r3303 - in trunk/src/host/qemu-neo1973: . darwin-user hw linux-user linux-user/alpha linux-user/arm linux-user/cris linux-user/i386 linux-user/m68k linux-user/mips linux-user/ppc linux-user/sh4 linux-user/sparc linux-user/sparc64 linux-user/x86_64 pc-bios slirp target-alpha target-arm target-cris target-i386 target-m68k target-mips target-ppc target-sh4 target-sparc tests

andrew at sita.openmoko.org andrew at sita.openmoko.org
Mon Oct 29 22:16:21 CET 2007


Author: andrew
Date: 2007-10-29 22:14:04 +0100 (Mon, 29 Oct 2007)
New Revision: 3303

Added:
   trunk/src/host/qemu-neo1973/cris-dis.c
   trunk/src/host/qemu-neo1973/host-utils.h
   trunk/src/host/qemu-neo1973/hw/ecc.c
   trunk/src/host/qemu-neo1973/hw/etraxfs.c
   trunk/src/host/qemu-neo1973/hw/etraxfs_ser.c
   trunk/src/host/qemu-neo1973/hw/etraxfs_timer.c
   trunk/src/host/qemu-neo1973/hw/mac_dbdma.c
   trunk/src/host/qemu-neo1973/hw/mac_nvram.c
   trunk/src/host/qemu-neo1973/hw/macio.c
   trunk/src/host/qemu-neo1973/hw/mips_mipssim.c
   trunk/src/host/qemu-neo1973/hw/mipsnet.c
   trunk/src/host/qemu-neo1973/hw/ppc4xx.h
   trunk/src/host/qemu-neo1973/hw/ppc4xx_devs.c
   trunk/src/host/qemu-neo1973/hw/ppc_mac.h
   trunk/src/host/qemu-neo1973/hw/ppc_oldworld.c
   trunk/src/host/qemu-neo1973/hw/r2d.c
   trunk/src/host/qemu-neo1973/hw/sh_intc.c
   trunk/src/host/qemu-neo1973/hw/sh_intc.h
   trunk/src/host/qemu-neo1973/hw/sh_serial.c
   trunk/src/host/qemu-neo1973/hw/sh_timer.c
   trunk/src/host/qemu-neo1973/hw/tsc210x.c
   trunk/src/host/qemu-neo1973/linux-user/alpha/target_signal.h
   trunk/src/host/qemu-neo1973/linux-user/arm/target_signal.h
   trunk/src/host/qemu-neo1973/linux-user/cris/
   trunk/src/host/qemu-neo1973/linux-user/cris/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/cris/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/cris/target_signal.h
   trunk/src/host/qemu-neo1973/linux-user/cris/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/elfload32.c
   trunk/src/host/qemu-neo1973/linux-user/i386/target_signal.h
   trunk/src/host/qemu-neo1973/linux-user/m68k/target_signal.h
   trunk/src/host/qemu-neo1973/linux-user/mips/target_signal.h
   trunk/src/host/qemu-neo1973/linux-user/ppc/target_signal.h
   trunk/src/host/qemu-neo1973/linux-user/sh4/target_signal.h
   trunk/src/host/qemu-neo1973/linux-user/sparc/target_signal.h
   trunk/src/host/qemu-neo1973/linux-user/sparc64/target_signal.h
   trunk/src/host/qemu-neo1973/linux-user/x86_64/target_signal.h
   trunk/src/host/qemu-neo1973/target-alpha/STATUS
   trunk/src/host/qemu-neo1973/target-cris/
   trunk/src/host/qemu-neo1973/target-cris/cpu.h
   trunk/src/host/qemu-neo1973/target-cris/crisv32-decode.h
   trunk/src/host/qemu-neo1973/target-cris/exec.h
   trunk/src/host/qemu-neo1973/target-cris/helper.c
   trunk/src/host/qemu-neo1973/target-cris/mmu.c
   trunk/src/host/qemu-neo1973/target-cris/mmu.h
   trunk/src/host/qemu-neo1973/target-cris/op.c
   trunk/src/host/qemu-neo1973/target-cris/op_helper.c
   trunk/src/host/qemu-neo1973/target-cris/op_mem.c
   trunk/src/host/qemu-neo1973/target-cris/op_template.h
   trunk/src/host/qemu-neo1973/target-cris/opcode-cris.h
   trunk/src/host/qemu-neo1973/target-cris/translate.c
   trunk/src/host/qemu-neo1973/target-i386/svm.h
   trunk/src/host/qemu-neo1973/target-ppc/helper_regs.h
Removed:
   trunk/src/host/qemu-neo1973/ecc.h
   trunk/src/host/qemu-neo1973/linux-user/ppc64/
   trunk/src/host/qemu-neo1973/target-mips/op_helper_mem.c
Modified:
   trunk/src/host/qemu-neo1973/Changelog
   trunk/src/host/qemu-neo1973/Makefile
   trunk/src/host/qemu-neo1973/Makefile.target
   trunk/src/host/qemu-neo1973/block-raw.c
   trunk/src/host/qemu-neo1973/block-vmdk.c
   trunk/src/host/qemu-neo1973/block-vvfat.c
   trunk/src/host/qemu-neo1973/configure
   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/darwin-user/main.c
   trunk/src/host/qemu-neo1973/dis-asm.h
   trunk/src/host/qemu-neo1973/disas.c
   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/gdbstub.c
   trunk/src/host/qemu-neo1973/host-utils.c
   trunk/src/host/qemu-neo1973/hw/acpi.c
   trunk/src/host/qemu-neo1973/hw/alpha_palcode.c
   trunk/src/host/qemu-neo1973/hw/apb_pci.c
   trunk/src/host/qemu-neo1973/hw/apic.c
   trunk/src/host/qemu-neo1973/hw/cs4231.c
   trunk/src/host/qemu-neo1973/hw/cuda.c
   trunk/src/host/qemu-neo1973/hw/esp.c
   trunk/src/host/qemu-neo1973/hw/grackle_pci.c
   trunk/src/host/qemu-neo1973/hw/gt64xxx.c
   trunk/src/host/qemu-neo1973/hw/heathrow_pic.c
   trunk/src/host/qemu-neo1973/hw/i8259.c
   trunk/src/host/qemu-neo1973/hw/iommu.c
   trunk/src/host/qemu-neo1973/hw/irq.c
   trunk/src/host/qemu-neo1973/hw/irq.h
   trunk/src/host/qemu-neo1973/hw/m48t59.c
   trunk/src/host/qemu-neo1973/hw/m48t59.h
   trunk/src/host/qemu-neo1973/hw/mips_malta.c
   trunk/src/host/qemu-neo1973/hw/mips_pica61.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/omap.c
   trunk/src/host/qemu-neo1973/hw/omap.h
   trunk/src/host/qemu-neo1973/hw/omap_mmc.c
   trunk/src/host/qemu-neo1973/hw/palm.c
   trunk/src/host/qemu-neo1973/hw/pc.c
   trunk/src/host/qemu-neo1973/hw/pckbd.c
   trunk/src/host/qemu-neo1973/hw/piix_pci.c
   trunk/src/host/qemu-neo1973/hw/pl110.c
   trunk/src/host/qemu-neo1973/hw/pl110_template.h
   trunk/src/host/qemu-neo1973/hw/ppc.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/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/pxa.h
   trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c
   trunk/src/host/qemu-neo1973/hw/sh7750.c
   trunk/src/host/qemu-neo1973/hw/sh7750_regnames.c
   trunk/src/host/qemu-neo1973/hw/sh7750_regs.h
   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/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/usb-uhci.c
   trunk/src/host/qemu-neo1973/hw/vmport.c
   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/arm/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/arm/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/arm/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/elfload.c
   trunk/src/host/qemu-neo1973/linux-user/flat.h
   trunk/src/host/qemu-neo1973/linux-user/flatload.c
   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/linuxload.c
   trunk/src/host/qemu-neo1973/linux-user/m68k/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/m68k/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/m68k/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/main.c
   trunk/src/host/qemu-neo1973/linux-user/mips/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/mips/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/mips/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/mmap.c
   trunk/src/host/qemu-neo1973/linux-user/ppc/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/ppc/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/sh4/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/signal.c
   trunk/src/host/qemu-neo1973/linux-user/sparc/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/sparc/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/sparc/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/sparc64/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/syscall.c
   trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h
   trunk/src/host/qemu-neo1973/linux-user/vm86.c
   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/loader.c
   trunk/src/host/qemu-neo1973/monitor.c
   trunk/src/host/qemu-neo1973/pc-bios/README
   trunk/src/host/qemu-neo1973/pc-bios/openbios-sparc32
   trunk/src/host/qemu-neo1973/pc-bios/ppc_rom.bin
   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/readline.c
   trunk/src/host/qemu-neo1973/slirp/bootp.c
   trunk/src/host/qemu-neo1973/slirp/debug.c
   trunk/src/host/qemu-neo1973/slirp/debug.h
   trunk/src/host/qemu-neo1973/slirp/icmp_var.h
   trunk/src/host/qemu-neo1973/slirp/if.c
   trunk/src/host/qemu-neo1973/slirp/if.h
   trunk/src/host/qemu-neo1973/slirp/ip.h
   trunk/src/host/qemu-neo1973/slirp/ip_icmp.c
   trunk/src/host/qemu-neo1973/slirp/ip_input.c
   trunk/src/host/qemu-neo1973/slirp/ip_output.c
   trunk/src/host/qemu-neo1973/slirp/libslirp.h
   trunk/src/host/qemu-neo1973/slirp/main.h
   trunk/src/host/qemu-neo1973/slirp/mbuf.c
   trunk/src/host/qemu-neo1973/slirp/mbuf.h
   trunk/src/host/qemu-neo1973/slirp/misc.c
   trunk/src/host/qemu-neo1973/slirp/misc.h
   trunk/src/host/qemu-neo1973/slirp/sbuf.c
   trunk/src/host/qemu-neo1973/slirp/sbuf.h
   trunk/src/host/qemu-neo1973/slirp/slirp.c
   trunk/src/host/qemu-neo1973/slirp/slirp.h
   trunk/src/host/qemu-neo1973/slirp/socket.c
   trunk/src/host/qemu-neo1973/slirp/socket.h
   trunk/src/host/qemu-neo1973/slirp/tcp.h
   trunk/src/host/qemu-neo1973/slirp/tcp_input.c
   trunk/src/host/qemu-neo1973/slirp/tcp_output.c
   trunk/src/host/qemu-neo1973/slirp/tcp_subr.c
   trunk/src/host/qemu-neo1973/slirp/tcp_timer.c
   trunk/src/host/qemu-neo1973/slirp/tcp_timer.h
   trunk/src/host/qemu-neo1973/slirp/tcp_var.h
   trunk/src/host/qemu-neo1973/slirp/tftp.c
   trunk/src/host/qemu-neo1973/slirp/udp.c
   trunk/src/host/qemu-neo1973/slirp/udp.h
   trunk/src/host/qemu-neo1973/softmmu_exec.h
   trunk/src/host/qemu-neo1973/softmmu_header.h
   trunk/src/host/qemu-neo1973/softmmu_template.h
   trunk/src/host/qemu-neo1973/sparc-dis.c
   trunk/src/host/qemu-neo1973/sparc.ld
   trunk/src/host/qemu-neo1973/sparc64.ld
   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_mem.h
   trunk/src/host/qemu-neo1973/target-alpha/translate.c
   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_helper.c
   trunk/src/host/qemu-neo1973/target-i386/cpu.h
   trunk/src/host/qemu-neo1973/target-i386/exec.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/translate.c
   trunk/src/host/qemu-neo1973/target-m68k/cpu.h
   trunk/src/host/qemu-neo1973/target-m68k/exec.h
   trunk/src/host/qemu-neo1973/target-m68k/helper.c
   trunk/src/host/qemu-neo1973/target-m68k/op_helper.c
   trunk/src/host/qemu-neo1973/target-mips/TODO
   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/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_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-mips/translate_init.c
   trunk/src/host/qemu-neo1973/target-ppc/STATUS
   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.h
   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/exec.h
   trunk/src/host/qemu-neo1973/target-sh4/helper.c
   trunk/src/host/qemu-neo1973/target-sh4/op_helper.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/helper.c
   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/op_mem.h
   trunk/src/host/qemu-neo1973/target-sparc/translate.c
   trunk/src/host/qemu-neo1973/tests/Makefile
   trunk/src/host/qemu-neo1973/thunk.c
   trunk/src/host/qemu-neo1973/thunk.h
   trunk/src/host/qemu-neo1973/usb-linux.c
   trunk/src/host/qemu-neo1973/vl.c
   trunk/src/host/qemu-neo1973/vl.h
   trunk/src/host/qemu-neo1973/vnc.c
Log:
Pull changes from cvs.savannah.nongnu.org.


Modified: trunk/src/host/qemu-neo1973/Changelog
===================================================================
--- trunk/src/host/qemu-neo1973/Changelog	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/Changelog	2007-10-29 21:14:04 UTC (rev 3303)
@@ -3,7 +3,7 @@
   - 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)
+  - Several Sparc fixes (Aurelien Jarno, Blue Swirl, Robert Reif)
   - MIPS 64-bit FPU support (Thiemo Seufer)
   - Xscale PDA emulation (Andrzei Zaborowski)
   - ColdFire system emulation (Paul Brook)
@@ -11,6 +11,9 @@
   - MIPS64 support (Aurelien Jarno, Thiemo Seufer)
   - Preliminary Alpha guest support (J. Mayer)
   - Read-only support for Parallels disk images (Alex Beregszaszi)
+  - SVM (x86 virtualization) support (Alexander Graf)
+  - CRIS emulation (Edgar E. Iglesias)
+  - SPARC32PLUS execution support (Blue Swirl)
 
 version 0.9.0:
 

Modified: trunk/src/host/qemu-neo1973/Makefile
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/Makefile	2007-10-29 21:14:04 UTC (rev 3303)
@@ -13,7 +13,6 @@
 
 CPPFLAGS += -I. -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
 LIBS=
-TOOLS=qemu-img$(EXESUF) raw2flash$(EXESUF) flash2raw$(EXESUF)
 ifdef CONFIG_STATIC
 BASE_LDFLAGS += -static
 endif
@@ -80,7 +79,9 @@
 
 install: all $(if $(BUILD_DOCS),install-doc)
 	mkdir -p "$(DESTDIR)$(bindir)"
+ifneq ($(TOOLS),)
 	$(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
+endif
 	mkdir -p "$(DESTDIR)$(datadir)"
 	for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
 		video.x openbios-sparc32 pxe-ne2k_pci.bin \
@@ -150,7 +151,7 @@
 
 # generate a binary distribution
 tarbin:
-	( cd / ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \
+	( cd / ; tar zcvf ~/qemu-$(VERSION)-$(ARCH).tar.gz \
 	$(bindir)/qemu \
 	$(bindir)/qemu-system-ppc \
 	$(bindir)/qemu-system-ppc64 \
@@ -162,6 +163,8 @@
 	$(bindir)/qemu-system-mips64 \
 	$(bindir)/qemu-system-mips64el \
 	$(bindir)/qemu-system-arm \
+	$(bindir)/qemu-system-m68k \
+	$(bindir)/qemu-system-sh4 \
 	$(bindir)/qemu-i386 \
         $(bindir)/qemu-arm \
         $(bindir)/qemu-armeb \
@@ -170,7 +173,13 @@
         $(bindir)/qemu-ppc64 \
         $(bindir)/qemu-mips \
         $(bindir)/qemu-mipsel \
+        $(bindir)/qemu-mipsn32 \
+        $(bindir)/qemu-mipsn32el \
+        $(bindir)/qemu-mips64 \
+        $(bindir)/qemu-mips64el \
         $(bindir)/qemu-alpha \
+        $(bindir)/qemu-m68k \
+        $(bindir)/qemu-sh4 \
         $(bindir)/qemu-img \
 	$(datadir)/bios.bin \
 	$(datadir)/vgabios.bin \

Modified: trunk/src/host/qemu-neo1973/Makefile.target
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile.target	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/Makefile.target	2007-10-29 21:14:04 UTC (rev 3303)
@@ -4,12 +4,18 @@
 ifeq ($(TARGET_ARCH), x86_64)
 TARGET_BASE_ARCH:=i386
 endif
+ifeq ($(TARGET_ARCH), mipsn32)
+TARGET_BASE_ARCH:=mips
+endif
 ifeq ($(TARGET_ARCH), mips64)
 TARGET_BASE_ARCH:=mips
 endif
 ifeq ($(TARGET_ARCH), ppc64)
 TARGET_BASE_ARCH:=ppc
 endif
+ifeq ($(TARGET_ARCH), ppc64h)
+TARGET_BASE_ARCH:=ppc
+endif
 ifeq ($(TARGET_ARCH), ppcemb)
 TARGET_BASE_ARCH:=ppc
 endif
@@ -18,15 +24,18 @@
 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)
+CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH) -MMD -MP
 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)
+ifndef TARGET_ABI_DIR
+  TARGET_ABI_DIR=$(TARGET_ARCH)
 endif
+CPPFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
+endif
 BASE_CFLAGS=
 BASE_LDFLAGS=
 #CFLAGS+=-Werror
@@ -50,11 +59,21 @@
     TARGET_ARCH2=mipsel
   endif
 endif
+ifeq ($(TARGET_ARCH),mipsn32)
+  ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
+    TARGET_ARCH2=mipsn32el
+  endif
+endif
 ifeq ($(TARGET_ARCH),mips64)
   ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
     TARGET_ARCH2=mips64el
   endif
 endif
+ifeq ($(TARGET_ARCH),sparc64)
+  ifeq ($(TARGET_ABI_DIR),sparc)
+    TARGET_ARCH2=sparc32plus
+  endif
+endif
 QEMU_USER=qemu-$(TARGET_ARCH2)
 # system emulator name
 ifdef CONFIG_SOFTMMU
@@ -246,6 +265,10 @@
 ifdef TARGET_HAS_BFLT
 OBJS+= flatload.o
 endif
+ifdef TARGET_HAS_ELFLOAD32
+OBJS+= elfload32.o
+elfload32.o: elfload.c
+endif
 
 ifeq ($(TARGET_ARCH), i386)
 OBJS+= vm86.o
@@ -269,7 +292,7 @@
 
 # cpu emulator library
 LIBOBJS=exec.o kqemu.o translate-op.o translate-all.o cpu-exec.o\
-        translate.o op.o
+        translate.o op.o host-utils.o
 ifdef CONFIG_SOFTFLOAT
 LIBOBJS+=fpu/softfloat.o
 else
@@ -316,6 +339,15 @@
 LIBOBJS+= op_helper.o helper.o alpha_palcode.o
 endif
 
+ifeq ($(TARGET_BASE_ARCH), cris)
+LIBOBJS+= op_helper.o helper.o
+LIBOBJS+= cris-dis.o
+
+ifndef CONFIG_USER_ONLY
+LIBOBJS+= mmu.o
+endif
+endif
+
 # NOTE: the disassembler code is only needed for debugging
 LIBOBJS+=disas.o
 ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
@@ -369,7 +401,6 @@
 # must use static linking to avoid leaving stuff in virtual address space
 VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o loader.o isa_mmio.o
 VL_OBJS+=cutils.o
-VL_OBJS+=host-utils.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 block-parallels.o
 VL_OBJS+=irq.o
@@ -446,20 +477,36 @@
 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 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 ppc405_uc.o ppc405_boards.o
 CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
+# shared objects
+VL_OBJS+= ppc.o ide.o vga.o $(SOUND_HW) dma.o openpic.o $(AUDIODRV)
+# PREP target
+VL_OBJS+= pckbd.o ps2.o serial.o i8259.o i8254.o fdc.o m48t59.o mc146818rtc.o
+VL_OBJS+= prep_pci.o ppc_prep.o
+# Mac shared devices
+VL_OBJS+= macio.o cuda.o adb.o mac_nvram.o mac_dbdma.o
+# OldWorld PowerMac
+VL_OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o
+# NewWorld PowerMac
+VL_OBJS+= unin_pci.o ppc_chrp.o
+# PowerPC 4xx boards
+VL_OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc405_uc.o ppc405_boards.o
 endif
 ifeq ($(TARGET_BASE_ARCH), mips)
-VL_OBJS+= mips_r4k.o mips_malta.o mips_pica61.o
+VL_OBJS+= mips_r4k.o mips_malta.o mips_pica61.o mips_mipssim.o
 VL_OBJS+= mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o
 VL_OBJS+= jazz_led.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 smbus_eeprom.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
+VL_OBJS+= mipsnet.o
 CPPFLAGS += -DHAS_AUDIO
 endif
+ifeq ($(TARGET_BASE_ARCH), cris)
+VL_OBJS+= etraxfs.o
+VL_OBJS+= ptimer.o
+VL_OBJS+= etraxfs_timer.o
+VL_OBJS+= etraxfs_ser.o
+endif
 ifeq ($(TARGET_BASE_ARCH), sparc)
 ifeq ($(TARGET_ARCH), sparc64)
 VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o
@@ -479,15 +526,17 @@
 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+= spitz.o ads7846.o ide.o serial.o nand.o $(AUDIODRV) wm8750.o wm8753.o
+VL_OBJS+= spitz.o ads7846.o ide.o serial.o nand.o ecc.o
+VL_OBJS+= $(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
 VL_OBJS+= $(GSM_OBJS) modem.o
-VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o palm.o
+VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o palm.o tsc210x.o
 CPPFLAGS+= -DHAS_AUDIO $(GSM_CPPFLAGS)
 endif
 ifeq ($(TARGET_BASE_ARCH), sh4)
-VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
+VL_OBJS+= shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
+VL_OBJS+= sh_timer.o ptimer.o sh_serial.o sh_intc.o
 endif
 ifeq ($(TARGET_BASE_ARCH), m68k)
 VL_OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
@@ -615,58 +664,6 @@
 signal.o: signal.c
 	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
 
-vga.o: pixel_ops.h
-
-tcx.o: pixel_ops.h
-
-ifeq ($(TARGET_BASE_ARCH), i386)
-op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h ops_sse.h
-endif
-
-ifeq ($(TARGET_ARCH), arm)
-op.o: op.c op_template.h
-pl110.o: pl110_template.h
-endif
-
-ifeq ($(TARGET_BASE_ARCH), sparc)
-helper.o: cpu.h exec-all.h
-op.o: op.c op_template.h op_mem.h fop_template.h fbranch_template.h exec.h cpu.h
-op_helper.o: exec.h softmmu_template.h cpu.h
-translate.o: cpu.h exec-all.h disas.h
-endif
-
-ifeq ($(TARGET_BASE_ARCH), ppc)
-op.o: op.c op_template.h op_mem.h
-op_helper.o: op_helper_mem.h
-translate.o: translate.c translate_init.c
-endif
-
-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 cpu.h
-op_helper.o: op_helper_mem.c exec.h softmmu_template.h cpu.h
-translate.o: translate_init.c exec-all.h disas.h
-endif
-
-loader.o: loader.c elf_ops.h
-
-ifeq ($(TARGET_ARCH), sh4)
-op.o: op.c op_mem.c cpu.h
-op_helper.o: op_helper.c exec.h cpu.h
-helper.o: helper.c exec.h cpu.h
-sh7750.o: sh7750.c sh7750_regs.h sh7750_regnames.h cpu.h
-shix.o: shix.c sh7750_regs.h sh7750_regnames.h
-sh7750_regnames.o: sh7750_regnames.c sh7750_regnames.h sh7750_regs.h
-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
 	$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
 
@@ -674,7 +671,8 @@
 	$(CC) $(CPPFLAGS) -c -o $@ $<
 
 clean:
-	rm -f *.o  *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o fpu/*.o
+	rm -f *.o *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o fpu/*.o
+	rm -f *.d */*.d
 
 install: all
 ifneq ($(PROGS),)
@@ -690,3 +688,6 @@
 fmodaudio.o alsaaudio.o mixeng.o sb16.o es1370.o gus.o adlib.o: \
 CFLAGS := $(CFLAGS) -Wall -Werror -W -Wsign-compare
 endif
+
+# Include automatically generated dependency files
+-include $(wildcard *.d */*.d)

Modified: trunk/src/host/qemu-neo1973/block-raw.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-raw.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/block-raw.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -151,7 +151,8 @@
     if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
         ++(s->lseek_err_cnt);
         if(s->lseek_err_cnt <= 10) {
-            DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] lseek failed : %d = %s\n",
+            DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
+                              "] lseek failed : %d = %s\n",
                               s->fd, bs->filename, offset, buf, count,
                               bs->total_sectors, errno, strerror(errno));
         }
@@ -163,7 +164,8 @@
     if (ret == count)
         goto label__raw_read__success;
 
-    DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] read failed %d : %d = %s\n",
+    DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
+                      "] read failed %d : %d = %s\n",
                       s->fd, bs->filename, offset, buf, count,
                       bs->total_sectors, ret, errno, strerror(errno));
 
@@ -178,7 +180,8 @@
         if (ret == count)
             goto label__raw_read__success;
 
-        DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] retry read failed %d : %d = %s\n",
+        DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
+                          "] retry read failed %d : %d = %s\n",
                           s->fd, bs->filename, offset, buf, count,
                           bs->total_sectors, ret, errno, strerror(errno));
     }
@@ -201,7 +204,8 @@
     if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
         ++(s->lseek_err_cnt);
         if(s->lseek_err_cnt) {
-            DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %lld, %p, %d) [%lld] lseek failed : %d = %s\n",
+            DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
+                              PRId64 "] lseek failed : %d = %s\n",
                               s->fd, bs->filename, offset, buf, count,
                               bs->total_sectors, errno, strerror(errno));
         }
@@ -213,7 +217,8 @@
     if (ret == count)
         goto label__raw_write__success;
 
-    DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %lld, %p, %d) [%lld] write failed %d : %d = %s\n",
+    DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
+                      "] write failed %d : %d = %s\n",
                       s->fd, bs->filename, offset, buf, count,
                       bs->total_sectors, ret, errno, strerror(errno));
 
@@ -1169,7 +1174,7 @@
     BDRVRawState *s = bs->opaque;
     LARGE_INTEGER l;
     ULARGE_INTEGER available, total, total_free;
-    DISK_GEOMETRY dg;
+    DISK_GEOMETRY_EX dg;
     DWORD count;
     BOOL status;
 
@@ -1185,11 +1190,10 @@
         l.QuadPart = total.QuadPart;
         break;
     case FTYPE_HARDDISK:
-        status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY,
+        status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
                                  NULL, 0, &dg, sizeof(dg), &count, NULL);
-        if (status != FALSE) {
-            l.QuadPart = dg.Cylinders.QuadPart * dg.TracksPerCylinder
-                * dg.SectorsPerTrack * dg.BytesPerSector;
+        if (status != 0) {
+            l = dg.DiskSize;
         }
         break;
     default:

Modified: trunk/src/host/qemu-neo1973/block-vmdk.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-vmdk.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/block-vmdk.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -659,7 +659,8 @@
 
     if (sector_num > bs->total_sectors) {
         fprintf(stderr,
-                "(VMDK) Wrong offset: sector_num=0x%llx total_sectors=0x%llx\n",
+                "(VMDK) Wrong offset: sector_num=0x%" PRIx64
+                " total_sectors=0x%" PRIx64 "\n",
                 sector_num, bs->total_sectors);
         return -1;
     }

Modified: trunk/src/host/qemu-neo1973/block-vvfat.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-vvfat.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/block-vvfat.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -242,21 +242,25 @@
     uint8_t magic[2];
 } __attribute__((packed)) bootsector_t;
 
+typedef struct {
+    uint8_t head;
+    uint8_t sector;
+    uint8_t cylinder;
+} mbr_chs_t;
+
 typedef struct partition_t {
     uint8_t attributes; /* 0x80 = bootable */
-    uint8_t start_head;
-    uint8_t start_sector;
-    uint8_t start_cylinder;
-    uint8_t fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xb = FAT32 */
-    uint8_t end_head;
-    uint8_t end_sector;
-    uint8_t end_cylinder;
+    mbr_chs_t start_CHS;
+    uint8_t   fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */
+    mbr_chs_t end_CHS;
     uint32_t start_sector_long;
-    uint32_t end_sector_long;
+    uint32_t length_sector_long;
 } __attribute__((packed)) partition_t;
 
 typedef struct mbr_t {
-    uint8_t ignored[0x1be];
+    uint8_t ignored[0x1b8];
+    uint32_t nt_id;
+    uint8_t ignored2[2];
     partition_t partition[4];
     uint8_t magic[2];
 } __attribute__((packed)) mbr_t;
@@ -350,26 +354,57 @@
     int downcase_short_names;
 } BDRVVVFATState;
 
+/* take the sector position spos and convert it to Cylinder/Head/Sector position
+ * if the position is outside the specified geometry, fill maximum value for CHS
+ * and return 1 to signal overflow.
+ */
+static int sector2CHS(BlockDriverState* bs, mbr_chs_t * chs, int spos){
+    int head,sector;
+    sector   = spos % (bs->secs);  spos/= bs->secs;
+    head     = spos % (bs->heads); spos/= bs->heads;
+    if(spos >= bs->cyls){
+        /* Overflow,
+        it happens if 32bit sector positions are used, while CHS is only 24bit.
+        Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
+        chs->head     = 0xFF;
+        chs->sector   = 0xFF;
+        chs->cylinder = 0xFF;
+        return 1;
+    }
+    chs->head     = (uint8_t)head;
+    chs->sector   = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
+    chs->cylinder = (uint8_t)spos;
+    return 0;
+}
 
 static void init_mbr(BDRVVVFATState* s)
 {
     /* TODO: if the files mbr.img and bootsect.img exist, use them */
     mbr_t* real_mbr=(mbr_t*)s->first_sectors;
     partition_t* partition=&(real_mbr->partition[0]);
+    int lba;
 
     memset(s->first_sectors,0,512);
 
+    /* Win NT Disk Signature */
+    real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
+
     partition->attributes=0x80; /* bootable */
-    partition->start_head=1;
-    partition->start_sector=1;
-    partition->start_cylinder=0;
+
+    /* LBA is used when partition is outside the CHS geometry */
+    lba = sector2CHS(s->bs, &partition->start_CHS, s->first_sectors_number-1);
+    lba|= sector2CHS(s->bs, &partition->end_CHS,   s->sector_count);
+
+    /*LBA partitions are identified only by start/length_sector_long not by CHS*/
+    partition->start_sector_long =cpu_to_le32(s->first_sectors_number-1);
+    partition->length_sector_long=cpu_to_le32(s->sector_count - s->first_sectors_number+1);
+
     /* FAT12/FAT16/FAT32 */
-    partition->fs_type=(s->fat_type==12?0x1:s->fat_type==16?0x6:0xb);
-    partition->end_head=s->bs->heads-1;
-    partition->end_sector=0xff; /* end sector & upper 2 bits of cylinder */;
-    partition->end_cylinder=0xff; /* lower 8 bits of end cylinder */;
-    partition->start_sector_long=cpu_to_le32(s->bs->secs);
-    partition->end_sector_long=cpu_to_le32(s->sector_count);
+    /* DOS uses different types when partition is LBA,
+       probably to prevent older versions from using CHS on them */
+    partition->fs_type= s->fat_type==12 ? 0x1:
+                        s->fat_type==16 ? (lba?0xe:0x06):
+                         /*fat_tyoe==32*/ (lba?0xc:0x0b);
 
     real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
 }
@@ -973,10 +1008,9 @@
 
     s->fat_type=16;
     /* LATER TODO: if FAT32, adjust */
-    s->sector_count=0xec04f;
     s->sectors_per_cluster=0x10;
-    /* LATER TODO: this could be wrong for FAT32 */
-    bs->cyls=1023; bs->heads=15; bs->secs=63;
+    /* 504MB disk*/
+    bs->cyls=1024; bs->heads=16; bs->secs=63;
 
     s->current_cluster=0xffffffff;
 
@@ -991,12 +1025,6 @@
     if (!strstart(dirname, "fat:", NULL))
 	return -1;
 
-    if (strstr(dirname, ":rw:")) {
-	if (enable_write_target(s))
-	    return -1;
-	bs->read_only = 0;
-    }
-
     if (strstr(dirname, ":floppy:")) {
 	floppy = 1;
 	s->fat_type = 12;
@@ -1005,6 +1033,8 @@
 	bs->cyls = 80; bs->heads = 2; bs->secs = 36;
     }
 
+    s->sector_count=bs->cyls*bs->heads*bs->secs;
+
     if (strstr(dirname, ":32:")) {
 	fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
 	s->fat_type = 32;
@@ -1015,6 +1045,12 @@
 	s->sector_count=2880;
     }
 
+    if (strstr(dirname, ":rw:")) {
+	if (enable_write_target(s))
+	    return -1;
+	bs->read_only = 0;
+    }
+
     i = strrchr(dirname, ':') - dirname;
     assert(i >= 3);
     if (dirname[i-2] == ':' && isalpha(dirname[i-1]))
@@ -1024,11 +1060,12 @@
 	dirname += i+1;
 
     bs->total_sectors=bs->cyls*bs->heads*bs->secs;
-    if (s->sector_count > bs->total_sectors)
-	s->sector_count = bs->total_sectors;
+
     if(init_directories(s, dirname))
 	return -1;
 
+    s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
+
     if(s->first_sectors_number==0x40)
 	init_mbr(s);
 

Modified: trunk/src/host/qemu-neo1973/configure
===================================================================
--- trunk/src/host/qemu-neo1973/configure	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/configure	2007-10-29 21:14:04 UTC (rev 3303)
@@ -53,6 +53,9 @@
   mips64)
     cpu="mips64"
   ;;
+  cris)
+    cpu="cris"
+  ;;
   s390*)
     cpu="s390"
   ;;
@@ -501,11 +504,11 @@
 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 mips64-softmmu mips64el-softmmu arm-softmmu ppc64-softmmu ppcemb-softmmu m68k-softmmu"
+        target_list="i386-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc-softmmu ppcemb-softmmu ppc64-softmmu m68k-softmmu sh4-softmmu cris-softmmu"
     fi
 # the following are Linux specific
     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"
+        target_list="i386-linux-user arm-linux-user armeb-linux-user sparc-linux-user sparc64-linux-user sparc32plus-linux-user mips-linux-user mipsel-linux-user m68k-linux-user alpha-linux-user sh4-linux-user ppc-linux-user ppcemb-linux-user ppc64-linux-user ppc64abi32-linux-user x86_64-linux-user cris-linux-user $target_list"
     fi
 # the following are Darwin specific
     if [ "$darwin_user" = "yes" ] ; then
@@ -826,6 +829,9 @@
 elif test "$cpu" = "mips64" ; then
   echo "ARCH=mips64" >> $config_mak
   echo "#define HOST_MIPS64 1" >> $config_h
+elif test "$cpu" = "cris" ; then
+  echo "ARCH=cris" >> $config_mak
+  echo "#define HOST_CRIS 1" >> $config_h
 elif test "$cpu" = "s390" ; then
   echo "ARCH=s390" >> $config_mak
   echo "#define HOST_S390 1" >> $config_h
@@ -967,6 +973,12 @@
   echo "#define INTERNAL_MODEM \"gnokiigsm\"" >> $config_h
 fi
 
+if test `expr "$target_list" : ".*softmmu.*"` != 0 ; then
+  tools="raw2flash\$(EXESUF) flash2raw\$(EXESUF) $tools"
+  tools="qemu-img\$(EXESUF) $tools"
+fi
+echo "TOOLS=$tools" >> $config_mak
+
 test -f ${config_h}~ && cmp -s $config_h ${config_h}~ && mv ${config_h}~ $config_h
 
 for target in $target_list; do
@@ -978,10 +990,14 @@
 [ "$target_cpu" = "armeb" ] && target_bigendian=yes
 [ "$target_cpu" = "sparc" ] && target_bigendian=yes
 [ "$target_cpu" = "sparc64" ] && target_bigendian=yes
+[ "$target_cpu" = "sparc32plus" ] && target_bigendian=yes
 [ "$target_cpu" = "ppc" ] && target_bigendian=yes
+[ "$target_cpu" = "ppcemb" ] && target_bigendian=yes
 [ "$target_cpu" = "ppc64" ] && target_bigendian=yes
-[ "$target_cpu" = "ppcemb" ] && target_bigendian=yes
+[ "$target_cpu" = "ppc64abi32" ] && target_bigendian=yes
+[ "$target_cpu" = "ppc64h" ] && target_bigendian=yes
 [ "$target_cpu" = "mips" ] && target_bigendian=yes
+[ "$target_cpu" = "mipsn32" ] && target_bigendian=yes
 [ "$target_cpu" = "mips64" ] && target_bigendian=yes
 [ "$target_cpu" = "sh4eb" ] && target_bigendian=yes
 [ "$target_cpu" = "m68k" ] && target_bigendian=yes
@@ -1046,6 +1062,7 @@
 echo "#include \"../config-host.h\"" >> $config_h
 
 bflt="no"
+elfload32="no"
 interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
 echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
 
@@ -1070,20 +1087,44 @@
   echo "#define TARGET_ARCH \"sparc64\"" >> $config_h
   echo "#define TARGET_SPARC 1" >> $config_h
   echo "#define TARGET_SPARC64 1" >> $config_h
+  elfload32="yes"
+elif test "$target_cpu" = "sparc32plus" ; then
+  echo "TARGET_ARCH=sparc64" >> $config_mak
+  echo "TARGET_ABI_DIR=sparc" >> $config_mak
+  echo "#define TARGET_ARCH \"sparc64\"" >> $config_h
+  echo "#define TARGET_SPARC 1" >> $config_h
+  echo "#define TARGET_SPARC64 1" >> $config_h
+  echo "#define TARGET_ABI32 1" >> $config_h
 elif test "$target_cpu" = "ppc" ; then
   echo "TARGET_ARCH=ppc" >> $config_mak
   echo "#define TARGET_ARCH \"ppc\"" >> $config_h
   echo "#define TARGET_PPC 1" >> $config_h
+elif test "$target_cpu" = "ppcemb" ; then
+  echo "TARGET_ARCH=ppcemb" >> $config_mak
+  echo "TARGET_ABI_DIR=ppc" >> $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" = "ppc64" ; then
   echo "TARGET_ARCH=ppc64" >> $config_mak
   echo "#define TARGET_ARCH \"ppc64\"" >> $config_h
+  echo "TARGET_ABI_DIR=ppc" >> $config_mak
   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
+elif test "$target_cpu" = "ppc64abi32" ; then
+  echo "TARGET_ARCH=ppc64" >> $config_mak
+  echo "#define TARGET_ARCH \"ppc64\"" >> $config_h
+  echo "TARGET_ABI_DIR=ppc" >> $config_mak
   echo "#define TARGET_PPC 1" >> $config_h
-  echo "#define TARGET_PPCEMB 1" >> $config_h
+  echo "#define TARGET_PPC64 1" >> $config_h
+  echo "#define TARGET_ABI32 1" >> $config_h
+elif test "$target_cpu" = "ppc64h" ; then
+  echo "TARGET_ARCH=ppc64h" >> $config_mak
+  echo "#define TARGET_ARCH \"ppc64h\"" >> $config_h
+  echo "TARGET_ABI_DIR=ppc" >> $config_mak
+  echo "#define TARGET_PPC 1" >> $config_h
+  echo "#define TARGET_PPC64 1" >> $config_h
+  echo "#define TARGET_PPC64H 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
@@ -1096,13 +1137,20 @@
   echo "TARGET_ARCH=mips" >> $config_mak
   echo "#define TARGET_ARCH \"mips\"" >> $config_h
   echo "#define TARGET_MIPS 1" >> $config_h
-  echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
-  echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
+elif test "$target_cpu" = "mipsn32" -o "$target_cpu" = "mipsn32el" ; then
+  echo "TARGET_ARCH=mipsn32" >> $config_mak
+  echo "#define TARGET_ARCH \"mipsn32\"" >> $config_h
+  echo "#define TARGET_MIPS 1" >> $config_h
+  echo "#define TARGET_MIPSN32 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
+elif test "$target_cpu" = "cris" ; then
+  echo "TARGET_ARCH=cris" >> $config_mak
+  echo "#define TARGET_ARCH \"cris\"" >> $config_h
+  echo "#define TARGET_CRIS 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
@@ -1144,7 +1192,7 @@
   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
+if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64"  -o "$target_cpu" = "sparc32plus" -o "$target_cpu" = "m68k" -o "$target_cpu" = "mips" -o "$target_cpu" = "mipsel" -o "$target_cpu" = "mipsn32" -o "$target_cpu" = "mipsn32el" -o "$target_cpu" = "mips64" -o "$target_cpu" = "mips64el"; then
   echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
   echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
 fi
@@ -1152,6 +1200,11 @@
   echo "TARGET_HAS_BFLT=yes" >> $config_mak
   echo "#define TARGET_HAS_BFLT 1" >> $config_h
 fi
+# 32 bit ELF loader in addition to native 64 bit loader?
+if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then
+  echo "TARGET_HAS_ELFLOAD32=yes" >> $config_mak
+  echo "#define TARGET_HAS_ELFLOAD32 1" >> $config_h
+fi
 # sdl defines
 
 if test "$target_user_only" = "no"; then
@@ -1187,8 +1240,9 @@
 
 # build tree in object directory if source path is different from current one
 if test "$source_path_used" = "yes" ; then
-    DIRS="tests"
+    DIRS="tests tests/cris"
     FILES="Makefile tests/Makefile"
+    FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
     for dir in $DIRS ; do
             mkdir -p $dir
     done

Modified: trunk/src/host/qemu-neo1973/cpu-all.h
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-all.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/cpu-all.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -716,6 +716,7 @@
 #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.  */
+#define CPU_INTERRUPT_VIRQ   0x100 /* virtual interrupt pending.  */
 
 void cpu_interrupt(CPUState *s, int mask);
 void cpu_reset_interrupt(CPUState *env, int mask);

Modified: trunk/src/host/qemu-neo1973/cpu-defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-defs.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/cpu-defs.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -112,15 +112,6 @@
     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 */                                              \
@@ -131,7 +122,7 @@
                                    written */                           \
     target_ulong mem_write_vaddr; /* target virtual addr at which the   \
                                      memory was written */              \
-    /* 0 = kernel, 1 = user */                                          \
+    /* The meaning of the MMU modes is defined in the target code. */   \
     CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE];                  \
     struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];           \
                                                                         \

Modified: trunk/src/host/qemu-neo1973/cpu-exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-exec.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/cpu-exec.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -77,7 +77,7 @@
 
 static TranslationBlock *tb_find_slow(target_ulong pc,
                                       target_ulong cs_base,
-                                      unsigned int flags)
+                                      uint64_t flags)
 {
     TranslationBlock *tb, **ptb1;
     int code_gen_size;
@@ -155,7 +155,7 @@
 {
     TranslationBlock *tb;
     target_ulong cs_base, pc;
-    unsigned int flags;
+    uint64_t flags;
 
     /* we record a subset of the CPU state. It will
        always be the same before a given translated block
@@ -163,6 +163,7 @@
 #if defined(TARGET_I386)
     flags = env->hflags;
     flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
+    flags |= env->intercept;
     cs_base = env->segs[R_CS].base;
     pc = cs_base + env->eip;
 #elif defined(TARGET_ARM)
@@ -180,8 +181,9 @@
     flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
         | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
 #else
-    // FPU enable . MMU enabled . MMU no-fault . Supervisor
-    flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
+    // FPU enable . MMU Boot . MMU enabled . MMU no-fault . Supervisor
+    flags = (env->psref << 4) | (((env->mmuregs[0] & MMU_BM) >> 14) << 3)
+        | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
         | env->psrs;
 #endif
     cs_base = env->npc;
@@ -208,6 +210,10 @@
     flags = env->ps;
     cs_base = 0;
     pc = env->pc;
+#elif defined(TARGET_CRIS)
+    flags = 0;
+    cs_base = 0;
+    pc = env->pc;
 #else
 #error unsupported CPU
 #endif
@@ -282,6 +288,7 @@
 #elif defined(TARGET_PPC)
 #elif defined(TARGET_MIPS)
 #elif defined(TARGET_SH4)
+#elif defined(TARGET_CRIS)
     /* XXXXX */
 #else
 #error unsupported target CPU
@@ -333,6 +340,8 @@
 		    do_interrupt(env);
 #elif defined(TARGET_ALPHA)
                     do_interrupt(env);
+#elif defined(TARGET_CRIS)
+                    do_interrupt(env);
 #elif defined(TARGET_M68K)
                     do_interrupt(0);
 #endif
@@ -372,14 +381,18 @@
                 tmp_T0 = T0;
 #endif
                 interrupt_request = env->interrupt_request;
-                if (__builtin_expect(interrupt_request, 0)) {
+                if (__builtin_expect(interrupt_request, 0)
+#if defined(TARGET_I386)
+			&& env->hflags & HF_GIF_MASK
+#endif
+				) {
                     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)
+    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
                     if (interrupt_request & CPU_INTERRUPT_HALT) {
                         env->interrupt_request &= ~CPU_INTERRUPT_HALT;
                         env->halted = 1;
@@ -390,6 +403,7 @@
 #if defined(TARGET_I386)
                     if ((interrupt_request & CPU_INTERRUPT_SMI) &&
                         !(env->hflags & HF_SMM_MASK)) {
+                        svm_check_intercept(SVM_EXIT_SMI);
                         env->interrupt_request &= ~CPU_INTERRUPT_SMI;
                         do_smm_enter();
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
@@ -398,10 +412,11 @@
                         T0 = 0;
 #endif
                     } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
-                        (env->eflags & IF_MASK) &&
+                        (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
                         !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
                         int intno;
-                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+                        svm_check_intercept(SVM_EXIT_INTR);
+                        env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
                         intno = cpu_get_pic_interrupt(env);
                         if (loglevel & CPU_LOG_TB_IN_ASM) {
                             fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
@@ -414,6 +429,25 @@
 #else
                         T0 = 0;
 #endif
+#if !defined(CONFIG_USER_ONLY)
+                    } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
+                        (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
+                         int intno;
+                         /* FIXME: this should respect TPR */
+                         env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+                         svm_check_intercept(SVM_EXIT_VINTR);
+                         intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
+                         if (loglevel & CPU_LOG_TB_IN_ASM)
+                             fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
+	                 do_interrupt(intno, 0, 0, -1, 1);
+                         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
+                                  ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
+                         tmp_T0 = 0;
+#else
+                         T0 = 0;
+#endif
+#endif
                     }
 #elif defined(TARGET_PPC)
 #if 0
@@ -490,6 +524,11 @@
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                         do_interrupt(env);
                     }
+#elif defined(TARGET_CRIS)
+                    if (interrupt_request & CPU_INTERRUPT_HARD) {
+                        do_interrupt(env);
+			env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+                    }
 #elif defined(TARGET_M68K)
                     if (interrupt_request & CPU_INTERRUPT_HARD
                         && ((env->sr & SR_I) >> SR_I_SHIFT)
@@ -549,6 +588,8 @@
 		    cpu_dump_state(env, logfile, fprintf, 0);
 #elif defined(TARGET_ALPHA)
                     cpu_dump_state(env, logfile, fprintf, 0);
+#elif defined(TARGET_CRIS)
+                    cpu_dump_state(env, logfile, fprintf, 0);
 #else
 #error unsupported target CPU
 #endif
@@ -742,6 +783,7 @@
 #elif defined(TARGET_MIPS)
 #elif defined(TARGET_SH4)
 #elif defined(TARGET_ALPHA)
+#elif defined(TARGET_CRIS)
     /* XXXXX */
 #else
 #error unsupported target CPU
@@ -842,8 +884,7 @@
     }
 
     /* see if it is an MMU fault */
-    ret = cpu_x86_handle_mmu_fault(env, address, is_write,
-                                   ((env->hflags & HF_CPL_MASK) == 3), 0);
+    ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
     if (ret < 0)
         return 0; /* not an MMU fault */
     if (ret == 0)
@@ -892,7 +933,7 @@
         return 1;
     }
     /* see if it is an MMU fault */
-    ret = cpu_arm_handle_mmu_fault(env, address, is_write, 1, 0);
+    ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
     if (ret < 0)
         return 0; /* not an MMU fault */
     if (ret == 0)
@@ -928,7 +969,7 @@
         return 1;
     }
     /* see if it is an MMU fault */
-    ret = cpu_sparc_handle_mmu_fault(env, address, is_write, 1, 0);
+    ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
     if (ret < 0)
         return 0; /* not an MMU fault */
     if (ret == 0)
@@ -965,7 +1006,7 @@
     }
 
     /* see if it is an MMU fault */
-    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
+    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
     if (ret < 0)
         return 0; /* not an MMU fault */
     if (ret == 0)
@@ -1014,7 +1055,7 @@
         return 1;
     }
     /* see if it is an MMU fault */
-    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, 1, 0);
+    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
     if (ret < 0)
         return 0; /* not an MMU fault */
     if (ret == 0)
@@ -1054,7 +1095,7 @@
     }
 
     /* see if it is an MMU fault */
-    ret = cpu_mips_handle_mmu_fault(env, address, is_write, 1, 0);
+    ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
     if (ret < 0)
         return 0; /* not an MMU fault */
     if (ret == 0)
@@ -1104,7 +1145,7 @@
     }
 
     /* see if it is an MMU fault */
-    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, 1, 0);
+    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
     if (ret < 0)
         return 0; /* not an MMU fault */
     if (ret == 0)
@@ -1149,7 +1190,7 @@
     }
 
     /* see if it is an MMU fault */
-    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, 1, 0);
+    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
     if (ret < 0)
         return 0; /* not an MMU fault */
     if (ret == 0)
@@ -1173,6 +1214,51 @@
     /* never comes here */
     return 1;
 }
+#elif defined (TARGET_CRIS)
+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_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 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

Added: trunk/src/host/qemu-neo1973/cris-dis.c
===================================================================
--- trunk/src/host/qemu-neo1973/cris-dis.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/cris-dis.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,2907 @@
+/* Disassembler code for CRIS.
+   Copyright 2000, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Contributed by Axis Communications AB, Lund, Sweden.
+   Written by Hans-Peter Nilsson.
+
+   This file is part of the GNU binutils and GDB, the GNU debugger.
+
+   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, 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.  */
+
+#include "dis-asm.h"
+//#include "sysdep.h"
+#include "target-cris/opcode-cris.h"
+//#include "libiberty.h"
+
+
+#define FALSE 0
+#define TRUE 1
+#define CONST_STRNEQ(STR1,STR2) (strncmp ((STR1), (STR2), sizeof (STR2) - 1) == 0)
+
+/* cris-opc.c -- Table of opcodes for the CRIS processor.
+   Copyright 2000, 2001, 2004 Free Software Foundation, Inc.
+   Contributed by Axis Communications AB, Lund, Sweden.
+   Originally written for GAS 1.38.1 by Mikael Asker.
+   Reorganized by Hans-Peter Nilsson.
+
+This file is part of GAS, GDB and the GNU binutils.
+
+GAS, GDB, and GNU binutils 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, or (at your
+option) any later version.
+
+GAS, GDB, and GNU binutils are distributed in the hope that they 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 NULL
+#define NULL (0)
+#endif
+
+/* This table isn't used for CRISv32 and the size of immediate operands.  */
+const struct cris_spec_reg
+cris_spec_regs[] =
+{
+  {"bz",  0,  1, cris_ver_v32p,	   NULL},
+  {"p0",  0,  1, 0,		   NULL},
+  {"vr",  1,  1, 0,		   NULL},
+  {"p1",  1,  1, 0,		   NULL},
+  {"pid", 2,  1, cris_ver_v32p,    NULL},
+  {"p2",  2,  1, cris_ver_v32p,	   NULL},
+  {"p2",  2,  1, cris_ver_warning, NULL},
+  {"srs", 3,  1, cris_ver_v32p,    NULL},
+  {"p3",  3,  1, cris_ver_v32p,	   NULL},
+  {"p3",  3,  1, cris_ver_warning, NULL},
+  {"wz",  4,  2, cris_ver_v32p,	   NULL},
+  {"p4",  4,  2, 0,		   NULL},
+  {"ccr", 5,  2, cris_ver_v0_10,   NULL},
+  {"exs", 5,  4, cris_ver_v32p,	   NULL},
+  {"p5",  5,  2, cris_ver_v0_10,   NULL},
+  {"p5",  5,  4, cris_ver_v32p,	   NULL},
+  {"dcr0",6,  2, cris_ver_v0_3,	   NULL},
+  {"eda", 6,  4, cris_ver_v32p,	   NULL},
+  {"p6",  6,  2, cris_ver_v0_3,	   NULL},
+  {"p6",  6,  4, cris_ver_v32p,	   NULL},
+  {"dcr1/mof", 7, 4, cris_ver_v10p,
+   "Register `dcr1/mof' with ambiguous size specified.  Guessing 4 bytes"},
+  {"dcr1/mof", 7, 2, cris_ver_v0_3,
+   "Register `dcr1/mof' with ambiguous size specified.  Guessing 2 bytes"},
+  {"mof", 7,  4, cris_ver_v10p,	   NULL},
+  {"dcr1",7,  2, cris_ver_v0_3,	   NULL},
+  {"p7",  7,  4, cris_ver_v10p,	   NULL},
+  {"p7",  7,  2, cris_ver_v0_3,	   NULL},
+  {"dz",  8,  4, cris_ver_v32p,	   NULL},
+  {"p8",  8,  4, 0,		   NULL},
+  {"ibr", 9,  4, cris_ver_v0_10,   NULL},
+  {"ebp", 9,  4, cris_ver_v32p,	   NULL},
+  {"p9",  9,  4, 0,		   NULL},
+  {"irp", 10, 4, cris_ver_v0_10,   NULL},
+  {"erp", 10, 4, cris_ver_v32p,	   NULL},
+  {"p10", 10, 4, 0,		   NULL},
+  {"srp", 11, 4, 0,		   NULL},
+  {"p11", 11, 4, 0,		   NULL},
+  /* For disassembly use only.  Accept at assembly with a warning.  */
+  {"bar/dtp0", 12, 4, cris_ver_warning,
+   "Ambiguous register `bar/dtp0' specified"},
+  {"nrp", 12, 4, cris_ver_v32p,	   NULL},
+  {"bar", 12, 4, cris_ver_v8_10,   NULL},
+  {"dtp0",12, 4, cris_ver_v0_3,	   NULL},
+  {"p12", 12, 4, 0,		   NULL},
+  /* For disassembly use only.  Accept at assembly with a warning.  */
+  {"dccr/dtp1",13, 4, cris_ver_warning,
+   "Ambiguous register `dccr/dtp1' specified"},
+  {"ccs", 13, 4, cris_ver_v32p,	   NULL},
+  {"dccr",13, 4, cris_ver_v8_10,   NULL},
+  {"dtp1",13, 4, cris_ver_v0_3,	   NULL},
+  {"p13", 13, 4, 0,		   NULL},
+  {"brp", 14, 4, cris_ver_v3_10,   NULL},
+  {"usp", 14, 4, cris_ver_v32p,	   NULL},
+  {"p14", 14, 4, cris_ver_v3p,	   NULL},
+  {"usp", 15, 4, cris_ver_v10,	   NULL},
+  {"spc", 15, 4, cris_ver_v32p,	   NULL},
+  {"p15", 15, 4, cris_ver_v10p,	   NULL},
+  {NULL, 0, 0, cris_ver_version_all, NULL}
+};
+
+/* Add version specifiers to this table when necessary.
+   The (now) regular coding of register names suggests a simpler
+   implementation.  */
+const struct cris_support_reg cris_support_regs[] =
+{
+  {"s0", 0},
+  {"s1", 1},
+  {"s2", 2},
+  {"s3", 3},
+  {"s4", 4},
+  {"s5", 5},
+  {"s6", 6},
+  {"s7", 7},
+  {"s8", 8},
+  {"s9", 9},
+  {"s10", 10},
+  {"s11", 11},
+  {"s12", 12},
+  {"s13", 13},
+  {"s14", 14},
+  {"s15", 15},
+  {NULL, 0}
+};
+
+/* All CRIS opcodes are 16 bits.
+
+   - The match component is a mask saying which bits must match a
+     particular opcode in order for an instruction to be an instance
+     of that opcode.
+
+   - The args component is a string containing characters symbolically
+     matching the operands of an instruction.  Used for both assembly
+     and disassembly.
+
+     Operand-matching characters:
+     [ ] , space
+        Verbatim.
+     A	The string "ACR" (case-insensitive).
+     B	Not really an operand.  It causes a "BDAP -size,SP" prefix to be
+	output for the PUSH alias-instructions and recognizes a push-
+	prefix at disassembly.  This letter isn't recognized for v32.
+	Must be followed by a R or P letter.
+     !	Non-match pattern, will not match if there's a prefix insn.
+     b	Non-matching operand, used for branches with 16-bit
+	displacement. Only recognized by the disassembler.
+     c	5-bit unsigned immediate in bits <4:0>.
+     C	4-bit unsigned immediate in bits <3:0>.
+     d  At assembly, optionally (as in put other cases before this one)
+	".d" or ".D" at the start of the operands, followed by one space
+	character.  At disassembly, nothing.
+     D	General register in bits <15:12> and <3:0>.
+     f	List of flags in bits <15:12> and <3:0>.
+     i	6-bit signed immediate in bits <5:0>.
+     I	6-bit unsigned immediate in bits <5:0>.
+     M	Size modifier (B, W or D) for CLEAR instructions.
+     m	Size modifier (B, W or D) in bits <5:4>
+     N  A 32-bit dword, like in the difference between s and y.
+        This has no effect on bits in the opcode.  Can also be expressed
+	as "[pc+]" in input.
+     n  As N, but PC-relative (to the start of the instruction).
+     o	[-128..127] word offset in bits <7:1> and <0>.  Used by 8-bit
+	branch instructions.
+     O	[-128..127] offset in bits <7:0>.  Also matches a comma and a
+	general register after the expression, in bits <15:12>.  Used
+	only for the BDAP prefix insn (in v32 the ADDOQ insn; same opcode).
+     P	Special register in bits <15:12>.
+     p	Indicates that the insn is a prefix insn.  Must be first
+	character.
+     Q  As O, but don't relax; force an 8-bit offset.
+     R	General register in bits <15:12>.
+     r	General register in bits <3:0>.
+     S	Source operand in bit <10> and a prefix; a 3-operand prefix
+	without side-effect.
+     s	Source operand in bits <10> and <3:0>, optionally with a
+	side-effect prefix, except [pc] (the name, not R15 as in ACR)
+	isn't allowed for v32 and higher.
+     T  Support register in bits <15:12>.
+     u  4-bit (PC-relative) unsigned immediate word offset in bits <3:0>.
+     U  Relaxes to either u or n, instruction is assumed LAPCQ or LAPC.
+	Not recognized at disassembly.
+     x	Register-dot-modifier, for example "r5.w" in bits <15:12> and <5:4>.
+     y	Like 's' but do not allow an integer at assembly.
+     Y	The difference s-y; only an integer is allowed.
+     z	Size modifier (B or W) in bit <4>.  */
+
+
+/* Please note the order of the opcodes in this table is significant.
+   The assembler requires that all instances of the same mnemonic must
+   be consecutive.  If they aren't, the assembler might not recognize
+   them, or may indicate an internal error.
+
+   The disassembler should not normally care about the order of the
+   opcodes, but will prefer an earlier alternative if the "match-score"
+   (see cris-dis.c) is computed as equal.
+
+   It should not be significant for proper execution that this table is
+   in alphabetical order, but please follow that convention for an easy
+   overview.  */
+
+const struct cris_opcode
+cris_opcodes[] =
+{
+  {"abs",     0x06B0, 0x0940,		  "r,R",     0, SIZE_NONE,     0,
+   cris_abs_op},
+
+  {"add",     0x0600, 0x09c0,		  "m r,R",   0, SIZE_NONE,     0,
+   cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"add",     0x0A00, 0x01c0,		  "m s,R",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"add",     0x0A00, 0x01c0,		  "m S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"add",     0x0a00, 0x05c0,		  "m S,R,r", 0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_three_operand_add_sub_cmp_and_or_op},
+
+  {"add",     0x0A00, 0x01c0,		  "m s,R",   0, SIZE_FIELD,
+   cris_ver_v32p,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"addc",    0x0570, 0x0A80,		  "r,R",     0, SIZE_FIX_32,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"addc",    0x09A0, 0x0250,		  "s,R",     0, SIZE_FIX_32,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"addi",    0x0540, 0x0A80,		  "x,r,A",   0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_addi_op},
+
+  {"addi",    0x0500, 0x0Ac0,		  "x,r",     0, SIZE_NONE,     0,
+   cris_addi_op},
+
+  /* This collates after "addo", but we want to disassemble as "addoq",
+     not "addo".  */
+  {"addoq",   0x0100, 0x0E00,		  "Q,A",     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"addo",    0x0940, 0x0280,		  "m s,R,A", 0, SIZE_FIELD_SIGNED,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  /* This must be located after the insn above, lest we misinterpret
+     "addo.b -1,r0,acr" as "addo .b-1,r0,acr".  FIXME: Sounds like a
+     parser bug.  */
+  {"addo",   0x0100, 0x0E00,		  "O,A",     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"addq",    0x0200, 0x0Dc0,		  "I,R",     0, SIZE_NONE,     0,
+   cris_quick_mode_add_sub_op},
+
+  {"adds",    0x0420, 0x0Bc0,		  "z r,R",   0, SIZE_NONE,     0,
+   cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+  /* FIXME: SIZE_FIELD_SIGNED and all necessary changes.  */
+  {"adds",    0x0820, 0x03c0,		  "z s,R",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"adds",    0x0820, 0x03c0,		  "z S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"adds",    0x0820, 0x07c0,		  "z S,R,r", 0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_three_operand_add_sub_cmp_and_or_op},
+
+  {"addu",    0x0400, 0x0be0,		  "z r,R",   0, SIZE_NONE,     0,
+   cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+  /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes.  */
+  {"addu",    0x0800, 0x03e0,		  "z s,R",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"addu",    0x0800, 0x03e0,		  "z S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"addu",    0x0800, 0x07e0,		  "z S,R,r", 0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_three_operand_add_sub_cmp_and_or_op},
+
+  {"and",     0x0700, 0x08C0,		  "m r,R",   0, SIZE_NONE,     0,
+   cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"and",     0x0B00, 0x00C0,		  "m s,R",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"and",     0x0B00, 0x00C0,		  "m S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"and",     0x0B00, 0x04C0,		  "m S,R,r", 0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_three_operand_add_sub_cmp_and_or_op},
+
+  {"andq",    0x0300, 0x0CC0,		  "i,R",     0, SIZE_NONE,     0,
+   cris_quick_mode_and_cmp_move_or_op},
+
+  {"asr",     0x0780, 0x0840,		  "m r,R",   0, SIZE_NONE,     0,
+   cris_asr_op},
+
+  {"asrq",    0x03a0, 0x0c40,		  "c,R",     0, SIZE_NONE,     0,
+   cris_asrq_op},
+
+  {"ax",      0x15B0, 0xEA4F,		  "",	     0, SIZE_NONE,     0,
+   cris_ax_ei_setf_op},
+
+  /* FIXME: Should use branch #defines.  */
+  {"b",	      0x0dff, 0x0200,		  "b",	     1, SIZE_NONE,     0,
+   cris_sixteen_bit_offset_branch_op},
+
+  {"ba",
+   BA_QUICK_OPCODE,
+   0x0F00+(0xF-CC_A)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  /* Needs to come after the usual "ba o", which might be relaxed to
+     this one.  */
+  {"ba",     BA_DWORD_OPCODE,
+   0xffff & (~BA_DWORD_OPCODE),		  "n",	     0, SIZE_FIX_32,
+   cris_ver_v32p,
+   cris_none_reg_mode_jump_op},
+
+  {"bas",     0x0EBF, 0x0140,		  "n,P",     0, SIZE_FIX_32,
+   cris_ver_v32p,
+   cris_none_reg_mode_jump_op},
+
+  {"basc",     0x0EFF, 0x0100,		  "n,P",     0, SIZE_FIX_32,
+   cris_ver_v32p,
+   cris_none_reg_mode_jump_op},
+
+  {"bcc",
+   BRANCH_QUICK_OPCODE+CC_CC*0x1000,
+   0x0f00+(0xF-CC_CC)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"bcs",
+   BRANCH_QUICK_OPCODE+CC_CS*0x1000,
+   0x0f00+(0xF-CC_CS)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"bdap",
+   BDAP_INDIR_OPCODE, BDAP_INDIR_Z_BITS,  "pm s,R",  0, SIZE_FIELD_SIGNED,
+   cris_ver_v0_10,
+   cris_bdap_prefix},
+
+  {"bdap",
+   BDAP_QUICK_OPCODE, BDAP_QUICK_Z_BITS,  "pO",	     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_quick_mode_bdap_prefix},
+
+  {"beq",
+   BRANCH_QUICK_OPCODE+CC_EQ*0x1000,
+   0x0f00+(0xF-CC_EQ)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  /* This is deliberately put before "bext" to trump it, even though not
+     in alphabetical order, since we don't do excluding version checks
+     for v0..v10.  */
+  {"bwf",
+   BRANCH_QUICK_OPCODE+CC_EXT*0x1000,
+   0x0f00+(0xF-CC_EXT)*0x1000,		  "o",	     1, SIZE_NONE,
+   cris_ver_v10,
+   cris_eight_bit_offset_branch_op},
+
+  {"bext",
+   BRANCH_QUICK_OPCODE+CC_EXT*0x1000,
+   0x0f00+(0xF-CC_EXT)*0x1000,		  "o",	     1, SIZE_NONE,
+   cris_ver_v0_3,
+   cris_eight_bit_offset_branch_op},
+
+  {"bge",
+   BRANCH_QUICK_OPCODE+CC_GE*0x1000,
+   0x0f00+(0xF-CC_GE)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"bgt",
+   BRANCH_QUICK_OPCODE+CC_GT*0x1000,
+   0x0f00+(0xF-CC_GT)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"bhi",
+   BRANCH_QUICK_OPCODE+CC_HI*0x1000,
+   0x0f00+(0xF-CC_HI)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"bhs",
+   BRANCH_QUICK_OPCODE+CC_HS*0x1000,
+   0x0f00+(0xF-CC_HS)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"biap", BIAP_OPCODE, BIAP_Z_BITS,	  "pm r,R",  0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_biap_prefix},
+
+  {"ble",
+   BRANCH_QUICK_OPCODE+CC_LE*0x1000,
+   0x0f00+(0xF-CC_LE)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"blo",
+   BRANCH_QUICK_OPCODE+CC_LO*0x1000,
+   0x0f00+(0xF-CC_LO)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"bls",
+   BRANCH_QUICK_OPCODE+CC_LS*0x1000,
+   0x0f00+(0xF-CC_LS)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"blt",
+   BRANCH_QUICK_OPCODE+CC_LT*0x1000,
+   0x0f00+(0xF-CC_LT)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"bmi",
+   BRANCH_QUICK_OPCODE+CC_MI*0x1000,
+   0x0f00+(0xF-CC_MI)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"bmod",    0x0ab0, 0x0140,		  "s,R",     0, SIZE_FIX_32,
+   cris_ver_sim_v0_10,
+   cris_not_implemented_op},
+
+  {"bmod",    0x0ab0, 0x0140,		  "S,D",     0, SIZE_NONE,
+   cris_ver_sim_v0_10,
+   cris_not_implemented_op},
+
+  {"bmod",    0x0ab0, 0x0540,		  "S,R,r",   0, SIZE_NONE,
+   cris_ver_sim_v0_10,
+   cris_not_implemented_op},
+
+  {"bne",
+   BRANCH_QUICK_OPCODE+CC_NE*0x1000,
+   0x0f00+(0xF-CC_NE)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"bound",   0x05c0, 0x0A00,		  "m r,R",   0, SIZE_NONE,     0,
+   cris_two_operand_bound_op},
+  /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes.  */
+  {"bound",   0x09c0, 0x0200,		  "m s,R",   0, SIZE_FIELD,
+   cris_ver_v0_10,
+   cris_two_operand_bound_op},
+  /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes.  */
+  {"bound",   0x0dcf, 0x0200,		  "m Y,R",   0, SIZE_FIELD,    0,
+   cris_two_operand_bound_op},
+  {"bound",   0x09c0, 0x0200,		  "m S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_two_operand_bound_op},
+  {"bound",   0x09c0, 0x0600,		  "m S,R,r", 0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_three_operand_bound_op},
+
+  {"bpl",
+   BRANCH_QUICK_OPCODE+CC_PL*0x1000,
+   0x0f00+(0xF-CC_PL)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"break",   0xe930, 0x16c0,		  "C",	     0, SIZE_NONE,
+   cris_ver_v3p,
+   cris_break_op},
+
+  {"bsb",
+   BRANCH_QUICK_OPCODE+CC_EXT*0x1000,
+   0x0f00+(0xF-CC_EXT)*0x1000,		  "o",	     1, SIZE_NONE,
+   cris_ver_v32p,
+   cris_eight_bit_offset_branch_op},
+
+  {"bsr",     0xBEBF, 0x4140,		  "n",	     0, SIZE_FIX_32,
+   cris_ver_v32p,
+   cris_none_reg_mode_jump_op},
+
+  {"bsrc",     0xBEFF, 0x4100,		  "n",	     0, SIZE_FIX_32,
+   cris_ver_v32p,
+   cris_none_reg_mode_jump_op},
+
+  {"bstore",  0x0af0, 0x0100,		  "s,R",     0, SIZE_FIX_32,
+   cris_ver_warning,
+   cris_not_implemented_op},
+
+  {"bstore",  0x0af0, 0x0100,		  "S,D",     0, SIZE_NONE,
+   cris_ver_warning,
+   cris_not_implemented_op},
+
+  {"bstore",  0x0af0, 0x0500,		  "S,R,r",   0, SIZE_NONE,
+   cris_ver_warning,
+   cris_not_implemented_op},
+
+  {"btst",    0x04F0, 0x0B00,		  "r,R",     0, SIZE_NONE,     0,
+   cris_btst_nop_op},
+  {"btstq",   0x0380, 0x0C60,		  "c,R",     0, SIZE_NONE,     0,
+   cris_btst_nop_op},
+
+  {"bvc",
+   BRANCH_QUICK_OPCODE+CC_VC*0x1000,
+   0x0f00+(0xF-CC_VC)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"bvs",
+   BRANCH_QUICK_OPCODE+CC_VS*0x1000,
+   0x0f00+(0xF-CC_VS)*0x1000,		  "o",	     1, SIZE_NONE,     0,
+   cris_eight_bit_offset_branch_op},
+
+  {"clear",   0x0670, 0x3980,		  "M r",     0, SIZE_NONE,     0,
+   cris_reg_mode_clear_op},
+
+  {"clear",   0x0A70, 0x3180,		  "M y",     0, SIZE_NONE,     0,
+   cris_none_reg_mode_clear_test_op},
+
+  {"clear",   0x0A70, 0x3180,		  "M S",     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_clear_test_op},
+
+  {"clearf",  0x05F0, 0x0A00,		  "f",	     0, SIZE_NONE,     0,
+   cris_clearf_di_op},
+
+  {"cmp",     0x06C0, 0x0900,		  "m r,R",   0, SIZE_NONE,     0,
+   cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"cmp",     0x0Ac0, 0x0100,		  "m s,R",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"cmp",     0x0Ac0, 0x0100,		  "m S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"cmpq",    0x02C0, 0x0D00,		  "i,R",     0, SIZE_NONE,     0,
+   cris_quick_mode_and_cmp_move_or_op},
+
+  /* FIXME: SIZE_FIELD_SIGNED and all necessary changes.  */
+  {"cmps",    0x08e0, 0x0300,		  "z s,R",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"cmps",    0x08e0, 0x0300,		  "z S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes.  */
+  {"cmpu",    0x08c0, 0x0320,		  "z s,R" ,  0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"cmpu",    0x08c0, 0x0320,		  "z S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"di",      0x25F0, 0xDA0F,		  "",	     0, SIZE_NONE,     0,
+   cris_clearf_di_op},
+
+  {"dip",     DIP_OPCODE, DIP_Z_BITS,	  "ps",	     0, SIZE_FIX_32,
+   cris_ver_v0_10,
+   cris_dip_prefix},
+
+  {"div",     0x0980, 0x0640,		  "m R,r",   0, SIZE_FIELD,    0,
+   cris_not_implemented_op},
+
+  {"dstep",   0x06f0, 0x0900,		  "r,R",     0, SIZE_NONE,     0,
+   cris_dstep_logshift_mstep_neg_not_op},
+
+  {"ei",      0x25B0, 0xDA4F,		  "",	     0, SIZE_NONE,     0,
+   cris_ax_ei_setf_op},
+
+  {"fidxd",    0x0ab0, 0xf540,		  "[r]",     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"fidxi",    0x0d30, 0xF2C0,		  "[r]",     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"ftagd",    0x1AB0, 0xE540,		  "[r]",     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"ftagi",    0x1D30, 0xE2C0,		  "[r]",     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"halt",    0xF930, 0x06CF,		  "",	     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"jas",    0x09B0, 0x0640,		  "r,P",     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_reg_mode_jump_op},
+
+  {"jas",    0x0DBF, 0x0240,		  "N,P",     0, SIZE_FIX_32,
+   cris_ver_v32p,
+   cris_reg_mode_jump_op},
+
+  {"jasc",    0x0B30, 0x04C0,		  "r,P",     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_reg_mode_jump_op},
+
+  {"jasc",    0x0F3F, 0x00C0,		  "N,P",     0, SIZE_FIX_32,
+   cris_ver_v32p,
+   cris_reg_mode_jump_op},
+
+  {"jbrc",    0x69b0, 0x9640,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8_10,
+   cris_reg_mode_jump_op},
+
+  {"jbrc",    0x6930, 0x92c0,		  "s",	     0, SIZE_FIX_32,
+   cris_ver_v8_10,
+   cris_none_reg_mode_jump_op},
+
+  {"jbrc",    0x6930, 0x92c0,		  "S",	     0, SIZE_NONE,
+   cris_ver_v8_10,
+   cris_none_reg_mode_jump_op},
+
+  {"jir",     0xA9b0, 0x5640,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8_10,
+   cris_reg_mode_jump_op},
+
+  {"jir",     0xA930, 0x52c0,		  "s",	     0, SIZE_FIX_32,
+   cris_ver_v8_10,
+   cris_none_reg_mode_jump_op},
+
+  {"jir",     0xA930, 0x52c0,		  "S",	     0, SIZE_NONE,
+   cris_ver_v8_10,
+   cris_none_reg_mode_jump_op},
+
+  {"jirc",    0x29b0, 0xd640,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8_10,
+   cris_reg_mode_jump_op},
+
+  {"jirc",    0x2930, 0xd2c0,		  "s",	     0, SIZE_FIX_32,
+   cris_ver_v8_10,
+   cris_none_reg_mode_jump_op},
+
+  {"jirc",    0x2930, 0xd2c0,		  "S",	     0, SIZE_NONE,
+   cris_ver_v8_10,
+   cris_none_reg_mode_jump_op},
+
+  {"jsr",     0xB9b0, 0x4640,		  "r",	     0, SIZE_NONE,     0,
+   cris_reg_mode_jump_op},
+
+  {"jsr",     0xB930, 0x42c0,		  "s",	     0, SIZE_FIX_32,
+   cris_ver_v0_10,
+   cris_none_reg_mode_jump_op},
+
+  {"jsr",     0xBDBF, 0x4240,		  "N",	     0, SIZE_FIX_32,
+   cris_ver_v32p,
+   cris_none_reg_mode_jump_op},
+
+  {"jsr",     0xB930, 0x42c0,		  "S",	     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_jump_op},
+
+  {"jsrc",    0x39b0, 0xc640,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8_10,
+   cris_reg_mode_jump_op},
+
+  {"jsrc",    0x3930, 0xc2c0,		  "s",	     0, SIZE_FIX_32,
+   cris_ver_v8_10,
+   cris_none_reg_mode_jump_op},
+
+  {"jsrc",    0x3930, 0xc2c0,		  "S",	     0, SIZE_NONE,
+   cris_ver_v8_10,
+   cris_none_reg_mode_jump_op},
+
+  {"jsrc",    0xBB30, 0x44C0,		  "r",       0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_reg_mode_jump_op},
+
+  {"jsrc",    0xBF3F, 0x40C0,		  "N",	     0, SIZE_FIX_32,
+   cris_ver_v32p,
+   cris_reg_mode_jump_op},
+
+  {"jump",    0x09b0, 0xF640,		  "r",	     0, SIZE_NONE,     0,
+   cris_reg_mode_jump_op},
+
+  {"jump",
+   JUMP_INDIR_OPCODE, JUMP_INDIR_Z_BITS,  "s",	     0, SIZE_FIX_32,
+   cris_ver_v0_10,
+   cris_none_reg_mode_jump_op},
+
+  {"jump",
+   JUMP_INDIR_OPCODE, JUMP_INDIR_Z_BITS,  "S",	     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_jump_op},
+
+  {"jump",    0x09F0, 0x060F,		  "P",	     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_none_reg_mode_jump_op},
+
+  {"jump",
+   JUMP_PC_INCR_OPCODE_V32,
+   (0xffff & ~JUMP_PC_INCR_OPCODE_V32),	  "N",	     0, SIZE_FIX_32,
+   cris_ver_v32p,
+   cris_none_reg_mode_jump_op},
+
+  {"jmpu",    0x8930, 0x72c0,		  "s",	     0, SIZE_FIX_32,
+   cris_ver_v10,
+   cris_none_reg_mode_jump_op},
+
+  {"jmpu",    0x8930, 0x72c0,		   "S",	     0, SIZE_NONE,
+   cris_ver_v10,
+   cris_none_reg_mode_jump_op},
+
+  {"lapc",    0x0970, 0x0680,		  "U,R",    0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"lapc",    0x0D7F, 0x0280,		  "dn,R",    0, SIZE_FIX_32,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"lapcq",   0x0970, 0x0680,		  "u,R",     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_addi_op},
+
+  {"lsl",     0x04C0, 0x0B00,		  "m r,R",   0, SIZE_NONE,     0,
+   cris_dstep_logshift_mstep_neg_not_op},
+
+  {"lslq",    0x03c0, 0x0C20,		  "c,R",     0, SIZE_NONE,     0,
+   cris_dstep_logshift_mstep_neg_not_op},
+
+  {"lsr",     0x07C0, 0x0800,		  "m r,R",   0, SIZE_NONE,     0,
+   cris_dstep_logshift_mstep_neg_not_op},
+
+  {"lsrq",    0x03e0, 0x0C00,		  "c,R",     0, SIZE_NONE,     0,
+   cris_dstep_logshift_mstep_neg_not_op},
+
+  {"lz",      0x0730, 0x08C0,		  "r,R",     0, SIZE_NONE,
+   cris_ver_v3p,
+   cris_not_implemented_op},
+
+  {"mcp",      0x07f0, 0x0800,		  "P,r",     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"move",    0x0640, 0x0980,		  "m r,R",   0, SIZE_NONE,     0,
+   cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"move",    0x0A40, 0x0180,		  "m s,R",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"move",    0x0A40, 0x0180,		  "m S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"move",    0x0630, 0x09c0,		  "r,P",     0, SIZE_NONE,     0,
+   cris_move_to_preg_op},
+
+  {"move",    0x0670, 0x0980,		  "P,r",     0, SIZE_NONE,     0,
+   cris_reg_mode_move_from_preg_op},
+
+  {"move",    0x0BC0, 0x0000,		  "m R,y",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"move",    0x0BC0, 0x0000,		  "m D,S",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"move",
+   MOVE_M_TO_PREG_OPCODE, MOVE_M_TO_PREG_ZBITS,
+   "s,P",   0, SIZE_SPEC_REG, 0,
+   cris_move_to_preg_op},
+
+  {"move",    0x0A30, 0x01c0,		  "S,P",     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_move_to_preg_op},
+
+  {"move",    0x0A70, 0x0180,		  "P,y",     0, SIZE_SPEC_REG, 0,
+   cris_none_reg_mode_move_from_preg_op},
+
+  {"move",    0x0A70, 0x0180,		  "P,S",     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_move_from_preg_op},
+
+  {"move",    0x0B70, 0x0480,		  "r,T",     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"move",    0x0F70, 0x0080,		  "T,r",     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"movem",   0x0BF0, 0x0000,		  "R,y",     0, SIZE_FIX_32,   0,
+   cris_move_reg_to_mem_movem_op},
+
+  {"movem",   0x0BF0, 0x0000,		  "D,S",     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_move_reg_to_mem_movem_op},
+
+  {"movem",   0x0BB0, 0x0040,		  "s,R",     0, SIZE_FIX_32,   0,
+   cris_move_mem_to_reg_movem_op},
+
+  {"movem",   0x0BB0, 0x0040,		  "S,D",     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_move_mem_to_reg_movem_op},
+
+  {"moveq",   0x0240, 0x0D80,		  "i,R",     0, SIZE_NONE,     0,
+   cris_quick_mode_and_cmp_move_or_op},
+
+  {"movs",    0x0460, 0x0B80,		  "z r,R",   0, SIZE_NONE,     0,
+   cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+  /* FIXME: SIZE_FIELD_SIGNED and all necessary changes.  */
+  {"movs",    0x0860, 0x0380,		  "z s,R",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"movs",    0x0860, 0x0380,		  "z S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"movu",    0x0440, 0x0Ba0,		  "z r,R",   0, SIZE_NONE,     0,
+   cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+  /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes.  */
+  {"movu",    0x0840, 0x03a0,		  "z s,R",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"movu",    0x0840, 0x03a0,		  "z S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"mstep",   0x07f0, 0x0800,		  "r,R",     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_dstep_logshift_mstep_neg_not_op},
+
+  {"muls",    0x0d00, 0x02c0,		  "m r,R",   0, SIZE_NONE,
+   cris_ver_v10p,
+   cris_muls_op},
+
+  {"mulu",    0x0900, 0x06c0,		  "m r,R",   0, SIZE_NONE,
+   cris_ver_v10p,
+   cris_mulu_op},
+
+  {"neg",     0x0580, 0x0A40,		  "m r,R",   0, SIZE_NONE,     0,
+   cris_dstep_logshift_mstep_neg_not_op},
+
+  {"nop",     NOP_OPCODE, NOP_Z_BITS,	  "",	     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_btst_nop_op},
+
+  {"nop",     NOP_OPCODE_V32, NOP_Z_BITS_V32, "",    0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_btst_nop_op},
+
+  {"not",     0x8770, 0x7880,		  "r",	     0, SIZE_NONE,     0,
+   cris_dstep_logshift_mstep_neg_not_op},
+
+  {"or",      0x0740, 0x0880,		  "m r,R",   0, SIZE_NONE,     0,
+   cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"or",      0x0B40, 0x0080,		  "m s,R",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"or",      0x0B40, 0x0080,		  "m S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"or",      0x0B40, 0x0480,		  "m S,R,r", 0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_three_operand_add_sub_cmp_and_or_op},
+
+  {"orq",     0x0340, 0x0C80,		  "i,R",     0, SIZE_NONE,     0,
+   cris_quick_mode_and_cmp_move_or_op},
+
+  {"pop",     0x0E6E, 0x0191,		  "!R",	     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"pop",     0x0e3e, 0x01c1,		  "!P",	     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_move_from_preg_op},
+
+  {"push",    0x0FEE, 0x0011,		  "BR",	     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"push",    0x0E7E, 0x0181,		  "BP",	     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_move_to_preg_op},
+
+  {"rbf",     0x3b30, 0xc0c0,		  "y",	     0, SIZE_NONE,
+   cris_ver_v10,
+   cris_not_implemented_op},
+
+  {"rbf",     0x3b30, 0xc0c0,		  "S",	     0, SIZE_NONE,
+   cris_ver_v10,
+   cris_not_implemented_op},
+
+  {"rfe",     0x2930, 0xD6CF,		  "",	     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"rfg",     0x4930, 0xB6CF,		  "",	     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"rfn",     0x5930, 0xA6CF,		  "",	     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  {"ret",     0xB67F, 0x4980,		  "",	     1, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_reg_mode_move_from_preg_op},
+
+  {"ret",     0xB9F0, 0x460F,		  "",	     1, SIZE_NONE,
+   cris_ver_v32p,
+   cris_reg_mode_move_from_preg_op},
+
+  {"retb",    0xe67f, 0x1980,		  "",	     1, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_reg_mode_move_from_preg_op},
+
+  {"rete",     0xA9F0, 0x560F,		  "",	     1, SIZE_NONE,
+   cris_ver_v32p,
+   cris_reg_mode_move_from_preg_op},
+
+  {"reti",    0xA67F, 0x5980,		  "",	     1, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_reg_mode_move_from_preg_op},
+
+  {"retn",     0xC9F0, 0x360F,		  "",	     1, SIZE_NONE,
+   cris_ver_v32p,
+   cris_reg_mode_move_from_preg_op},
+
+  {"sbfs",    0x3b70, 0xc080,		  "y",	     0, SIZE_NONE,
+   cris_ver_v10,
+   cris_not_implemented_op},
+
+  {"sbfs",    0x3b70, 0xc080,		  "S",	     0, SIZE_NONE,
+   cris_ver_v10,
+   cris_not_implemented_op},
+
+  {"sa",
+   0x0530+CC_A*0x1000,
+   0x0AC0+(0xf-CC_A)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"ssb",
+   0x0530+CC_EXT*0x1000,
+   0x0AC0+(0xf-CC_EXT)*0x1000,		  "r",	     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_scc_op},
+
+  {"scc",
+   0x0530+CC_CC*0x1000,
+   0x0AC0+(0xf-CC_CC)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"scs",
+   0x0530+CC_CS*0x1000,
+   0x0AC0+(0xf-CC_CS)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"seq",
+   0x0530+CC_EQ*0x1000,
+   0x0AC0+(0xf-CC_EQ)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"setf",    0x05b0, 0x0A40,		  "f",	     0, SIZE_NONE,     0,
+   cris_ax_ei_setf_op},
+
+  {"sfe",    0x3930, 0xC6CF,		  "",	     0, SIZE_NONE,
+   cris_ver_v32p,
+   cris_not_implemented_op},
+
+  /* Need to have "swf" in front of "sext" so it is the one displayed in
+     disassembly.  */
+  {"swf",
+   0x0530+CC_EXT*0x1000,
+   0x0AC0+(0xf-CC_EXT)*0x1000,		  "r",	     0, SIZE_NONE,
+   cris_ver_v10,
+   cris_scc_op},
+
+  {"sext",
+   0x0530+CC_EXT*0x1000,
+   0x0AC0+(0xf-CC_EXT)*0x1000,		  "r",	     0, SIZE_NONE,
+   cris_ver_v0_3,
+   cris_scc_op},
+
+  {"sge",
+   0x0530+CC_GE*0x1000,
+   0x0AC0+(0xf-CC_GE)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"sgt",
+   0x0530+CC_GT*0x1000,
+   0x0AC0+(0xf-CC_GT)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"shi",
+   0x0530+CC_HI*0x1000,
+   0x0AC0+(0xf-CC_HI)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"shs",
+   0x0530+CC_HS*0x1000,
+   0x0AC0+(0xf-CC_HS)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"sle",
+   0x0530+CC_LE*0x1000,
+   0x0AC0+(0xf-CC_LE)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"slo",
+   0x0530+CC_LO*0x1000,
+   0x0AC0+(0xf-CC_LO)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"sls",
+   0x0530+CC_LS*0x1000,
+   0x0AC0+(0xf-CC_LS)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"slt",
+   0x0530+CC_LT*0x1000,
+   0x0AC0+(0xf-CC_LT)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"smi",
+   0x0530+CC_MI*0x1000,
+   0x0AC0+(0xf-CC_MI)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"sne",
+   0x0530+CC_NE*0x1000,
+   0x0AC0+(0xf-CC_NE)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"spl",
+   0x0530+CC_PL*0x1000,
+   0x0AC0+(0xf-CC_PL)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"sub",     0x0680, 0x0940,		  "m r,R",   0, SIZE_NONE,     0,
+   cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"sub",     0x0a80, 0x0140,		  "m s,R",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"sub",     0x0a80, 0x0140,		  "m S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"sub",     0x0a80, 0x0540,		  "m S,R,r", 0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_three_operand_add_sub_cmp_and_or_op},
+
+  {"subq",    0x0280, 0x0d40,		  "I,R",     0, SIZE_NONE,     0,
+   cris_quick_mode_add_sub_op},
+
+  {"subs",    0x04a0, 0x0b40,		  "z r,R",   0, SIZE_NONE,     0,
+   cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+  /* FIXME: SIZE_FIELD_SIGNED and all necessary changes.  */
+  {"subs",    0x08a0, 0x0340,		  "z s,R",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"subs",    0x08a0, 0x0340,		  "z S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"subs",    0x08a0, 0x0740,		  "z S,R,r", 0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_three_operand_add_sub_cmp_and_or_op},
+
+  {"subu",    0x0480, 0x0b60,		  "z r,R",   0, SIZE_NONE,     0,
+   cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+  /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes.  */
+  {"subu",    0x0880, 0x0360,		  "z s,R",   0, SIZE_FIELD,    0,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"subu",    0x0880, 0x0360,		  "z S,D",   0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+  {"subu",    0x0880, 0x0760,		  "z S,R,r", 0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_three_operand_add_sub_cmp_and_or_op},
+
+  {"svc",
+   0x0530+CC_VC*0x1000,
+   0x0AC0+(0xf-CC_VC)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  {"svs",
+   0x0530+CC_VS*0x1000,
+   0x0AC0+(0xf-CC_VS)*0x1000,		  "r",	     0, SIZE_NONE,     0,
+   cris_scc_op},
+
+  /* The insn "swapn" is the same as "not" and will be disassembled as
+     such, but the swap* family of mnmonics are generally v8-and-higher
+     only, so count it in.  */
+  {"swapn",   0x8770, 0x7880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapw",   0x4770, 0xb880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapnw",  0xc770, 0x3880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapb",   0x2770, 0xd880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapnb",  0xA770, 0x5880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapwb",  0x6770, 0x9880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapnwb", 0xE770, 0x1880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapr",   0x1770, 0xe880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapnr",  0x9770, 0x6880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapwr",  0x5770, 0xa880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapnwr", 0xd770, 0x2880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapbr",  0x3770, 0xc880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapnbr", 0xb770, 0x4880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapwbr", 0x7770, 0x8880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"swapnwbr", 0xf770, 0x0880,		  "r",	     0, SIZE_NONE,
+   cris_ver_v8p,
+   cris_not_implemented_op},
+
+  {"test",    0x0640, 0x0980,		  "m D",     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_reg_mode_test_op},
+
+  {"test",    0x0b80, 0xf040,		  "m y",     0, SIZE_FIELD,    0,
+   cris_none_reg_mode_clear_test_op},
+
+  {"test",    0x0b80, 0xf040,		  "m S",     0, SIZE_NONE,
+   cris_ver_v0_10,
+   cris_none_reg_mode_clear_test_op},
+
+  {"xor",     0x07B0, 0x0840,		  "r,R",     0, SIZE_NONE,     0,
+   cris_xor_op},
+
+  {NULL, 0, 0, NULL, 0, 0, 0, cris_not_implemented_op}
+};
+
+/* Condition-names, indexed by the CC_* numbers as found in cris.h. */
+const char * const
+cris_cc_strings[] =
+{
+  "hs",
+  "lo",
+  "ne",
+  "eq",
+  "vc",
+  "vs",
+  "pl",
+  "mi",
+  "ls",
+  "hi",
+  "ge",
+  "lt",
+  "gt",
+  "le",
+  "a",
+  /* This is a placeholder.  In v0, this would be "ext".  In v32, this
+     is "sb".  See cris_conds15.  */
+  "wf"
+};
+
+/* Different names and semantics for condition 1111 (0xf).  */
+const struct cris_cond15 cris_cond15s[] =
+{
+  /* FIXME: In what version did condition "ext" disappear?  */
+  {"ext", cris_ver_v0_3},
+  {"wf", cris_ver_v10},
+  {"sb", cris_ver_v32p},
+  {NULL, 0}
+};
+
+
+/*
+ * Local variables:
+ * eval: (c-set-style "gnu")
+ * indent-tabs-mode: t
+ * End:
+ */
+
+
+/* No instruction will be disassembled longer than this.  In theory, and
+   in silicon, address prefixes can be cascaded.  In practice, cascading
+   is not used by GCC, and not supported by the assembler.  */
+#ifndef MAX_BYTES_PER_CRIS_INSN
+#define MAX_BYTES_PER_CRIS_INSN 8
+#endif
+
+/* Whether or not to decode prefixes, folding it into the following
+   instruction.  FIXME: Make this optional later.  */
+#ifndef PARSE_PREFIX
+#define PARSE_PREFIX 1
+#endif
+
+/* Sometimes we prefix all registers with this character.  */
+#define REGISTER_PREFIX_CHAR '$'
+
+/* Whether or not to trace the following sequence:
+   sub* X,r%d
+   bound* Y,r%d
+   adds.w [pc+r%d.w],pc
+
+   This is the assembly form of a switch-statement in C.
+   The "sub is optional.  If there is none, then X will be zero.
+   X is the value of the first case,
+   Y is the number of cases (including default).
+
+   This results in case offsets printed on the form:
+    case N: -> case_address
+   where N is an estimation on the corresponding 'case' operand in C,
+   and case_address is where execution of that case continues after the
+   sequence presented above.
+
+   The old style of output was to print the offsets as instructions,
+   which made it hard to follow "case"-constructs in the disassembly,
+   and caused a lot of annoying warnings about undefined instructions.
+
+   FIXME: Make this optional later.  */
+#ifndef TRACE_CASE
+#define TRACE_CASE (disdata->trace_case)
+#endif
+
+enum cris_disass_family
+ { cris_dis_v0_v10, cris_dis_common_v10_v32, cris_dis_v32 };
+
+/* Stored in the disasm_info->private_data member.  */
+struct cris_disasm_data
+{
+  /* Whether to print something less confusing if we find something
+     matching a switch-construct.  */
+  bfd_boolean trace_case;
+
+  /* Whether this code is flagged as crisv32.  FIXME: Should be an enum
+     that includes "compatible".  */
+  enum cris_disass_family distype;
+};
+
+/* Value of first element in switch.  */
+static long case_offset = 0;
+
+/* How many more case-offsets to print.  */
+static long case_offset_counter = 0;
+
+/* Number of case offsets.  */
+static long no_of_case_offsets = 0;
+
+/* Candidate for next case_offset.  */
+static long last_immediate = 0;
+
+static int cris_constraint
+  (const char *, unsigned, unsigned, struct cris_disasm_data *);
+
+/* Parse disassembler options and store state in info.  FIXME: For the
+   time being, we abuse static variables.  */
+
+static bfd_boolean
+cris_parse_disassembler_options (disassemble_info *info,
+				 enum cris_disass_family distype)
+{
+  struct cris_disasm_data *disdata;
+
+  info->private_data = calloc (1, sizeof (struct cris_disasm_data));
+  disdata = (struct cris_disasm_data *) info->private_data;
+  if (disdata == NULL)
+    return FALSE;
+
+  /* Default true.  */
+  disdata->trace_case
+    = (info->disassembler_options == NULL
+       || (strcmp (info->disassembler_options, "nocase") != 0));
+
+  disdata->distype = distype;
+  return TRUE;
+}
+
+static const struct cris_spec_reg *
+spec_reg_info (unsigned int sreg, enum cris_disass_family distype)
+{
+  int i;
+
+  for (i = 0; cris_spec_regs[i].name != NULL; i++)
+    {
+      if (cris_spec_regs[i].number == sreg)
+	{
+	  if (distype == cris_dis_v32)
+	    switch (cris_spec_regs[i].applicable_version)
+	      {
+	      case cris_ver_warning:
+	      case cris_ver_version_all:
+	      case cris_ver_v3p:
+	      case cris_ver_v8p:
+	      case cris_ver_v10p:
+	      case cris_ver_v32p:
+		/* No ambiguous sizes or register names with CRISv32.  */
+		if (cris_spec_regs[i].warning == NULL)
+		  return &cris_spec_regs[i];
+	      default:
+		;
+	      }
+	  else if (cris_spec_regs[i].applicable_version != cris_ver_v32p)
+	    return &cris_spec_regs[i];
+	}
+    }
+
+  return NULL;
+}
+
+/* Return the number of bits in the argument.  */
+
+static int
+number_of_bits (unsigned int val)
+{
+  int bits;
+
+  for (bits = 0; val != 0; val &= val - 1)
+    bits++;
+
+  return bits;
+}
+
+/* Get an entry in the opcode-table.  */
+
+static const struct cris_opcode *
+get_opcode_entry (unsigned int insn,
+		  unsigned int prefix_insn,
+		  struct cris_disasm_data *disdata)
+{
+  /* For non-prefixed insns, we keep a table of pointers, indexed by the
+     insn code.  Each entry is initialized when found to be NULL.  */
+  static const struct cris_opcode **opc_table = NULL;
+
+  const struct cris_opcode *max_matchedp = NULL;
+  const struct cris_opcode **prefix_opc_table = NULL;
+
+  /* We hold a table for each prefix that need to be handled differently.  */
+  static const struct cris_opcode **dip_prefixes = NULL;
+  static const struct cris_opcode **bdapq_m1_prefixes = NULL;
+  static const struct cris_opcode **bdapq_m2_prefixes = NULL;
+  static const struct cris_opcode **bdapq_m4_prefixes = NULL;
+  static const struct cris_opcode **rest_prefixes = NULL;
+
+  /* Allocate and clear the opcode-table.  */
+  if (opc_table == NULL)
+    {
+      opc_table = malloc (65536 * sizeof (opc_table[0]));
+      if (opc_table == NULL)
+	return NULL;
+
+      memset (opc_table, 0, 65536 * sizeof (const struct cris_opcode *));
+
+      dip_prefixes
+	= malloc (65536 * sizeof (const struct cris_opcode **));
+      if (dip_prefixes == NULL)
+	return NULL;
+
+      memset (dip_prefixes, 0, 65536 * sizeof (dip_prefixes[0]));
+
+      bdapq_m1_prefixes
+	= malloc (65536 * sizeof (const struct cris_opcode **));
+      if (bdapq_m1_prefixes == NULL)
+	return NULL;
+
+      memset (bdapq_m1_prefixes, 0, 65536 * sizeof (bdapq_m1_prefixes[0]));
+
+      bdapq_m2_prefixes
+	= malloc (65536 * sizeof (const struct cris_opcode **));
+      if (bdapq_m2_prefixes == NULL)
+	return NULL;
+
+      memset (bdapq_m2_prefixes, 0, 65536 * sizeof (bdapq_m2_prefixes[0]));
+
+      bdapq_m4_prefixes
+	= malloc (65536 * sizeof (const struct cris_opcode **));
+      if (bdapq_m4_prefixes == NULL)
+	return NULL;
+
+      memset (bdapq_m4_prefixes, 0, 65536 * sizeof (bdapq_m4_prefixes[0]));
+
+      rest_prefixes
+	= malloc (65536 * sizeof (const struct cris_opcode **));
+      if (rest_prefixes == NULL)
+	return NULL;
+
+      memset (rest_prefixes, 0, 65536 * sizeof (rest_prefixes[0]));
+    }
+
+  /* Get the right table if this is a prefix.
+     This code is connected to cris_constraints in that it knows what
+     prefixes play a role in recognition of patterns; the necessary
+     state is reflected by which table is used.  If constraints
+     involving match or non-match of prefix insns are changed, then this
+     probably needs changing too.  */
+  if (prefix_insn != NO_CRIS_PREFIX)
+    {
+      const struct cris_opcode *popcodep
+	= (opc_table[prefix_insn] != NULL
+	   ? opc_table[prefix_insn]
+	   : get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata));
+
+      if (popcodep == NULL)
+	return NULL;
+
+      if (popcodep->match == BDAP_QUICK_OPCODE)
+	{
+	  /* Since some offsets are recognized with "push" macros, we
+	     have to have different tables for them.  */
+	  int offset = (prefix_insn & 255);
+
+	  if (offset > 127)
+	    offset -= 256;
+
+	  switch (offset)
+	    {
+	    case -4:
+	      prefix_opc_table = bdapq_m4_prefixes;
+	      break;
+
+	    case -2:
+	      prefix_opc_table = bdapq_m2_prefixes;
+	      break;
+
+	    case -1:
+	      prefix_opc_table = bdapq_m1_prefixes;
+	      break;
+
+	    default:
+	      prefix_opc_table = rest_prefixes;
+	      break;
+	    }
+	}
+      else if (popcodep->match == DIP_OPCODE)
+	/* We don't allow postincrement when the prefix is DIP, so use a
+	   different table for DIP.  */
+	prefix_opc_table = dip_prefixes;
+      else
+	prefix_opc_table = rest_prefixes;
+    }
+
+  if (prefix_insn != NO_CRIS_PREFIX
+      && prefix_opc_table[insn] != NULL)
+    max_matchedp = prefix_opc_table[insn];
+  else if (prefix_insn == NO_CRIS_PREFIX && opc_table[insn] != NULL)
+    max_matchedp = opc_table[insn];
+  else
+    {
+      const struct cris_opcode *opcodep;
+      int max_level_of_match = -1;
+
+      for (opcodep = cris_opcodes;
+	   opcodep->name != NULL;
+	   opcodep++)
+	{
+	  int level_of_match;
+
+	  if (disdata->distype == cris_dis_v32)
+	    {
+	      switch (opcodep->applicable_version)
+		{
+		case cris_ver_version_all:
+		  break;
+
+		case cris_ver_v0_3:
+		case cris_ver_v0_10:
+		case cris_ver_v3_10:
+		case cris_ver_sim_v0_10:
+		case cris_ver_v8_10:
+		case cris_ver_v10:
+		case cris_ver_warning:
+		  continue;
+
+		case cris_ver_v3p:
+		case cris_ver_v8p:
+		case cris_ver_v10p:
+		case cris_ver_v32p:
+		  break;
+
+		case cris_ver_v8:
+		  abort ();
+		default:
+		  abort ();
+		}
+	    }
+	  else
+	    {
+	      switch (opcodep->applicable_version)
+		{
+		case cris_ver_version_all:
+		case cris_ver_v0_3:
+		case cris_ver_v3p:
+		case cris_ver_v0_10:
+		case cris_ver_v8p:
+		case cris_ver_v8_10:
+		case cris_ver_v10:
+		case cris_ver_sim_v0_10:
+		case cris_ver_v10p:
+		case cris_ver_warning:
+		  break;
+
+		case cris_ver_v32p:
+		  continue;
+
+		case cris_ver_v8:
+		  abort ();
+		default:
+		  abort ();
+		}
+	    }
+
+	  /* We give a double lead for bits matching the template in
+	     cris_opcodes.  Not even, because then "move p8,r10" would
+	     be given 2 bits lead over "clear.d r10".  When there's a
+	     tie, the first entry in the table wins.  This is
+	     deliberate, to avoid a more complicated recognition
+	     formula.  */
+	  if ((opcodep->match & insn) == opcodep->match
+	      && (opcodep->lose & insn) == 0
+	      && ((level_of_match
+		   = cris_constraint (opcodep->args,
+				      insn,
+				      prefix_insn,
+				      disdata))
+		  >= 0)
+	      && ((level_of_match
+		   += 2 * number_of_bits (opcodep->match
+					  | opcodep->lose))
+			  > max_level_of_match))
+		    {
+		      max_matchedp = opcodep;
+		      max_level_of_match = level_of_match;
+
+		      /* If there was a full match, never mind looking
+			 further.  */
+		      if (level_of_match >= 2 * 16)
+			break;
+		    }
+		}
+      /* Fill in the new entry.
+
+	 If there are changes to the opcode-table involving prefixes, and
+	 disassembly then does not work correctly, try removing the
+	 else-clause below that fills in the prefix-table.  If that
+	 helps, you need to change the prefix_opc_table setting above, or
+	 something related.  */
+      if (prefix_insn == NO_CRIS_PREFIX)
+	opc_table[insn] = max_matchedp;
+      else
+	prefix_opc_table[insn] = max_matchedp;
+    }
+
+  return max_matchedp;
+}
+
+/* Return -1 if the constraints of a bitwise-matched instruction say
+   that there is no match.  Otherwise return a nonnegative number
+   indicating the confidence in the match (higher is better).  */
+
+static int
+cris_constraint (const char *cs,
+		 unsigned int insn,
+		 unsigned int prefix_insn,
+		 struct cris_disasm_data *disdata)
+{
+  int retval = 0;
+  int tmp;
+  int prefix_ok = 0;
+  const char *s;
+
+  for (s = cs; *s; s++)
+    switch (*s)
+      {
+      case '!':
+	/* Do not recognize "pop" if there's a prefix and then only for
+           v0..v10.  */
+	if (prefix_insn != NO_CRIS_PREFIX
+	    || disdata->distype != cris_dis_v0_v10)
+	  return -1;
+	break;
+
+      case 'U':
+	/* Not recognized at disassembly.  */
+	return -1;
+
+      case 'M':
+	/* Size modifier for "clear", i.e. special register 0, 4 or 8.
+	   Check that it is one of them.  Only special register 12 could
+	   be mismatched, but checking for matches is more logical than
+	   checking for mismatches when there are only a few cases.  */
+	tmp = ((insn >> 12) & 0xf);
+	if (tmp != 0 && tmp != 4 && tmp != 8)
+	  return -1;
+	break;
+
+      case 'm':
+	if ((insn & 0x30) == 0x30)
+	  return -1;
+	break;
+
+      case 'S':
+	/* A prefix operand without side-effect.  */
+	if (prefix_insn != NO_CRIS_PREFIX && (insn & 0x400) == 0)
+	  {
+	    prefix_ok = 1;
+	    break;
+	  }
+	else
+	  return -1;
+
+      case 's':
+      case 'y':
+      case 'Y':
+	/* If this is a prefixed insn with postincrement (side-effect),
+	   the prefix must not be DIP.  */
+	if (prefix_insn != NO_CRIS_PREFIX)
+	  {
+	    if (insn & 0x400)
+	      {
+		const struct cris_opcode *prefix_opcodep
+		  = get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata);
+
+		if (prefix_opcodep->match == DIP_OPCODE)
+		  return -1;
+	      }
+
+	    prefix_ok = 1;
+	  }
+	break;
+
+      case 'B':
+	/* If we don't fall through, then the prefix is ok.  */
+	prefix_ok = 1;
+
+	/* A "push" prefix.  Check for valid "push" size.
+	   In case of special register, it may be != 4.  */
+	if (prefix_insn != NO_CRIS_PREFIX)
+	  {
+	    /* Match the prefix insn to BDAPQ.  */
+	    const struct cris_opcode *prefix_opcodep
+	      = get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata);
+
+	    if (prefix_opcodep->match == BDAP_QUICK_OPCODE)
+	      {
+		int pushsize = (prefix_insn & 255);
+
+		if (pushsize > 127)
+		  pushsize -= 256;
+
+		if (s[1] == 'P')
+		  {
+		    unsigned int spec_reg = (insn >> 12) & 15;
+		    const struct cris_spec_reg *sregp
+		      = spec_reg_info (spec_reg, disdata->distype);
+
+		    /* For a special-register, the "prefix size" must
+		       match the size of the register.  */
+		    if (sregp && sregp->reg_size == (unsigned int) -pushsize)
+		      break;
+		  }
+		else if (s[1] == 'R')
+		  {
+		    if ((insn & 0x30) == 0x20 && pushsize == -4)
+		      break;
+		  }
+		/* FIXME:  Should abort here; next constraint letter
+		   *must* be 'P' or 'R'.  */
+	      }
+	  }
+	return -1;
+
+      case 'D':
+	retval = (((insn >> 12) & 15) == (insn & 15));
+	if (!retval)
+	  return -1;
+	else
+	  retval += 4;
+	break;
+
+      case 'P':
+	{
+	  const struct cris_spec_reg *sregp
+	    = spec_reg_info ((insn >> 12) & 15, disdata->distype);
+
+	  /* Since we match four bits, we will give a value of 4-1 = 3
+	     in a match.  If there is a corresponding exact match of a
+	     special register in another pattern, it will get a value of
+	     4, which will be higher.  This should be correct in that an
+	     exact pattern would match better than a general pattern.
+
+	     Note that there is a reason for not returning zero; the
+	     pattern for "clear" is partly  matched in the bit-pattern
+	     (the two lower bits must be zero), while the bit-pattern
+	     for a move from a special register is matched in the
+	     register constraint.  */
+
+	  if (sregp != NULL)
+	    {
+	      retval += 3;
+	      break;
+	    }
+	  else
+	    return -1;
+	}
+      }
+
+  if (prefix_insn != NO_CRIS_PREFIX && ! prefix_ok)
+    return -1;
+
+  return retval;
+}
+
+/* Format number as hex with a leading "0x" into outbuffer.  */
+
+static char *
+format_hex (unsigned long number,
+	    char *outbuffer,
+	    struct cris_disasm_data *disdata)
+{
+  /* Truncate negative numbers on >32-bit hosts.  */
+  number &= 0xffffffff;
+
+  sprintf (outbuffer, "0x%lx", number);
+
+  /* Save this value for the "case" support.  */
+  if (TRACE_CASE)
+    last_immediate = number;
+
+  return outbuffer + strlen (outbuffer);
+}
+
+/* Format number as decimal into outbuffer.  Parameter signedp says
+   whether the number should be formatted as signed (!= 0) or
+   unsigned (== 0).  */
+
+static char *
+format_dec (long number, char *outbuffer, int signedp)
+{
+  last_immediate = number;
+  sprintf (outbuffer, signedp ? "%ld" : "%lu", number);
+
+  return outbuffer + strlen (outbuffer);
+}
+
+/* Format the name of the general register regno into outbuffer.  */
+
+static char *
+format_reg (struct cris_disasm_data *disdata,
+	    int regno,
+	    char *outbuffer_start,
+	    bfd_boolean with_reg_prefix)
+{
+  char *outbuffer = outbuffer_start;
+
+  if (with_reg_prefix)
+    *outbuffer++ = REGISTER_PREFIX_CHAR;
+
+  switch (regno)
+    {
+    case 15:
+      /* For v32, there is no context in which we output PC.  */
+      if (disdata->distype == cris_dis_v32)
+	strcpy (outbuffer, "acr");
+      else
+	strcpy (outbuffer, "pc");
+      break;
+
+    case 14:
+      strcpy (outbuffer, "sp");
+      break;
+
+    default:
+      sprintf (outbuffer, "r%d", regno);
+      break;
+    }
+
+  return outbuffer_start + strlen (outbuffer_start);
+}
+
+/* Format the name of a support register into outbuffer.  */
+
+static char *
+format_sup_reg (unsigned int regno,
+		char *outbuffer_start,
+		bfd_boolean with_reg_prefix)
+{
+  char *outbuffer = outbuffer_start;
+  int i;
+
+  if (with_reg_prefix)
+    *outbuffer++ = REGISTER_PREFIX_CHAR;
+
+  for (i = 0; cris_support_regs[i].name != NULL; i++)
+    if (cris_support_regs[i].number == regno)
+      {
+	sprintf (outbuffer, "%s", cris_support_regs[i].name);
+	return outbuffer_start + strlen (outbuffer_start);
+      }
+
+  /* There's supposed to be register names covering all numbers, though
+     some may be generic names.  */
+  sprintf (outbuffer, "format_sup_reg-BUG");
+  return outbuffer_start + strlen (outbuffer_start);
+}
+
+/* Return the length of an instruction.  */
+
+static unsigned
+bytes_to_skip (unsigned int insn,
+	       const struct cris_opcode *matchedp,
+	       enum cris_disass_family distype,
+	       const struct cris_opcode *prefix_matchedp)
+{
+  /* Each insn is a word plus "immediate" operands.  */
+  unsigned to_skip = 2;
+  const char *template = matchedp->args;
+  const char *s;
+
+  for (s = template; *s; s++)
+    if ((*s == 's' || *s == 'N' || *s == 'Y')
+	&& (insn & 0x400) && (insn & 15) == 15
+	&& prefix_matchedp == NULL)
+      {
+	/* Immediate via [pc+], so we have to check the size of the
+	   operand.  */
+	int mode_size = 1 << ((insn >> 4) & (*template == 'z' ? 1 : 3));
+
+	if (matchedp->imm_oprnd_size == SIZE_FIX_32)
+	  to_skip += 4;
+	else if (matchedp->imm_oprnd_size == SIZE_SPEC_REG)
+	  {
+	    const struct cris_spec_reg *sregp
+	      = spec_reg_info ((insn >> 12) & 15, distype);
+
+	    /* FIXME: Improve error handling; should have been caught
+	       earlier.  */
+	    if (sregp == NULL)
+	      return 2;
+
+	    /* PC is incremented by two, not one, for a byte.  Except on
+	       CRISv32, where constants are always DWORD-size for
+	       special registers.  */
+	    to_skip +=
+	      distype == cris_dis_v32 ? 4 : (sregp->reg_size + 1) & ~1;
+	  }
+	else
+	  to_skip += (mode_size + 1) & ~1;
+      }
+    else if (*s == 'n')
+      to_skip += 4;
+    else if (*s == 'b')
+      to_skip += 2;
+
+  return to_skip;
+}
+
+/* Print condition code flags.  */
+
+static char *
+print_flags (struct cris_disasm_data *disdata, unsigned int insn, char *cp)
+{
+  /* Use the v8 (Etrax 100) flag definitions for disassembly.
+     The differences with v0 (Etrax 1..4) vs. Svinto are:
+      v0 'd' <=> v8 'm'
+      v0 'e' <=> v8 'b'.
+     FIXME: Emit v0..v3 flag names somehow.  */
+  static const char v8_fnames[] = "cvznxibm";
+  static const char v32_fnames[] = "cvznxiup";
+  const char *fnames
+    = disdata->distype == cris_dis_v32 ? v32_fnames : v8_fnames;
+
+  unsigned char flagbits = (((insn >> 8) & 0xf0) | (insn & 15));
+  int i;
+
+  for (i = 0; i < 8; i++)
+    if (flagbits & (1 << i))
+      *cp++ = fnames[i];
+
+  return cp;
+}
+
+/* Print out an insn with its operands, and update the info->insn_type
+   fields.  The prefix_opcodep and the rest hold a prefix insn that is
+   supposed to be output as an address mode.  */
+
+static void
+print_with_operands (const struct cris_opcode *opcodep,
+		     unsigned int insn,
+		     unsigned char *buffer,
+		     bfd_vma addr,
+		     disassemble_info *info,
+		     /* If a prefix insn was before this insn (and is supposed
+			to be output as an address), here is a description of
+			it.  */
+		     const struct cris_opcode *prefix_opcodep,
+		     unsigned int prefix_insn,
+		     unsigned char *prefix_buffer,
+		     bfd_boolean with_reg_prefix)
+{
+  /* Get a buffer of somewhat reasonable size where we store
+     intermediate parts of the insn.  */
+  char temp[sizeof (".d [$r13=$r12-2147483648],$r10") * 2];
+  char *tp = temp;
+  static const char mode_char[] = "bwd?";
+  const char *s;
+  const char *cs;
+  struct cris_disasm_data *disdata
+    = (struct cris_disasm_data *) info->private_data;
+
+  /* Print out the name first thing we do.  */
+  (*info->fprintf_func) (info->stream, "%s", opcodep->name);
+
+  cs = opcodep->args;
+  s = cs;
+
+  /* Ignore any prefix indicator.  */
+  if (*s == 'p')
+    s++;
+
+  if (*s == 'm' || *s == 'M' || *s == 'z')
+    {
+      *tp++ = '.';
+
+      /* Get the size-letter.  */
+      *tp++ = *s == 'M'
+	? (insn & 0x8000 ? 'd'
+	   : insn & 0x4000 ? 'w' : 'b')
+	: mode_char[(insn >> 4) & (*s == 'z' ? 1 : 3)];
+
+      /* Ignore the size and the space character that follows.  */
+      s += 2;
+    }
+
+  /* Add a space if this isn't a long-branch, because for those will add
+     the condition part of the name later.  */
+  if (opcodep->match != (BRANCH_PC_LOW + BRANCH_INCR_HIGH * 256))
+    *tp++ = ' ';
+
+  /* Fill in the insn-type if deducible from the name (and there's no
+     better way).  */
+  if (opcodep->name[0] == 'j')
+    {
+      if (CONST_STRNEQ (opcodep->name, "jsr"))
+	/* It's "jsr" or "jsrc".  */
+	info->insn_type = dis_jsr;
+      else
+	/* Any other jump-type insn is considered a branch.  */
+	info->insn_type = dis_branch;
+    }
+
+  /* We might know some more fields right now.  */
+  info->branch_delay_insns = opcodep->delayed;
+
+  /* Handle operands.  */
+  for (; *s; s++)
+    {
+    switch (*s)
+      {
+      case 'T':
+	tp = format_sup_reg ((insn >> 12) & 15, tp, with_reg_prefix);
+	break;
+
+      case 'A':
+	if (with_reg_prefix)
+	  *tp++ = REGISTER_PREFIX_CHAR;
+	*tp++ = 'a';
+	*tp++ = 'c';
+	*tp++ = 'r';
+	break;
+
+      case '[':
+      case ']':
+      case ',':
+	*tp++ = *s;
+	break;
+
+      case '!':
+	/* Ignore at this point; used at earlier stages to avoid
+	   recognition if there's a prefix at something that in other
+	   ways looks like a "pop".  */
+	break;
+
+      case 'd':
+	/* Ignore.  This is an optional ".d " on the large one of
+	   relaxable insns.  */
+	break;
+
+      case 'B':
+	/* This was the prefix that made this a "push".  We've already
+	   handled it by recognizing it, so signal that the prefix is
+	   handled by setting it to NULL.  */
+	prefix_opcodep = NULL;
+	break;
+
+      case 'D':
+      case 'r':
+	tp = format_reg (disdata, insn & 15, tp, with_reg_prefix);
+	break;
+
+      case 'R':
+	tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
+	break;
+
+      case 'n':
+	{
+	  /* Like N but pc-relative to the start of the insn.  */
+	  unsigned long number
+	    = (buffer[2] + buffer[3] * 256 + buffer[4] * 65536
+	       + buffer[5] * 0x1000000 + addr);
+
+	  /* Finish off and output previous formatted bytes.  */
+	  *tp = 0;
+	  if (temp[0])
+	    (*info->fprintf_func) (info->stream, "%s", temp);
+	  tp = temp;
+
+	  (*info->print_address_func) ((bfd_vma) number, info);
+	}
+	break;
+
+      case 'u':
+	{
+	  /* Like n but the offset is bits <3:0> in the instruction.  */
+	  unsigned long number = (buffer[0] & 0xf) * 2 + addr;
+
+	  /* Finish off and output previous formatted bytes.  */
+	  *tp = 0;
+	  if (temp[0])
+	    (*info->fprintf_func) (info->stream, "%s", temp);
+	  tp = temp;
+
+	  (*info->print_address_func) ((bfd_vma) number, info);
+	}
+	break;
+
+      case 'N':
+      case 'y':
+      case 'Y':
+      case 'S':
+      case 's':
+	/* Any "normal" memory operand.  */
+	if ((insn & 0x400) && (insn & 15) == 15 && prefix_opcodep == NULL)
+	  {
+	    /* We're looking at [pc+], i.e. we need to output an immediate
+	       number, where the size can depend on different things.  */
+	    long number;
+	    int signedp
+	      = ((*cs == 'z' && (insn & 0x20))
+		 || opcodep->match == BDAP_QUICK_OPCODE);
+	    int nbytes;
+
+	    if (opcodep->imm_oprnd_size == SIZE_FIX_32)
+	      nbytes = 4;
+	    else if (opcodep->imm_oprnd_size == SIZE_SPEC_REG)
+	      {
+		const struct cris_spec_reg *sregp
+		  = spec_reg_info ((insn >> 12) & 15, disdata->distype);
+
+		/* A NULL return should have been as a non-match earlier,
+		   so catch it as an internal error in the error-case
+		   below.  */
+		if (sregp == NULL)
+		  /* Whatever non-valid size.  */
+		  nbytes = 42;
+		else
+		  /* PC is always incremented by a multiple of two.
+		     For CRISv32, immediates are always 4 bytes for
+		     special registers.  */
+		  nbytes = disdata->distype == cris_dis_v32
+		    ? 4 : (sregp->reg_size + 1) & ~1;
+	      }
+	    else
+	      {
+		int mode_size = 1 << ((insn >> 4) & (*cs == 'z' ? 1 : 3));
+
+		if (mode_size == 1)
+		  nbytes = 2;
+		else
+		  nbytes = mode_size;
+	      }
+
+	    switch (nbytes)
+	      {
+	      case 1:
+		number = buffer[2];
+		if (signedp && number > 127)
+		  number -= 256;
+		break;
+
+	      case 2:
+		number = buffer[2] + buffer[3] * 256;
+		if (signedp && number > 32767)
+		  number -= 65536;
+		break;
+
+	      case 4:
+		number
+		  = buffer[2] + buffer[3] * 256 + buffer[4] * 65536
+		  + buffer[5] * 0x1000000;
+		break;
+
+	      default:
+		strcpy (tp, "bug");
+		tp += 3;
+		number = 42;
+	      }
+
+	    if ((*cs == 'z' && (insn & 0x20))
+		|| (opcodep->match == BDAP_QUICK_OPCODE
+		    && (nbytes <= 2 || buffer[1 + nbytes] == 0)))
+	      tp = format_dec (number, tp, signedp);
+	    else
+	      {
+		unsigned int highbyte = (number >> 24) & 0xff;
+
+		/* Either output this as an address or as a number.  If it's
+		   a dword with the same high-byte as the address of the
+		   insn, assume it's an address, and also if it's a non-zero
+		   non-0xff high-byte.  If this is a jsr or a jump, then
+		   it's definitely an address.  */
+		if (nbytes == 4
+		    && (highbyte == ((addr >> 24) & 0xff)
+			|| (highbyte != 0 && highbyte != 0xff)
+			|| info->insn_type == dis_branch
+			|| info->insn_type == dis_jsr))
+		  {
+		    /* Finish off and output previous formatted bytes.  */
+		    *tp = 0;
+		    tp = temp;
+		    if (temp[0])
+		      (*info->fprintf_func) (info->stream, "%s", temp);
+
+		    (*info->print_address_func) ((bfd_vma) number, info);
+
+		    info->target = number;
+		  }
+		else
+		  tp = format_hex (number, tp, disdata);
+	      }
+	  }
+	else
+	  {
+	    /* Not an immediate number.  Then this is a (possibly
+	       prefixed) memory operand.  */
+	    if (info->insn_type != dis_nonbranch)
+	      {
+		int mode_size
+		  = 1 << ((insn >> 4)
+			  & (opcodep->args[0] == 'z' ? 1 : 3));
+		int size;
+		info->insn_type = dis_dref;
+		info->flags |= CRIS_DIS_FLAG_MEMREF;
+
+		if (opcodep->imm_oprnd_size == SIZE_FIX_32)
+		  size = 4;
+		else if (opcodep->imm_oprnd_size == SIZE_SPEC_REG)
+		  {
+		    const struct cris_spec_reg *sregp
+		      = spec_reg_info ((insn >> 12) & 15, disdata->distype);
+
+		    /* FIXME: Improve error handling; should have been caught
+		       earlier.  */
+		    if (sregp == NULL)
+		      size = 4;
+		    else
+		      size = sregp->reg_size;
+		  }
+		else
+		  size = mode_size;
+
+		info->data_size = size;
+	      }
+
+	    *tp++ = '[';
+
+	    if (prefix_opcodep
+		/* We don't match dip with a postincremented field
+		   as a side-effect address mode.  */
+		&& ((insn & 0x400) == 0
+		    || prefix_opcodep->match != DIP_OPCODE))
+	      {
+		if (insn & 0x400)
+		  {
+		    tp = format_reg (disdata, insn & 15, tp, with_reg_prefix);
+		    *tp++ = '=';
+		  }
+
+
+		/* We mainly ignore the prefix format string when the
+		   address-mode syntax is output.  */
+		switch (prefix_opcodep->match)
+		  {
+		  case DIP_OPCODE:
+		    /* It's [r], [r+] or [pc+].  */
+		    if ((prefix_insn & 0x400) && (prefix_insn & 15) == 15)
+		      {
+			/* It's [pc+].  This cannot possibly be anything
+			   but an address.  */
+			unsigned long number
+			  = prefix_buffer[2] + prefix_buffer[3] * 256
+			  + prefix_buffer[4] * 65536
+			  + prefix_buffer[5] * 0x1000000;
+
+			info->target = (bfd_vma) number;
+
+			/* Finish off and output previous formatted
+			   data.  */
+			*tp = 0;
+			tp = temp;
+			if (temp[0])
+			  (*info->fprintf_func) (info->stream, "%s", temp);
+
+			(*info->print_address_func) ((bfd_vma) number, info);
+		      }
+		    else
+		      {
+			/* For a memref in an address, we use target2.
+			   In this case, target is zero.  */
+			info->flags
+			  |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
+			      | CRIS_DIS_FLAG_MEM_TARGET2_MEM);
+
+			info->target2 = prefix_insn & 15;
+
+			*tp++ = '[';
+			tp = format_reg (disdata, prefix_insn & 15, tp,
+					 with_reg_prefix);
+			if (prefix_insn & 0x400)
+			  *tp++ = '+';
+			*tp++ = ']';
+		      }
+		    break;
+
+		  case BDAP_QUICK_OPCODE:
+		    {
+		      int number;
+
+		      number = prefix_buffer[0];
+		      if (number > 127)
+			number -= 256;
+
+		      /* Output "reg+num" or, if num < 0, "reg-num".  */
+		      tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp,
+				       with_reg_prefix);
+		      if (number >= 0)
+			*tp++ = '+';
+		      tp = format_dec (number, tp, 1);
+
+		      info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
+		      info->target = (prefix_insn >> 12) & 15;
+		      info->target2 = (bfd_vma) number;
+		      break;
+		    }
+
+		  case BIAP_OPCODE:
+		    /* Output "r+R.m".  */
+		    tp = format_reg (disdata, prefix_insn & 15, tp,
+				     with_reg_prefix);
+		    *tp++ = '+';
+		    tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp,
+				     with_reg_prefix);
+		    *tp++ = '.';
+		    *tp++ = mode_char[(prefix_insn >> 4) & 3];
+
+		    info->flags
+		      |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
+			  | CRIS_DIS_FLAG_MEM_TARGET_IS_REG
+
+			  | ((prefix_insn & 0x8000)
+			     ? CRIS_DIS_FLAG_MEM_TARGET2_MULT4
+			     : ((prefix_insn & 0x8000)
+				? CRIS_DIS_FLAG_MEM_TARGET2_MULT2 : 0)));
+
+		    /* Is it the casejump?  It's a "adds.w [pc+r%d.w],pc".  */
+		    if (insn == 0xf83f && (prefix_insn & ~0xf000) == 0x55f)
+		      /* Then start interpreting data as offsets.  */
+		      case_offset_counter = no_of_case_offsets;
+		    break;
+
+		  case BDAP_INDIR_OPCODE:
+		    /* Output "r+s.m", or, if "s" is [pc+], "r+s" or
+		       "r-s".  */
+		    tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp,
+				     with_reg_prefix);
+
+		    if ((prefix_insn & 0x400) && (prefix_insn & 15) == 15)
+		      {
+			long number;
+			unsigned int nbytes;
+
+			/* It's a value.  Get its size.  */
+			int mode_size = 1 << ((prefix_insn >> 4) & 3);
+
+			if (mode_size == 1)
+			  nbytes = 2;
+			else
+			  nbytes = mode_size;
+
+			switch (nbytes)
+			  {
+			  case 1:
+			    number = prefix_buffer[2];
+			    if (number > 127)
+			      number -= 256;
+			    break;
+
+			  case 2:
+			    number = prefix_buffer[2] + prefix_buffer[3] * 256;
+			    if (number > 32767)
+			      number -= 65536;
+			    break;
+
+			  case 4:
+			    number
+			      = prefix_buffer[2] + prefix_buffer[3] * 256
+			      + prefix_buffer[4] * 65536
+			      + prefix_buffer[5] * 0x1000000;
+			    break;
+
+			  default:
+			    strcpy (tp, "bug");
+			    tp += 3;
+			    number = 42;
+			  }
+
+			info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
+			info->target2 = (bfd_vma) number;
+
+			/* If the size is dword, then assume it's an
+			   address.  */
+			if (nbytes == 4)
+			  {
+			    /* Finish off and output previous formatted
+			       bytes.  */
+			    *tp++ = '+';
+			    *tp = 0;
+			    tp = temp;
+			    (*info->fprintf_func) (info->stream, "%s", temp);
+
+			    (*info->print_address_func) ((bfd_vma) number, info);
+			  }
+			else
+			  {
+			    if (number >= 0)
+			      *tp++ = '+';
+			    tp = format_dec (number, tp, 1);
+			  }
+		      }
+		    else
+		      {
+			/* Output "r+[R].m" or "r+[R+].m".  */
+			*tp++ = '+';
+			*tp++ = '[';
+			tp = format_reg (disdata, prefix_insn & 15, tp,
+					 with_reg_prefix);
+			if (prefix_insn & 0x400)
+			  *tp++ = '+';
+			*tp++ = ']';
+			*tp++ = '.';
+			*tp++ = mode_char[(prefix_insn >> 4) & 3];
+
+			info->flags
+			  |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
+			      | CRIS_DIS_FLAG_MEM_TARGET2_MEM
+			      | CRIS_DIS_FLAG_MEM_TARGET_IS_REG
+
+			      | (((prefix_insn >> 4) == 2)
+				 ? 0
+				 : (((prefix_insn >> 4) & 3) == 1
+				    ? CRIS_DIS_FLAG_MEM_TARGET2_MEM_WORD
+				    : CRIS_DIS_FLAG_MEM_TARGET2_MEM_BYTE)));
+		      }
+		    break;
+
+		  default:
+		    (*info->fprintf_func) (info->stream, "?prefix-bug");
+		  }
+
+		/* To mark that the prefix is used, reset it.  */
+		prefix_opcodep = NULL;
+	      }
+	    else
+	      {
+		tp = format_reg (disdata, insn & 15, tp, with_reg_prefix);
+
+		info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
+		info->target = insn & 15;
+
+		if (insn & 0x400)
+		  *tp++ = '+';
+	      }
+	    *tp++ = ']';
+	  }
+	break;
+
+      case 'x':
+	tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
+	*tp++ = '.';
+	*tp++ = mode_char[(insn >> 4) & 3];
+	break;
+
+      case 'I':
+	tp = format_dec (insn & 63, tp, 0);
+	break;
+
+      case 'b':
+	{
+	  int where = buffer[2] + buffer[3] * 256;
+
+	  if (where > 32767)
+	    where -= 65536;
+
+	  where += addr + ((disdata->distype == cris_dis_v32) ? 0 : 4);
+
+	  if (insn == BA_PC_INCR_OPCODE)
+	    info->insn_type = dis_branch;
+	  else
+	    info->insn_type = dis_condbranch;
+
+	  info->target = (bfd_vma) where;
+
+	  *tp = 0;
+	  tp = temp;
+	  (*info->fprintf_func) (info->stream, "%s%s ",
+				 temp, cris_cc_strings[insn >> 12]);
+
+	  (*info->print_address_func) ((bfd_vma) where, info);
+	}
+      break;
+
+    case 'c':
+      tp = format_dec (insn & 31, tp, 0);
+      break;
+
+    case 'C':
+      tp = format_dec (insn & 15, tp, 0);
+      break;
+
+    case 'o':
+      {
+	long offset = insn & 0xfe;
+	bfd_vma target;
+
+	if (insn & 1)
+	  offset |= ~0xff;
+
+	if (opcodep->match == BA_QUICK_OPCODE)
+	  info->insn_type = dis_branch;
+	else
+	  info->insn_type = dis_condbranch;
+
+	target = addr + ((disdata->distype == cris_dis_v32) ? 0 : 2) + offset;
+	info->target = target;
+	*tp = 0;
+	tp = temp;
+	(*info->fprintf_func) (info->stream, "%s", temp);
+	(*info->print_address_func) (target, info);
+      }
+      break;
+
+    case 'Q':
+    case 'O':
+      {
+	long number = buffer[0];
+
+	if (number > 127)
+	  number = number - 256;
+
+	tp = format_dec (number, tp, 1);
+	*tp++ = ',';
+	tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
+      }
+      break;
+
+    case 'f':
+      tp = print_flags (disdata, insn, tp);
+      break;
+
+    case 'i':
+      tp = format_dec ((insn & 32) ? (insn & 31) | ~31L : insn & 31, tp, 1);
+      break;
+
+    case 'P':
+      {
+	const struct cris_spec_reg *sregp
+	  = spec_reg_info ((insn >> 12) & 15, disdata->distype);
+
+	if (sregp->name == NULL)
+	  /* Should have been caught as a non-match eariler.  */
+	  *tp++ = '?';
+	else
+	  {
+	    if (with_reg_prefix)
+	      *tp++ = REGISTER_PREFIX_CHAR;
+	    strcpy (tp, sregp->name);
+	    tp += strlen (tp);
+	  }
+      }
+      break;
+
+    default:
+      strcpy (tp, "???");
+      tp += 3;
+    }
+  }
+
+  *tp = 0;
+
+  if (prefix_opcodep)
+    (*info->fprintf_func) (info->stream, " (OOPS unused prefix \"%s: %s\")",
+			   prefix_opcodep->name, prefix_opcodep->args);
+
+  (*info->fprintf_func) (info->stream, "%s", temp);
+
+  /* Get info for matching case-tables, if we don't have any active.
+     We assume that the last constant seen is used; either in the insn
+     itself or in a "move.d const,rN, sub.d rN,rM"-like sequence.  */
+  if (TRACE_CASE && case_offset_counter == 0)
+    {
+      if (CONST_STRNEQ (opcodep->name, "sub"))
+	case_offset = last_immediate;
+
+      /* It could also be an "add", if there are negative case-values.  */
+      else if (CONST_STRNEQ (opcodep->name, "add"))
+	/* The first case is the negated operand to the add.  */
+	case_offset = -last_immediate;
+
+      /* A bound insn will tell us the number of cases.  */
+      else if (CONST_STRNEQ (opcodep->name, "bound"))
+	no_of_case_offsets = last_immediate + 1;
+
+      /* A jump or jsr or branch breaks the chain of insns for a
+	 case-table, so assume default first-case again.  */
+      else if (info->insn_type == dis_jsr
+	       || info->insn_type == dis_branch
+	       || info->insn_type == dis_condbranch)
+	case_offset = 0;
+    }
+}
+
+
+/* Print the CRIS instruction at address memaddr on stream.  Returns
+   length of the instruction, in bytes.  Prefix register names with `$' if
+   WITH_REG_PREFIX.  */
+
+static int
+print_insn_cris_generic (bfd_vma memaddr,
+			 disassemble_info *info,
+			 bfd_boolean with_reg_prefix)
+{
+  int nbytes;
+  unsigned int insn;
+  const struct cris_opcode *matchedp;
+  int advance = 0;
+  struct cris_disasm_data *disdata
+    = (struct cris_disasm_data *) info->private_data;
+
+  /* No instruction will be disassembled as longer than this number of
+     bytes; stacked prefixes will not be expanded.  */
+  unsigned char buffer[MAX_BYTES_PER_CRIS_INSN];
+  unsigned char *bufp;
+  int status = 0;
+  bfd_vma addr;
+
+  /* There will be an "out of range" error after the last instruction.
+     Reading pairs of bytes in decreasing number, we hope that we will get
+     at least the amount that we will consume.
+
+     If we can't get any data, or we do not get enough data, we print
+     the error message.  */
+
+  for (nbytes = MAX_BYTES_PER_CRIS_INSN; nbytes > 0; nbytes -= 2)
+    {
+      status = (*info->read_memory_func) (memaddr, buffer, nbytes, info);
+      if (status == 0)
+	break;
+    }
+
+  /* If we did not get all we asked for, then clear the rest.
+     Hopefully this makes a reproducible result in case of errors.  */
+  if (nbytes != MAX_BYTES_PER_CRIS_INSN)
+    memset (buffer + nbytes, 0, MAX_BYTES_PER_CRIS_INSN - nbytes);
+
+  addr = memaddr;
+  bufp = buffer;
+
+  /* Set some defaults for the insn info.  */
+  info->insn_info_valid = 1;
+  info->branch_delay_insns = 0;
+  info->data_size = 0;
+  info->insn_type = dis_nonbranch;
+  info->flags = 0;
+  info->target = 0;
+  info->target2 = 0;
+
+  /* If we got any data, disassemble it.  */
+  if (nbytes != 0)
+    {
+      matchedp = NULL;
+
+      insn = bufp[0] + bufp[1] * 256;
+
+      /* If we're in a case-table, don't disassemble the offsets.  */
+      if (TRACE_CASE && case_offset_counter != 0)
+	{
+	  info->insn_type = dis_noninsn;
+	  advance += 2;
+
+	  /* If to print data as offsets, then shortcut here.  */
+	  (*info->fprintf_func) (info->stream, "case %ld%s: -> ",
+				 case_offset + no_of_case_offsets
+				 - case_offset_counter,
+				 case_offset_counter == 1 ? "/default" :
+				 "");
+
+	  (*info->print_address_func) ((bfd_vma)
+				       ((short) (insn)
+					+ (long) (addr
+						  - (no_of_case_offsets
+						     - case_offset_counter)
+						  * 2)), info);
+	  case_offset_counter--;
+
+	  /* The default case start (without a "sub" or "add") must be
+	     zero.  */
+	  if (case_offset_counter == 0)
+	    case_offset = 0;
+	}
+      else if (insn == 0)
+	{
+	  /* We're often called to disassemble zeroes.  While this is a
+	     valid "bcc .+2" insn, it is also useless enough and enough
+	     of a nuiscance that we will just output "bcc .+2" for it
+	     and signal it as a noninsn.  */
+	  (*info->fprintf_func) (info->stream,
+				 disdata->distype == cris_dis_v32
+				 ? "bcc ." : "bcc .+2");
+	  info->insn_type = dis_noninsn;
+	  advance += 2;
+	}
+      else
+	{
+	  const struct cris_opcode *prefix_opcodep = NULL;
+	  unsigned char *prefix_buffer = bufp;
+	  unsigned int prefix_insn = insn;
+	  int prefix_size = 0;
+
+	  matchedp = get_opcode_entry (insn, NO_CRIS_PREFIX, disdata);
+
+	  /* Check if we're supposed to write out prefixes as address
+	     modes and if this was a prefix.  */
+	  if (matchedp != NULL && PARSE_PREFIX && matchedp->args[0] == 'p')
+	    {
+	      /* If it's a prefix, put it into the prefix vars and get the
+		 main insn.  */
+	      prefix_size = bytes_to_skip (prefix_insn, matchedp,
+					   disdata->distype, NULL);
+	      prefix_opcodep = matchedp;
+
+	      insn = bufp[prefix_size] + bufp[prefix_size + 1] * 256;
+	      matchedp = get_opcode_entry (insn, prefix_insn, disdata);
+
+	      if (matchedp != NULL)
+		{
+		  addr += prefix_size;
+		  bufp += prefix_size;
+		  advance += prefix_size;
+		}
+	      else
+		{
+		  /* The "main" insn wasn't valid, at least not when
+		     prefixed.  Put back things enough to output the
+		     prefix insn only, as a normal insn.  */
+		  matchedp = prefix_opcodep;
+		  insn = prefix_insn;
+		  prefix_opcodep = NULL;
+		}
+	    }
+
+	  if (matchedp == NULL)
+	    {
+	      (*info->fprintf_func) (info->stream, "??0x%x", insn);
+	      advance += 2;
+
+	      info->insn_type = dis_noninsn;
+	    }
+	  else
+	    {
+	      advance
+		+= bytes_to_skip (insn, matchedp, disdata->distype,
+				  prefix_opcodep);
+
+	      /* The info_type and assorted fields will be set according
+		 to the operands.   */
+	      print_with_operands (matchedp, insn, bufp, addr, info,
+				   prefix_opcodep, prefix_insn,
+				   prefix_buffer, with_reg_prefix);
+	    }
+	}
+    }
+  else
+    info->insn_type = dis_noninsn;
+
+  /* If we read less than MAX_BYTES_PER_CRIS_INSN, i.e. we got an error
+     status when reading that much, and the insn decoding indicated a
+     length exceeding what we read, there is an error.  */
+  if (status != 0 && (nbytes == 0 || advance > nbytes))
+    {
+      (*info->memory_error_func) (status, memaddr, info);
+      return -1;
+    }
+
+  /* Max supported insn size with one folded prefix insn.  */
+  info->bytes_per_line = MAX_BYTES_PER_CRIS_INSN;
+
+  /* I would like to set this to a fixed value larger than the actual
+     number of bytes to print in order to avoid spaces between bytes,
+     but objdump.c (2.9.1) does not like that, so we print 16-bit
+     chunks, which is the next choice.  */
+  info->bytes_per_chunk = 2;
+
+  /* Printing bytes in order of increasing addresses makes sense,
+     especially on a little-endian target.
+     This is completely the opposite of what you think; setting this to
+     BFD_ENDIAN_LITTLE will print bytes in order N..0 rather than the 0..N
+     we want.  */
+  info->display_endian = BFD_ENDIAN_BIG;
+
+  return advance;
+}
+
+/* Disassemble, prefixing register names with `$'.  CRIS v0..v10.  */
+#if 0
+static int
+print_insn_cris_with_register_prefix (bfd_vma vma,
+				      disassemble_info *info)
+{
+  if (info->private_data == NULL
+      && !cris_parse_disassembler_options (info, cris_dis_v0_v10))
+    return -1;
+  return print_insn_cris_generic (vma, info, TRUE);
+}
+#endif
+/* Disassemble, prefixing register names with `$'.  CRIS v32.  */
+
+static int
+print_insn_crisv32_with_register_prefix (bfd_vma vma,
+					 disassemble_info *info)
+{
+  if (info->private_data == NULL
+      && !cris_parse_disassembler_options (info, cris_dis_v32))
+    return -1;
+  return print_insn_cris_generic (vma, info, TRUE);
+}
+
+#if 0
+/* Disassemble, prefixing register names with `$'.
+   Common v10 and v32 subset.  */
+
+static int
+print_insn_crisv10_v32_with_register_prefix (bfd_vma vma,
+					     disassemble_info *info)
+{
+  if (info->private_data == NULL
+      && !cris_parse_disassembler_options (info, cris_dis_common_v10_v32))
+    return -1;
+  return print_insn_cris_generic (vma, info, TRUE);
+}
+
+/* Disassemble, no prefixes on register names.  CRIS v0..v10.  */
+
+static int
+print_insn_cris_without_register_prefix (bfd_vma vma,
+					 disassemble_info *info)
+{
+  if (info->private_data == NULL
+      && !cris_parse_disassembler_options (info, cris_dis_v0_v10))
+    return -1;
+  return print_insn_cris_generic (vma, info, FALSE);
+}
+
+/* Disassemble, no prefixes on register names.  CRIS v32.  */
+
+static int
+print_insn_crisv32_without_register_prefix (bfd_vma vma,
+					    disassemble_info *info)
+{
+  if (info->private_data == NULL
+      && !cris_parse_disassembler_options (info, cris_dis_v32))
+    return -1;
+  return print_insn_cris_generic (vma, info, FALSE);
+}
+
+/* Disassemble, no prefixes on register names.
+   Common v10 and v32 subset.  */
+
+static int
+print_insn_crisv10_v32_without_register_prefix (bfd_vma vma,
+						disassemble_info *info)
+{
+  if (info->private_data == NULL
+      && !cris_parse_disassembler_options (info, cris_dis_common_v10_v32))
+    return -1;
+  return print_insn_cris_generic (vma, info, FALSE);
+}
+#endif
+
+int
+print_insn_crisv32 (bfd_vma vma,
+		    disassemble_info *info)
+{
+  return print_insn_crisv32_with_register_prefix(vma, info);
+}
+
+/* Return a disassembler-function that prints registers with a `$' prefix,
+   or one that prints registers without a prefix.
+   FIXME: We should improve the solution to avoid the multitude of
+   functions seen above.  */
+#if 0
+disassembler_ftype
+cris_get_disassembler (bfd *abfd)
+{
+  /* If there's no bfd in sight, we return what is valid as input in all
+     contexts if fed back to the assembler: disassembly *with* register
+     prefix.  Unfortunately this will be totally wrong for v32.  */
+  if (abfd == NULL)
+    return print_insn_cris_with_register_prefix;
+
+  if (bfd_get_symbol_leading_char (abfd) == 0)
+    {
+      if (bfd_get_mach (abfd) == bfd_mach_cris_v32)
+	return print_insn_crisv32_with_register_prefix;
+      if (bfd_get_mach (abfd) == bfd_mach_cris_v10_v32)
+	return print_insn_crisv10_v32_with_register_prefix;
+
+      /* We default to v10.  This may be specifically specified in the
+	 bfd mach, but is also the default setting.  */
+      return print_insn_cris_with_register_prefix;
+    }
+
+  if (bfd_get_mach (abfd) == bfd_mach_cris_v32)
+    return print_insn_crisv32_without_register_prefix;
+  if (bfd_get_mach (abfd) == bfd_mach_cris_v10_v32)
+    return print_insn_crisv10_v32_without_register_prefix;
+  return print_insn_cris_without_register_prefix;
+}
+#endif
+/* Local variables:
+   eval: (c-set-style "gnu")
+   indent-tabs-mode: t
+   End:  */

Modified: trunk/src/host/qemu-neo1973/darwin-user/main.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/main.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/darwin-user/main.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -124,47 +124,47 @@
     return cpu_ppc_get_tb(env) >> 32;
 }
 
-static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
+uint32_t cpu_ppc_load_atbl (CPUState *env)
 {
-    /* TO FIX */
+    return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
 }
 
-void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
+uint32_t cpu_ppc_load_atbu (CPUState *env)
 {
-    cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
+    return cpu_ppc_get_tb(env) >> 32;
 }
 
-void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
+uint32_t cpu_ppc601_load_rtcu (CPUState *env)
 {
-    cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
+    cpu_ppc_load_tbu(env);
 }
 
-uint32_t cpu_ppc_load_decr (CPUState *env)
+uint32_t cpu_ppc601_load_rtcl (CPUState *env)
 {
-    /* TO FIX */
-    return -1;
+    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
 }
 
-void cpu_ppc_store_decr (CPUState *env, uint32_t value)
+/* XXX: to be fixed */
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
 {
-    /* TO FIX */
+    return -1;
 }
 
-void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
 {
-    cpu_ppc_store_tbu( env, value );
+    return -1;
 }
 
-uint32_t cpu_ppc601_load_rtcu (CPUState *env)
-{
-    cpu_ppc_load_tbu(env);
-}
+#define EXCP_DUMP(env, fmt, args...)                                         \
+do {                                                                          \
+    fprintf(stderr, fmt , ##args);                                            \
+    cpu_dump_state(env, stderr, fprintf, 0);                                  \
+    if (loglevel != 0) {                                                      \
+        fprintf(logfile, fmt , ##args);                                       \
+        cpu_dump_state(env, logfile, fprintf, 0);                             \
+    }                                                                         \
+} while (0)
 
-uint32_t cpu_ppc601_load_rtcl (CPUState *env)
-{
-    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
-}
-
 void cpu_loop(CPUPPCState *env)
 {
     int trapnr;
@@ -173,271 +173,363 @@
 
     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:
+        case POWERPC_EXCP_NONE:
+            /* Just go on */
             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;
+        case POWERPC_EXCP_CRITICAL: /* Critical input                        */
+            cpu_abort(env, "Critical interrupt while in user mode. "
+                      "Aborting\n");
             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:
+        case POWERPC_EXCP_MCHECK:   /* Machine check exception               */
+            cpu_abort(env, "Machine check exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_DSI:      /* Data storage exception                */
 #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]);
-            }
+            EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n",
+                      env->spr[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");
+        case POWERPC_EXCP_ISI:      /* Instruction storage exception         */
+            EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",
+                      env->spr[SPR_DAR]);
             /* 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;
+        case POWERPC_EXCP_EXTERNAL: /* External input                        */
+            cpu_abort(env, "External interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_ALIGN:    /* Alignment exception                   */
+            EXCP_DUMP(env, "Unaligned memory access\n");
             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:
+        case POWERPC_EXCP_PROGRAM:  /* Program exception                     */
+            /* XXX: check this */
             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);
+            case POWERPC_EXCP_FP:
+                EXCP_DUMP(env, "Floating point program exception\n");
+                /* Set FX */
+                info.si_signo = SIGFPE;
+                info.si_errno = 0;
+                switch (env->error_code & 0xF) {
+                case POWERPC_EXCP_FP_OX:
+                    info.si_code = FPE_FLTOVF;
                     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();
+                case POWERPC_EXCP_FP_UX:
+                    info.si_code = FPE_FLTUND;
+                    break;
+                case POWERPC_EXCP_FP_ZX:
+                case POWERPC_EXCP_FP_VXZDZ:
+                    info.si_code = FPE_FLTDIV;
+                    break;
+                case POWERPC_EXCP_FP_XX:
+                    info.si_code = FPE_FLTRES;
+                    break;
+                case POWERPC_EXCP_FP_VXSOFT:
+                    info.si_code = FPE_FLTINV;
+                    break;
+                case POWERPC_EXCP_FP_VXSNAN:
+                case POWERPC_EXCP_FP_VXISI:
+                case POWERPC_EXCP_FP_VXIDI:
+                case POWERPC_EXCP_FP_VXIMZ:
+                case POWERPC_EXCP_FP_VXVC:
+                case POWERPC_EXCP_FP_VXSQRT:
+                case POWERPC_EXCP_FP_VXCVI:
+                    info.si_code = FPE_FLTSUB;
+                    break;
                 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();
+                    EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
+                              env->error_code);
+                    break;
+                }
+                break;
+            case POWERPC_EXCP_INVAL:
+                EXCP_DUMP(env, "Invalid instruction\n");
+                info.si_signo = SIGILL;
+                info.si_errno = 0;
+                switch (env->error_code & 0xF) {
+                case POWERPC_EXCP_INVAL_INVAL:
+                    info.si_code = ILL_ILLOPC;
+                    break;
+                case POWERPC_EXCP_INVAL_LSWX:
+                    info.si_code = ILL_ILLOPN;
+                    break;
+                case POWERPC_EXCP_INVAL_SPR:
+                    info.si_code = ILL_PRVREG;
+                    break;
+                case POWERPC_EXCP_INVAL_FP:
+                    info.si_code = ILL_COPROC;
+                    break;
+                default:
+                    EXCP_DUMP(env, "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 POWERPC_EXCP_PRIV:
+                EXCP_DUMP(env, "Privilege violation\n");
+                info.si_signo = SIGILL;
+                info.si_errno = 0;
+                switch (env->error_code & 0xF) {
+                case POWERPC_EXCP_PRIV_OPC:
+                    info.si_code = ILL_PRVOPC;
+                    break;
+                case POWERPC_EXCP_PRIV_REG:
+                    info.si_code = ILL_PRVREG;
+                    break;
+                default:
+                    EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
+                              env->error_code & 0xF);
+                    info.si_code = ILL_PRVOPC;
+                    break;
+                }
+                break;
+            case POWERPC_EXCP_TRAP:
+                cpu_abort(env, "Tried to call a TRAP\n");
+                break;
+            default:
+                /* Should not happen ! */
+                cpu_abort(env, "Unknown program exception (%02x)\n",
+                          env->error_code);
+                break;
             }
             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;
+        case POWERPC_EXCP_FPU:      /* Floating-point unavailable exception  */
+            EXCP_DUMP(env, "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 */
+        case POWERPC_EXCP_SYSCALL:  /* System call exception                 */
+            cpu_abort(env, "Syscall exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_APU:      /* Auxiliary processor unavailable       */
+            EXCP_DUMP(env, "No APU instruction 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 POWERPC_EXCP_DECR:     /* Decrementer exception                 */
+            cpu_abort(env, "Decrementer interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_FIT:      /* Fixed-interval timer interrupt        */
+            cpu_abort(env, "Fix interval timer interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_WDT:      /* Watchdog timer interrupt              */
+            cpu_abort(env, "Watchdog timer interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_DTLB:     /* Data TLB error                        */
+            cpu_abort(env, "Data TLB exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_ITLB:     /* Instruction TLB error                 */
+            cpu_abort(env, "Instruction TLB exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_DEBUG:    /* Debug interrupt                       */
             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();
+#if defined(TARGET_PPCEMB)
+        case POWERPC_EXCP_SPEU:     /* SPE/embedded floating-point unavail.  */
+            EXCP_DUMP(env, "No SPE/floating-point instruction 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 POWERPC_EXCP_EFPDI:    /* Embedded floating-point data IRQ      */
+            cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
+            break;
+        case POWERPC_EXCP_EFPRI:    /* Embedded floating-point round IRQ     */
+            cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
+            break;
+        case POWERPC_EXCP_EPERFM:   /* Embedded performance monitor IRQ      */
+            cpu_abort(env, "Performance monitor exception not handled\n");
+            break;
+        case POWERPC_EXCP_DOORI:    /* Embedded doorbell interrupt           */
+            cpu_abort(env, "Doorbell interrupt while in user mode. "
+                       "Aborting\n");
+            break;
+        case POWERPC_EXCP_DOORCI:   /* Embedded doorbell critical interrupt  */
+            cpu_abort(env, "Doorbell critical interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+#endif /* defined(TARGET_PPCEMB) */
+        case POWERPC_EXCP_RESET:    /* System reset exception                */
+            cpu_abort(env, "Reset interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+#if defined(TARGET_PPC64) /* PowerPC 64 */
+        case POWERPC_EXCP_DSEG:     /* Data segment exception                */
+            cpu_abort(env, "Data segment exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_ISEG:     /* Instruction segment exception         */
+            cpu_abort(env, "Instruction segment exception "
+                      "while in user mode. Aborting\n");
+            break;
+#endif /* defined(TARGET_PPC64) */
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+        case POWERPC_EXCP_HDECR:    /* Hypervisor decrementer exception      */
+            cpu_abort(env, "Hypervisor decrementer interrupt "
+                      "while in user mode. Aborting\n");
+            break;
+#endif /* defined(TARGET_PPC64H) */
+        case POWERPC_EXCP_TRACE:    /* Trace exception                       */
+            /* Nothing to do:
+             * we use this exception to emulate step-by-step execution mode.
+             */
+            break;
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+        case POWERPC_EXCP_HDSI:     /* Hypervisor data storage exception     */
+            cpu_abort(env, "Hypervisor data storage exception "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_HISI:     /* Hypervisor instruction storage excp   */
+            cpu_abort(env, "Hypervisor instruction storage exception "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_HDSEG:    /* Hypervisor data segment exception     */
+            cpu_abort(env, "Hypervisor data segment exception "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_HISEG:    /* Hypervisor instruction segment excp   */
+            cpu_abort(env, "Hypervisor instruction segment exception "
+                      "while in user mode. Aborting\n");
+            break;
+#endif /* defined(TARGET_PPC64H) */
+        case POWERPC_EXCP_VPU:      /* Vector unavailable exception          */
+            EXCP_DUMP(env, "No Altivec instructions 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 POWERPC_EXCP_PIT:      /* Programmable interval timer IRQ       */
+            cpu_abort(env, "Programable interval timer interrupt "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_IO:       /* IO error exception                    */
+            cpu_abort(env, "IO error exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_RUNM:     /* Run mode exception                    */
+            cpu_abort(env, "Run mode exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_EMUL:     /* Emulation trap exception              */
+            cpu_abort(env, "Emulation trap exception not handled\n");
+            break;
+        case POWERPC_EXCP_IFTLB:    /* Instruction fetch TLB error           */
+            cpu_abort(env, "Instruction fetch TLB exception "
+                      "while in user-mode. Aborting");
+            break;
+        case POWERPC_EXCP_DLTLB:    /* Data load TLB miss                    */
+            cpu_abort(env, "Data load TLB exception while in user-mode. "
+                      "Aborting");
+            break;
+        case POWERPC_EXCP_DSTLB:    /* Data store TLB miss                   */
+            cpu_abort(env, "Data store TLB exception while in user-mode. "
+                      "Aborting");
+            break;
+        case POWERPC_EXCP_FPA:      /* Floating-point assist exception       */
+            cpu_abort(env, "Floating-point assist exception not handled\n");
+            break;
+        case POWERPC_EXCP_IABR:     /* Instruction address breakpoint        */
+            cpu_abort(env, "Instruction address breakpoint exception "
+                      "not handled\n");
+            break;
+        case POWERPC_EXCP_SMI:      /* System management interrupt           */
+            cpu_abort(env, "System management interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_THERM:    /* Thermal interrupt                     */
+            cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_PERFM:    /* Embedded performance monitor IRQ      */
+            cpu_abort(env, "Performance monitor exception not handled\n");
+            break;
+        case POWERPC_EXCP_VPUA:     /* Vector assist exception               */
+            cpu_abort(env, "Vector assist exception not handled\n");
+            break;
+        case POWERPC_EXCP_SOFTP:    /* Soft patch exception                  */
+            cpu_abort(env, "Soft patch exception not handled\n");
+            break;
+        case POWERPC_EXCP_MAINT:    /* Maintenance exception                 */
+            cpu_abort(env, "Maintenance exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_STOP:     /* stop translation                      */
+            /* We did invalidate the instruction cache. Go on */
+            break;
+        case POWERPC_EXCP_BRANCH:   /* branch instruction:                   */
+            /* We just stopped because of a branch. Go on */
+            break;
+        case POWERPC_EXCP_SYSCALL_USER:
+            /* system call in user-mode emulation */
+            /* 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_BRANCH:
-            /* We stopped because of a jump... */
-            break;
         case EXCP_INTERRUPT:
-            /* Don't know why this should ever happen... */
-            fprintf(stderr, "EXCP_INTERRUPT\n");
+            /* just indicate that signals should be handled asap */
             break;
-        case EXCP_DEBUG:
-            gdb_handlesig (env, SIGTRAP);
+        default:
+            cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
             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);
     }

Modified: trunk/src/host/qemu-neo1973/dis-asm.h
===================================================================
--- trunk/src/host/qemu-neo1973/dis-asm.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/dis-asm.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -200,6 +200,10 @@
 #define bfd_mach_m32r          0  /* backwards compatibility */
   bfd_arch_mn10200,    /* Matsushita MN10200 */
   bfd_arch_mn10300,    /* Matsushita MN10300 */
+  bfd_arch_cris,       /* Axis CRIS */
+#define bfd_mach_cris_v0_v10   255
+#define bfd_mach_cris_v32      32
+#define bfd_mach_cris_v10_v32  1032
   bfd_arch_last
   };
 #define bfd_mach_s390_31 31
@@ -382,6 +386,7 @@
 extern int print_insn_ppc		PARAMS ((bfd_vma, disassemble_info*));
 extern int print_insn_alpha             PARAMS ((bfd_vma, disassemble_info*));
 extern int print_insn_s390		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_crisv32           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-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/disas.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -178,13 +178,18 @@
     disasm_info.mach = bfd_mach_sparc_v9b;
 #endif
 #elif defined(TARGET_PPC)
-    if (flags)
+    if (flags >> 16)
         disasm_info.endian = BFD_ENDIAN_LITTLE;
+    if (flags & 0xFFFF) {
+        /* If we have a precise definitions of the instructions set, use it */
+        disasm_info.mach = flags & 0xFFFF;
+    } else {
 #ifdef TARGET_PPC64
-    disasm_info.mach = bfd_mach_ppc64;
+        disasm_info.mach = bfd_mach_ppc64;
 #else
-    disasm_info.mach = bfd_mach_ppc;
+        disasm_info.mach = bfd_mach_ppc;
 #endif
+    }
     print_insn = print_insn_ppc;
 #elif defined(TARGET_M68K)
     print_insn = print_insn_m68k;
@@ -200,6 +205,9 @@
 #elif defined(TARGET_ALPHA)
     disasm_info.mach = bfd_mach_alpha;
     print_insn = print_insn_alpha;
+#elif defined(TARGET_CRIS)
+    disasm_info.mach = bfd_mach_cris_v32;
+    print_insn = print_insn_crisv32;
 #else
     fprintf(out, "0x" TARGET_FMT_lx
 	    ": Asm output not supported on this arch\n", code);

Deleted: trunk/src/host/qemu-neo1973/ecc.h
===================================================================
--- trunk/src/host/qemu-neo1973/ecc.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/ecc.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,94 +0,0 @@
-/*
- * Calculate Error-correcting Codes. Used by NAND Flash controllers
- * (not by NAND chips).
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog at zabor.org>
- *
- * This code is licensed under the GNU GPL v2.
- */
-
-struct ecc_state_s {
-    uint8_t cp;		/* Column parity */
-    uint16_t lp[2];	/* Line parity */
-    uint16_t count;
-};
-
-/*
- * Pre-calculated 256-way 1 byte column parity.  Table borrowed from Linux.
- */
-static const uint8_t nand_ecc_precalc_table[] = {
-    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
-    0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
-    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
-    0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
-    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
-    0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
-    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
-    0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
-    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
-    0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
-    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
-    0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
-    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
-    0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
-    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
-    0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
-    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
-    0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
-    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
-    0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
-    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
-    0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
-    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
-    0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
-    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
-    0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
-    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
-    0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
-    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
-    0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
-    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
-    0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
-};
-
-/* Update ECC parity count.  */
-static inline uint8_t ecc_digest(struct ecc_state_s *s, uint8_t sample)
-{
-    uint8_t idx = nand_ecc_precalc_table[sample];
-
-    s->cp ^= idx & 0x3f;
-    if (idx & 0x40) {
-        s->lp[0] ^= ~s->count;
-        s->lp[1] ^= s->count;
-    }
-    s->count ++;
-
-    return sample;
-}
-
-/* Reinitialise the counters.  */
-static inline void ecc_reset(struct ecc_state_s *s)
-{
-    s->lp[0] = 0x0000;
-    s->lp[1] = 0x0000;
-    s->cp = 0x00;
-    s->count = 0;
-}
-
-/* Save/restore */
-static inline void ecc_put(QEMUFile *f, struct ecc_state_s *s)
-{
-    qemu_put_8s(f, &s->cp);
-    qemu_put_be16s(f, &s->lp[0]);
-    qemu_put_be16s(f, &s->lp[1]);
-    qemu_put_be16s(f, &s->count);
-}
-
-static inline void ecc_get(QEMUFile *f, struct ecc_state_s *s)
-{
-    qemu_get_8s(f, &s->cp);
-    qemu_get_be16s(f, &s->lp[0]);
-    qemu_get_be16s(f, &s->lp[1]);
-    qemu_get_be16s(f, &s->count);
-}

Modified: trunk/src/host/qemu-neo1973/elf.h
===================================================================
--- trunk/src/host/qemu-neo1973/elf.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/elf.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1130,6 +1130,7 @@
 #define elf_note	elf32_note
 #define elf_shdr	elf32_shdr
 #define elf_sym		elf32_sym
+#define elf_addr_t	Elf32_Off
 
 #ifdef ELF_USES_RELOCA
 # define ELF_RELOC      Elf32_Rela
@@ -1144,6 +1145,7 @@
 #define elf_note	elf64_note
 #define elf_shdr	elf64_shdr
 #define elf_sym		elf64_sym
+#define elf_addr_t	Elf64_Off
 
 #ifdef ELF_USES_RELOCA
 # define ELF_RELOC      Elf64_Rela

Modified: trunk/src/host/qemu-neo1973/elf_ops.h
===================================================================
--- trunk/src/host/qemu-neo1973/elf_ops.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/elf_ops.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -145,8 +145,8 @@
     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;
+    elf_word mem_size;
+    uint64_t addr, low = 0, high = 0;
     uint8_t *data = NULL;
 
     if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
@@ -159,7 +159,7 @@
         goto fail;
 
     if (pentry)
-   	*pentry = (uint64_t)ehdr.e_entry;
+   	*pentry = (uint64_t)(elf_sword)ehdr.e_entry;
 
     glue(load_symbols, SZ)(&ehdr, fd, must_swab);
 
@@ -206,9 +206,9 @@
     }
     qemu_free(phdr);
     if (lowaddr)
-        *lowaddr = (uint64_t)low;
+        *lowaddr = (uint64_t)(elf_sword)low;
     if (highaddr)
-        *highaddr = (uint64_t)high;
+        *highaddr = (uint64_t)(elf_sword)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-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/exec-all.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -37,6 +37,14 @@
 #define unlikely(x)   __builtin_expect(!!(x), 0)
 #endif
 
+#ifndef always_inline
+#if (__GNUC__ < 3) || defined(__APPLE__)
+#define always_inline inline
+#else
+#define always_inline __attribute__ (( always_inline )) inline
+#endif
+#endif
+
 #ifdef __i386__
 #define REGPARM(n) __attribute((regparm(n)))
 #else
@@ -109,14 +117,14 @@
 void tlb_flush(CPUState *env, int flush_global);
 int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
                       target_phys_addr_t paddr, int prot,
-                      int is_user, int is_softmmu);
+                      int mmu_idx, int is_softmmu);
 static inline int tlb_set_page(CPUState *env, target_ulong vaddr,
                                target_phys_addr_t paddr, int prot,
-                               int is_user, int is_softmmu)
+                               int mmu_idx, int is_softmmu)
 {
     if (prot & PAGE_READ)
         prot |= PAGE_EXEC;
-    return tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
+    return tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
 }
 
 #define CODE_GEN_MAX_SIZE        65536
@@ -171,7 +179,7 @@
 typedef struct TranslationBlock {
     target_ulong pc;   /* simulated PC corresponding to this block (EIP + CS base) */
     target_ulong cs_base; /* CS base for this block */
-    unsigned int flags; /* flags defining in which context the code was generated */
+    uint64_t flags; /* flags defining in which context the code was generated */
     uint16_t size;      /* size of target code for this block (1 <=
                            size <= TARGET_PAGE_SIZE) */
     uint16_t cflags;    /* compile flags */
@@ -554,10 +562,10 @@
 
 #if !defined(CONFIG_USER_ONLY)
 
-void tlb_fill(target_ulong addr, int is_write, int is_user,
+void tlb_fill(target_ulong addr, int is_write, int mmu_idx,
               void *retaddr);
 
-#define ACCESS_TYPE 3
+#define ACCESS_TYPE (NB_MMU_MODES + 1)
 #define MEMSUFFIX _code
 #define env cpu_single_env
 
@@ -590,41 +598,23 @@
    is the offset relative to phys_ram_base */
 static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
 {
-    int is_user, index, pd;
+    int mmu_idx, index, pd;
 
     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-#if defined(TARGET_I386)
-    is_user = ((env->hflags & HF_CPL_MASK) == 3);
-#elif defined (TARGET_PPC)
-    is_user = msr_pr;
-#elif defined (TARGET_MIPS)
-    is_user = ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
-#elif defined (TARGET_SPARC)
-    is_user = (env->psrs == 0);
-#elif defined (TARGET_ARM)
-    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);
-#elif defined (TARGET_M68K)
-    is_user = ((env->sr & SR_S) == 0);
-#else
-#error unimplemented CPU
-#endif
-    if (__builtin_expect(env->tlb_table[is_user][index].addr_code !=
+    mmu_idx = cpu_mmu_index(env);
+    if (__builtin_expect(env->tlb_table[mmu_idx][index].addr_code !=
                          (addr & TARGET_PAGE_MASK), 0)) {
         ldub_code(addr);
     }
-    pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK;
+    pd = env->tlb_table[mmu_idx][index].addr_code & ~TARGET_PAGE_MASK;
     if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
-#ifdef TARGET_SPARC
+#if defined(TARGET_SPARC) || defined(TARGET_MIPS)
         do_unassigned_access(addr, 0, 1, 0);
 #else
         cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
 #endif
     }
-    return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base;
+    return addr + env->tlb_table[mmu_idx][index].addend - (unsigned long)phys_ram_base;
 }
 #endif
 

Modified: trunk/src/host/qemu-neo1973/exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/exec.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/exec.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1292,15 +1292,28 @@
     vfprintf(stderr, fmt, ap);
     fprintf(stderr, "\n");
 #ifdef TARGET_I386
+    if(env->intercept & INTERCEPT_SVM_MASK) {
+	/* most probably the virtual machine should not
+	   be shut down but rather caught by the VMM */
+        vmexit(SVM_EXIT_SHUTDOWN, 0);
+    }
     cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
 #else
     cpu_dump_state(env, stderr, fprintf, 0);
 #endif
-    va_end(ap);
     if (logfile) {
+        fprintf(logfile, "qemu: fatal: ");
+        vfprintf(logfile, fmt, ap);
+        fprintf(logfile, "\n");
+#ifdef TARGET_I386
+        cpu_dump_state(env, logfile, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
+#else
+        cpu_dump_state(env, logfile, fprintf, 0);
+#endif
         fflush(logfile);
         fclose(logfile);
     }
+    va_end(ap);
     abort();
 }
 
@@ -1595,7 +1608,7 @@
    conflicting with the host address space). */
 int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
                       target_phys_addr_t paddr, int prot,
-                      int is_user, int is_softmmu)
+                      int mmu_idx, int is_softmmu)
 {
     PhysPageDesc *p;
     unsigned long pd;
@@ -1613,8 +1626,8 @@
         pd = p->phys_offset;
     }
 #if defined(DEBUG_TLB)
-    printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d smmu=%d pd=0x%08lx\n",
-           vaddr, (int)paddr, prot, is_user, is_softmmu, pd);
+    printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
+           vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
 #endif
 
     ret = 0;
@@ -1651,7 +1664,7 @@
 
         index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
         addend -= vaddr;
-        te = &env->tlb_table[is_user][index];
+        te = &env->tlb_table[mmu_idx][index];
         te->addend = addend;
         if (prot & PAGE_READ) {
             te->addr_read = address;
@@ -1777,7 +1790,7 @@
 
 int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
                       target_phys_addr_t paddr, int prot,
-                      int is_user, int is_softmmu)
+                      int mmu_idx, int is_softmmu)
 {
     return 0;
 }
@@ -2053,6 +2066,8 @@
 #endif
 #ifdef TARGET_SPARC
     do_unassigned_access(addr, 0, 0, 0);
+#elif TARGET_CRIS
+    do_unassigned_access(addr, 0, 0, 0);
 #endif
     return 0;
 }
@@ -2064,6 +2079,8 @@
 #endif
 #ifdef TARGET_SPARC
     do_unassigned_access(addr, 1, 0, 0);
+#elif TARGET_CRIS
+    do_unassigned_access(addr, 1, 0, 0);
 #endif
 }
 

Modified: trunk/src/host/qemu-neo1973/gdbstub.c
===================================================================
--- trunk/src/host/qemu-neo1973/gdbstub.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/gdbstub.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -300,7 +300,7 @@
     }
     /* nip, msr, ccr, lnk, ctr, xer, mq */
     registers[96] = tswapl(env->nip);
-    registers[97] = tswapl(do_load_msr(env));
+    registers[97] = tswapl(env->msr);
     tmp = 0;
     for (i = 0; i < 8; i++)
         tmp |= env->crf[i] << (32 - ((i + 1) * 4));
@@ -329,7 +329,7 @@
     }
     /* nip, msr, ccr, lnk, ctr, xer, mq */
     env->nip = tswapl(registers[96]);
-    do_store_msr(env, tswapl(registers[97]));
+    ppc_store_msr(env, tswapl(registers[97]));
     registers[98] = tswapl(registers[98]);
     for (i = 0; i < 8; i++)
         env->crf[i] = (registers[98] >> (32 - ((i + 1) * 4))) & 0xF;
@@ -563,7 +563,7 @@
         ptr += sizeof(target_ulong);
       }
 
-    *(target_ulong *)ptr = tswapl(env->CP0_Status);
+    *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_Status);
     ptr += sizeof(target_ulong);
 
     *(target_ulong *)ptr = tswapl(env->LO[0][env->current_tc]);
@@ -575,7 +575,7 @@
     *(target_ulong *)ptr = tswapl(env->CP0_BadVAddr);
     ptr += sizeof(target_ulong);
 
-    *(target_ulong *)ptr = tswapl(env->CP0_Cause);
+    *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_Cause);
     ptr += sizeof(target_ulong);
 
     *(target_ulong *)ptr = tswapl(env->PC[env->current_tc]);
@@ -585,20 +585,35 @@
       {
         for (i = 0; i < 32; i++)
           {
-            *(target_ulong *)ptr = tswapl(env->fpu->fpr[i].fs[FP_ENDIAN_IDX]);
+            if (env->CP0_Status & (1 << CP0St_FR))
+              *(target_ulong *)ptr = tswapl(env->fpu->fpr[i].d);
+            else
+              *(target_ulong *)ptr = tswap32(env->fpu->fpr[i].w[FP_ENDIAN_IDX]);
             ptr += sizeof(target_ulong);
           }
 
-        *(target_ulong *)ptr = tswapl(env->fpu->fcr31);
+        *(target_ulong *)ptr = (int32_t)tswap32(env->fpu->fcr31);
         ptr += sizeof(target_ulong);
 
-        *(target_ulong *)ptr = tswapl(env->fpu->fcr0);
+        *(target_ulong *)ptr = (int32_t)tswap32(env->fpu->fcr0);
         ptr += sizeof(target_ulong);
       }
 
-    /* 32 FP registers, fsr, fir, fp.  Not yet implemented.  */
-    /* what's 'fp' mean here?  */
+    /* "fp", pseudo frame pointer. Not yet implemented in gdb. */
+    *(target_ulong *)ptr = 0;
+    ptr += sizeof(target_ulong);
 
+    /* Registers for embedded use, we just pad them. */
+    for (i = 0; i < 16; i++)
+      {
+        *(target_ulong *)ptr = 0;
+        ptr += sizeof(target_ulong);
+      }
+
+    /* Processor ID. */
+    *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_PRid);
+    ptr += sizeof(target_ulong);
+
     return ptr - mem_buf;
 }
 
@@ -647,15 +662,17 @@
       {
         for (i = 0; i < 32; i++)
           {
-            env->fpu->fpr[i].fs[FP_ENDIAN_IDX] = tswapl(*(target_ulong *)ptr);
+            if (env->CP0_Status & (1 << CP0St_FR))
+              env->fpu->fpr[i].d = tswapl(*(target_ulong *)ptr);
+            else
+              env->fpu->fpr[i].w[FP_ENDIAN_IDX] = tswapl(*(target_ulong *)ptr);
             ptr += sizeof(target_ulong);
           }
 
-        env->fpu->fcr31 = tswapl(*(target_ulong *)ptr) & 0x0183FFFF;
+        env->fpu->fcr31 = tswapl(*(target_ulong *)ptr) & 0xFF83FFFF;
         ptr += sizeof(target_ulong);
 
-        env->fpu->fcr0 = tswapl(*(target_ulong *)ptr);
-        ptr += sizeof(target_ulong);
+        /* The remaining registers are assumed to be read-only. */
 
         /* set rounding mode */
         RESTORE_ROUNDING_MODE;
@@ -728,6 +745,66 @@
   for (i = 0; i < 8; i++) LOAD(env->gregs[i]);
   for (i = 0; i < 8; i++) LOAD(env->gregs[i + 16]);
 }
+#elif defined (TARGET_CRIS)
+
+static int cris_save_32 (unsigned char *d, uint32_t value)
+{
+	*d++ = (value);
+	*d++ = (value >>= 8);
+	*d++ = (value >>= 8);
+	*d++ = (value >>= 8);
+	return 4;
+}
+static int cris_save_16 (unsigned char *d, uint32_t value)
+{
+	*d++ = (value);
+	*d++ = (value >>= 8);
+	return 2;
+}
+static int cris_save_8 (unsigned char *d, uint32_t value)
+{
+	*d++ = (value);
+	return 1;
+}
+
+/* FIXME: this will bug on archs not supporting unaligned word accesses.  */
+static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
+{
+  uint8_t *ptr = mem_buf;
+  uint8_t srs;
+  int i;
+
+  for (i = 0; i < 16; i++)
+	  ptr += cris_save_32 (ptr, env->regs[i]);
+
+  srs = env->pregs[SR_SRS];
+
+  ptr += cris_save_8 (ptr, env->pregs[0]);
+  ptr += cris_save_8 (ptr, env->pregs[1]);
+  ptr += cris_save_32 (ptr, env->pregs[2]);
+  ptr += cris_save_8 (ptr, srs);
+  ptr += cris_save_16 (ptr, env->pregs[4]);
+
+  for (i = 5; i < 16; i++)
+	  ptr += cris_save_32 (ptr, env->pregs[i]);
+
+  ptr += cris_save_32 (ptr, env->pc);
+
+  for (i = 0; i < 16; i++)
+	  ptr += cris_save_32 (ptr, env->sregs[srs][i]);
+
+  return ((uint8_t *)ptr - mem_buf);
+}
+
+static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
+{
+  uint32_t *ptr = (uint32_t *)mem_buf;
+  int i;
+
+#define LOAD(x) (x)=*ptr++;
+  for (i = 0; i < 16; i++) LOAD(env->regs[i]);
+  LOAD (env->pc);
+}
 #else
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
 {
@@ -745,7 +822,7 @@
     const char *p;
     int ch, reg_size, type;
     char buf[4096];
-    uint8_t mem_buf[2000];
+    uint8_t mem_buf[4096];
     uint32_t *registers;
     target_ulong addr, len;
 
@@ -776,6 +853,8 @@
             env->pc = addr;
 #elif defined (TARGET_MIPS)
             env->PC[env->current_tc] = addr;
+#elif defined (TARGET_CRIS)
+            env->pc = addr;
 #endif
         }
 #ifdef CONFIG_USER_ONLY
@@ -800,6 +879,8 @@
             env->pc = addr;
 #elif defined (TARGET_MIPS)
             env->PC[env->current_tc] = addr;
+#elif defined (TARGET_CRIS)
+            env->pc = addr;
 #endif
         }
         cpu_single_step(env, 1);

Modified: trunk/src/host/qemu-neo1973/host-utils.c
===================================================================
--- trunk/src/host/qemu-neo1973/host-utils.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/host-utils.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,6 +1,7 @@
 /*
  * Utility compute operations used by translated code.
  *
+ * Copyright (c) 2003 Fabrice Bellard
  * Copyright (c) 2007 Aurelien Jarno
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,52 +25,90 @@
 
 #include "vl.h"
 
-/* Signed 64x64 -> 128 multiplication */
+//#define DEBUG_MULDIV
 
-void muls64(int64_t *phigh, int64_t *plow, int64_t a, int64_t b)
+/* Long integer helpers */
+static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
 {
-#if defined(__x86_64__)
-    __asm__ ("imul %0\n\t"
-             : "=d" (*phigh), "=a" (*plow)
-             : "a" (a), "0" (b)
-             );
-#else
-    int64_t ph;
-    uint64_t pm1, pm2, pl;
+    *plow += a;
+    /* carry test */
+    if (*plow < a)
+        (*phigh)++;
+    *phigh += b;
+}
 
-    pl = (uint64_t)((uint32_t)a) * (uint64_t)((uint32_t)b);
-    pm1 = (a >> 32) * (uint32_t)b;
-    pm2 = (uint32_t)a * (b >> 32);
-    ph = (a >> 32) * (b >> 32);
+static void neg128 (uint64_t *plow, uint64_t *phigh)
+{
+    *plow = ~*plow;
+    *phigh = ~*phigh;
+    add128(plow, phigh, 1, 0);
+}
 
-    ph += (int64_t)pm1 >> 32;
-    pm1 = (uint64_t)((uint32_t)pm1) + pm2 + (pl >> 32);
+static void mul64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
+{
+    uint32_t a0, a1, b0, b1;
+    uint64_t v;
 
-    *phigh = ph + ((int64_t)pm1 >> 32);
-    *plow = (pm1 << 32) + (uint32_t)pl;
-#endif
+    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;
 }
 
+
 /* Unsigned 64x64 -> 128 multiplication */
-void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b)
+void mulu64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
 {
 #if defined(__x86_64__)
     __asm__ ("mul %0\n\t"
              : "=d" (*phigh), "=a" (*plow)
-             : "a" (a), "0" (b)
-            );
+             : "a" (a), "0" (b));
 #else
-    uint64_t ph, pm1, pm2, pl;
+    mul64(plow, phigh, a, b);
+#endif
+#if defined(DEBUG_MULDIV)
+    printf("mulu64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
+           a, b, *phigh, *plow);
+#endif
+}
 
-    pl = (uint64_t)((uint32_t)a) * (uint64_t)((uint32_t)b);
-    pm1 = (a >> 32) * (uint32_t)b;
-    pm2 = (uint32_t)a * (b >> 32);
-    ph = (a >> 32) * (b >> 32);
+/* Signed 64x64 -> 128 multiplication */
+void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
+{
+#if defined(__x86_64__)
+    __asm__ ("imul %0\n\t"
+             : "=d" (*phigh), "=a" (*plow)
+             : "a" (a), "0" (b));
+#else
+    int sa, sb;
 
-    ph += pm1 >> 32;
-    pm1 = (uint64_t)((uint32_t)pm1) + pm2 + (pl >> 32);
-
-    *phigh = ph + (pm1 >> 32);
-    *plow = (pm1 << 32) + (uint32_t)pl;
+    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);
+    }
 #endif
+#if defined(DEBUG_MULDIV)
+    printf("muls64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
+           a, b, *phigh, *plow);
+#endif
 }

Added: trunk/src/host/qemu-neo1973/host-utils.h
===================================================================
--- trunk/src/host/qemu-neo1973/host-utils.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/host-utils.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,201 @@
+/*
+ * Utility compute operations used by translated code.
+ *
+ * Copyright (c) 2007 Thiemo Seufer
+ * 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.
+ */
+
+/* Note that some of those functions may end up calling libgcc functions,
+   depending on the host machine. It is up to the target emulation to
+   cope with that. */
+
+/* Binary search for leading zeros.  */
+
+static always_inline int clz32(uint32_t val)
+{
+    int cnt = 0;
+
+    if (!(val & 0xFFFF0000U)) {
+        cnt += 16;
+        val <<= 16;
+    }
+    if (!(val & 0xFF000000U)) {
+        cnt += 8;
+        val <<= 8;
+    }
+    if (!(val & 0xF0000000U)) {
+        cnt += 4;
+        val <<= 4;
+    }
+    if (!(val & 0xC0000000U)) {
+        cnt += 2;
+        val <<= 2;
+    }
+    if (!(val & 0x80000000U)) {
+        cnt++;
+        val <<= 1;
+    }
+    if (!(val & 0x80000000U)) {
+        cnt++;
+    }
+    return cnt;
+}
+
+static always_inline int clo32(uint32_t val)
+{
+    return clz32(~val);
+}
+
+static always_inline int clz64(uint64_t val)
+{
+    int cnt = 0;
+
+    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++;
+    }
+    return cnt;
+}
+
+static always_inline int clo64(uint64_t val)
+{
+    return clz64(~val);
+}
+
+static always_inline int ctz32 (uint32_t val)
+{
+    int cnt;
+
+    cnt = 0;
+    if (!(val & 0x0000FFFFUL)) {
+         cnt += 16;
+        val >>= 16;
+     }
+    if (!(val & 0x000000FFUL)) {
+         cnt += 8;
+        val >>= 8;
+     }
+    if (!(val & 0x0000000FUL)) {
+         cnt += 4;
+        val >>= 4;
+     }
+    if (!(val & 0x00000003UL)) {
+         cnt += 2;
+        val >>= 2;
+     }
+    if (!(val & 0x00000001UL)) {
+         cnt++;
+        val >>= 1;
+     }
+    if (!(val & 0x00000001UL)) {
+         cnt++;
+     }
+
+     return cnt;
+ }
+ 
+static always_inline int cto32 (uint32_t val)
+ {
+    return ctz32(~val);
+}
+
+static always_inline int ctz64 (uint64_t val)
+{
+    int cnt;
+
+    cnt = 0;
+    if (!((uint32_t)val)) {
+        cnt += 32;
+        val >>= 32;
+    }
+
+    return cnt + ctz32(val);
+}
+
+static always_inline int cto64 (uint64_t val)
+{
+    return ctz64(~val);
+}
+
+static always_inline int ctpop8 (uint8_t val)
+{
+    val = (val & 0x55) + ((val >> 1) & 0x55);
+    val = (val & 0x33) + ((val >> 2) & 0x33);
+    val = (val & 0x0f) + ((val >> 4) & 0x0f);
+
+    return val;
+}
+
+static always_inline int ctpop16 (uint16_t val)
+{
+    val = (val & 0x5555) + ((val >> 1) & 0x5555);
+    val = (val & 0x3333) + ((val >> 2) & 0x3333);
+    val = (val & 0x0f0f) + ((val >> 4) & 0x0f0f);
+    val = (val & 0x00ff) + ((val >> 8) & 0x00ff);
+
+    return val;
+}
+
+static always_inline int ctpop32 (uint32_t val)
+{
+    val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
+    val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
+    val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
+    val = (val & 0x00ff00ff) + ((val >>  8) & 0x00ff00ff);
+    val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
+
+    return val;
+}
+
+static always_inline int ctpop64 (uint64_t val)
+{
+    val = (val & 0x5555555555555555ULL) + ((val >>  1) & 0x5555555555555555ULL);
+    val = (val & 0x3333333333333333ULL) + ((val >>  2) & 0x3333333333333333ULL);
+    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) & 0x0f0f0f0f0f0f0f0fULL);
+    val = (val & 0x00ff00ff00ff00ffULL) + ((val >>  8) & 0x00ff00ff00ff00ffULL);
+    val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) & 0x0000ffff0000ffffULL);
+    val = (val & 0x00000000ffffffffULL) + ((val >> 32) & 0x00000000ffffffffULL);
+
+    return val;
+ }

Modified: trunk/src/host/qemu-neo1973/hw/acpi.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/acpi.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/acpi.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -400,7 +400,7 @@
 
     if (s->dev.config[0x80] & 1) {
         pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40));
-        pm_io_base &= 0xfffe;
+        pm_io_base &= 0xffc0;
 
         /* XXX: need to improve memory and ioport allocation */
 #if defined(DEBUG)
@@ -474,6 +474,8 @@
     pci_conf[0x01] = 0x80;
     pci_conf[0x02] = 0x13;
     pci_conf[0x03] = 0x71;
+    pci_conf[0x06] = 0x80;
+    pci_conf[0x07] = 0x02;
     pci_conf[0x08] = 0x00; // revision number
     pci_conf[0x09] = 0x00;
     pci_conf[0x0a] = 0x80; // other bridge device

Modified: trunk/src/host/qemu-neo1973/hw/alpha_palcode.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/alpha_palcode.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/alpha_palcode.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -811,12 +811,14 @@
 
 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)
+                    int mmu_idx, int rw)
 {
     uint64_t pteaddr, pte, pfn;
     uint8_t gh;
-    int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar;
+    int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar, is_user;
 
+    /* XXX: TOFIX */
+    is_user = mmu_idx == MMU_USER_IDX;
     pteaddr = (ptebase << page_bits) + (8 * level);
     pte = ldq_raw(pteaddr);
     /* Decode all interresting PTE fields */
@@ -871,7 +873,7 @@
 
 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 vaddr, int mmu_idx, int rw)
 {
     uint64_t pfn, page_mask, lvl_mask, level1, level2, level3;
     int lvl_bits, ret;
@@ -909,7 +911,7 @@
         break;
     }
     /* Level 3 PTE */
-    ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, is_user, rw);
+    ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, mmu_idx, rw);
     if (ret & 0x1) {
         /* Translation not valid */
         ret = 1;
@@ -943,7 +945,7 @@
 
 static int virtual_to_physical (CPUState *env, uint64_t *physp,
                                 int *zbitsp, int *protp,
-                                uint64_t virtual, int is_user, int rw)
+                                uint64_t virtual, int mmu_idx, int rw)
 {
     uint64_t sva, ptebase;
     int seg, page_bits, ret;
@@ -961,16 +963,16 @@
     case 0:
         /* seg1: 3 levels of PTE */
         ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
-                             virtual, is_user, rw);
+                             virtual, mmu_idx, rw);
         break;
     case 1:
         /* seg1: 2 levels of PTE */
         ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
-                             virtual, is_user, rw);
+                             virtual, mmu_idx, rw);
         break;
     case 2:
         /* kernel segment */
-        if (is_user) {
+        if (mmu_idx != 0) {
             ret = 2;
         } else {
             *physp = virtual;
@@ -979,7 +981,7 @@
     case 3:
         /* seg1: TB mapped */
         ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
-                             virtual, is_user, rw);
+                             virtual, mmu_idx, rw);
         break;
     default:
         ret = 1;
@@ -991,7 +993,7 @@
 
 /* XXX: code provision */
 int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
-                              int is_user, int is_softmmu)
+                              int mmu_idx, int is_softmmu)
 {
     uint64_t physical, page_size, end;
     int prot, zbits, ret;
@@ -1000,7 +1002,7 @@
         ret = 2;
     } else {
         ret = virtual_to_physical(env, &physical, &zbits, &prot,
-                                  address, is_user, rw);
+                                  address, mmu_idx, rw);
     }
     switch (ret) {
     case 0:
@@ -1009,7 +1011,7 @@
         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);
+                               mmu_idx, is_softmmu);
             address += 0x1000;
         }
         break;

Modified: trunk/src/host/qemu-neo1973/hw/apb_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/apb_pci.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/apb_pci.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -70,7 +70,7 @@
 };
 
 static void apb_config_writel (void *opaque, target_phys_addr_t addr,
-			       uint32_t val)
+                               uint32_t val)
 {
     //PCIBus *s = opaque;
 
@@ -80,14 +80,14 @@
     case 0x18: // AFAR
     case 0x20: // Diagnostic
     case 0x28: // Target address space
-	// XXX
+        // XXX
     default:
-	break;
+        break;
     }
 }
 
 static uint32_t apb_config_readl (void *opaque,
-				  target_phys_addr_t addr)
+                                  target_phys_addr_t addr)
 {
     //PCIBus *s = opaque;
     uint32_t val;
@@ -98,10 +98,10 @@
     case 0x18: // AFAR
     case 0x20: // Diagnostic
     case 0x28: // Target address space
-	// XXX
+        // XXX
     default:
-	val = 0;
-	break;
+        val = 0;
+        break;
     }
     return val;
 }
@@ -222,7 +222,7 @@
     pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read,
                                             pci_apb_config_write, s);
     apb_config = cpu_register_io_memory(0, apb_config_read,
-					apb_config_write, s);
+                                        apb_config_write, s);
     pci_mem_data = cpu_register_io_memory(0, pci_apb_read,
                                           pci_apb_write, s);
     pci_ioport = cpu_register_io_memory(0, pci_apb_ioread,

Modified: trunk/src/host/qemu-neo1973/hw/apic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/apic.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/apic.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -484,6 +484,25 @@
     return intno;
 }
 
+int apic_accept_pic_intr(CPUState *env)
+{
+    APICState *s = env->apic_state;
+    uint32_t lvt0;
+
+    if (!s)
+        return -1;
+
+    lvt0 = s->lvt[APIC_LVT_LINT0];
+
+    if (s->id == 0 &&
+        ((s->apicbase & MSR_IA32_APICBASE_ENABLE) == 0 ||
+         ((lvt0 & APIC_LVT_MASKED) == 0 &&
+          ((lvt0 >> 8) & 0x7) == APIC_DM_EXTINT)))
+        return 1;
+
+    return 0;
+}
+
 static uint32_t apic_get_current_count(APICState *s)
 {
     int64_t d;
@@ -790,6 +809,13 @@
 {
     APICState *s = opaque;
     apic_init_ipi(s);
+
+    /*
+     * LINT0 delivery mode is set to ExtInt at initialization time
+     * typically by BIOS, so PIC interrupt can be delivered to the
+     * processor when local APIC is enabled.
+     */
+    s->lvt[APIC_LVT_LINT0] = 0x700;
 }
 
 static CPUReadMemoryFunc *apic_mem_read[3] = {
@@ -821,6 +847,13 @@
     s->apicbase = 0xfee00000 |
         (s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE;
 
+    /*
+     * LINT0 delivery mode is set to ExtInt at initialization time
+     * typically by BIOS, so PIC interrupt can be delivered to the
+     * processor when local APIC is enabled.
+     */
+    s->lvt[APIC_LVT_LINT0] = 0x700;
+
     /* XXX: mapping more APICs at the same memory location */
     if (apic_io_memory == 0) {
         /* NOTE: the APIC is directly connected to the CPU - it is not

Modified: trunk/src/host/qemu-neo1973/hw/cs4231.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/cs4231.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/cs4231.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -79,11 +79,11 @@
             break;
         }
         DPRINTF("read dreg[%d]: 0x%8.8x\n", CS_RAP(s), ret);
-	break;
+        break;
     default:
         ret = s->regs[saddr];
         DPRINTF("read reg[%d]: 0x%8.8x\n", saddr, ret);
-	break;
+        break;
     }
     return ret;
 }
@@ -122,7 +122,7 @@
         break;
     default:
         s->regs[saddr] = val;
-	break;
+        break;
     }
 }
 

Modified: trunk/src/host/qemu-neo1973/hw/cuda.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/cuda.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/cuda.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,7 +1,8 @@
 /*
- * QEMU CUDA support
+ * QEMU PowerMac CUDA device support
  *
- * Copyright (c) 2004 Fabrice Bellard
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * 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
@@ -22,6 +23,7 @@
  * THE SOFTWARE.
  */
 #include "vl.h"
+#include "ppc_mac.h"
 
 /* XXX: implement all timer modes */
 
@@ -634,10 +636,9 @@
     &cuda_readl,
 };
 
-int cuda_init(qemu_irq irq)
+void cuda_init (int *cuda_mem_index, qemu_irq irq)
 {
     CUDAState *s = &cuda_state;
-    int cuda_mem_index;
 
     s->irq = irq;
 
@@ -653,6 +654,5 @@
     set_counter(s, &s->timers[1], 0xffff);
 
     s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
-    cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
-    return cuda_mem_index;
+    *cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
 }

Added: trunk/src/host/qemu-neo1973/hw/ecc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ecc.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ecc.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,90 @@
+/*
+ * Calculate Error-correcting Codes. Used by NAND Flash controllers
+ * (not by NAND chips).
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * This code is licensed under the GNU GPL v2.
+ */
+
+#include "vl.h"
+
+/*
+ * Pre-calculated 256-way 1 byte column parity.  Table borrowed from Linux.
+ */
+static const uint8_t nand_ecc_precalc_table[] = {
+    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
+    0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
+    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
+    0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
+    0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
+    0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
+    0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
+    0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
+    0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
+    0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
+    0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
+    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
+    0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
+    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
+    0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
+    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
+    0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
+    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
+    0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
+    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
+    0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
+    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
+    0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
+    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
+    0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
+};
+
+/* Update ECC parity count.  */
+uint8_t ecc_digest(struct ecc_state_s *s, uint8_t sample)
+{
+    uint8_t idx = nand_ecc_precalc_table[sample];
+
+    s->cp ^= idx & 0x3f;
+    if (idx & 0x40) {
+        s->lp[0] ^= ~s->count;
+        s->lp[1] ^= s->count;
+    }
+    s->count ++;
+
+    return sample;
+}
+
+/* Reinitialise the counters.  */
+void ecc_reset(struct ecc_state_s *s)
+{
+    s->lp[0] = 0x0000;
+    s->lp[1] = 0x0000;
+    s->cp = 0x00;
+    s->count = 0;
+}
+
+/* Save/restore */
+void ecc_put(QEMUFile *f, struct ecc_state_s *s)
+{
+    qemu_put_8s(f, &s->cp);
+    qemu_put_be16s(f, &s->lp[0]);
+    qemu_put_be16s(f, &s->lp[1]);
+    qemu_put_be16s(f, &s->count);
+}
+
+void ecc_get(QEMUFile *f, struct ecc_state_s *s)
+{
+    qemu_get_8s(f, &s->cp);
+    qemu_get_be16s(f, &s->lp[0]);
+    qemu_get_be16s(f, &s->lp[1]);
+    qemu_get_be16s(f, &s->count);
+}

Modified: trunk/src/host/qemu-neo1973/hw/esp.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/esp.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/esp.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -107,9 +107,9 @@
     if (s->dma) {
         espdma_memory_read(s->dma_opaque, buf, dmalen);
     } else {
-	buf[0] = 0;
-	memcpy(&buf[1], s->ti_buf, dmalen);
-	dmalen++;
+        buf[0] = 0;
+        memcpy(&buf[1], s->ti_buf, dmalen);
+        dmalen++;
     }
 
     s->ti_size = 0;
@@ -124,11 +124,11 @@
 
     if (target >= MAX_DISKS || !s->scsi_dev[target]) {
         // No such drive
-	s->rregs[4] = STAT_IN;
-	s->rregs[5] = INTR_DC;
-	s->rregs[6] = SEQ_0;
-	qemu_irq_raise(s->irq);
-	return 0;
+        s->rregs[4] = STAT_IN;
+        s->rregs[5] = INTR_DC;
+        s->rregs[6] = SEQ_0;
+        qemu_irq_raise(s->irq);
+        return 0;
     }
     s->current_dev = s->scsi_dev[target];
     return dmalen;
@@ -190,14 +190,14 @@
     s->ti_buf[1] = 0;
     if (s->dma) {
         espdma_memory_write(s->dma_opaque, s->ti_buf, 2);
-	s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
-	s->rregs[5] = INTR_BS | INTR_FC;
-	s->rregs[6] = SEQ_CD;
+        s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
+        s->rregs[5] = INTR_BS | INTR_FC;
+        s->rregs[6] = SEQ_CD;
     } else {
-	s->ti_size = 2;
-	s->ti_rptr = 0;
-	s->ti_wptr = 0;
-	s->rregs[7] = 2;
+        s->ti_size = 2;
+        s->ti_rptr = 0;
+        s->ti_wptr = 0;
+        s->rregs[7] = 2;
     }
     qemu_irq_raise(s->irq);
 }
@@ -359,9 +359,9 @@
     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
     switch (saddr) {
     case 2:
-	// FIFO
-	if (s->ti_size > 0) {
-	    s->ti_size--;
+        // FIFO
+        if (s->ti_size > 0) {
+            s->ti_size--;
             if ((s->rregs[4] & 6) == 0) {
                 /* Data in/out.  */
                 fprintf(stderr, "esp: PIO data read not implemented\n");
@@ -370,20 +370,20 @@
                 s->rregs[2] = s->ti_buf[s->ti_rptr++];
             }
             qemu_irq_raise(s->irq);
-	}
-	if (s->ti_size == 0) {
+        }
+        if (s->ti_size == 0) {
             s->ti_rptr = 0;
             s->ti_wptr = 0;
         }
-	break;
+        break;
     case 5:
         // interrupt
         // Clear interrupt/error status bits
         s->rregs[4] &= ~(STAT_IN | STAT_GE | STAT_PE);
-	qemu_irq_lower(s->irq);
+        qemu_irq_lower(s->irq);
         break;
     default:
-	break;
+        break;
     }
     return s->rregs[saddr];
 }
@@ -401,7 +401,7 @@
         s->rregs[4] &= ~STAT_TC;
         break;
     case 2:
-	// FIFO
+        // FIFO
         if (s->do_cmd) {
             s->cmdbuf[s->cmdlen++] = val & 0xff;
         } else if ((s->rregs[4] & 6) == 0) {
@@ -413,73 +413,73 @@
             s->ti_size++;
             s->ti_buf[s->ti_wptr++] = val & 0xff;
         }
-	break;
+        break;
     case 3:
         s->rregs[saddr] = val;
-	// Command
-	if (val & 0x80) {
-	    s->dma = 1;
+        // Command
+        if (val & 0x80) {
+            s->dma = 1;
             /* Reload DMA counter.  */
             s->rregs[0] = s->wregs[0];
             s->rregs[1] = s->wregs[1];
-	} else {
-	    s->dma = 0;
-	}
-	switch(val & 0x7f) {
-	case 0:
-	    DPRINTF("NOP (%2.2x)\n", val);
-	    break;
-	case 1:
-	    DPRINTF("Flush FIFO (%2.2x)\n", val);
+        } else {
+            s->dma = 0;
+        }
+        switch(val & 0x7f) {
+        case 0:
+            DPRINTF("NOP (%2.2x)\n", val);
+            break;
+        case 1:
+            DPRINTF("Flush FIFO (%2.2x)\n", val);
             //s->ti_size = 0;
-	    s->rregs[5] = INTR_FC;
-	    s->rregs[6] = 0;
-	    break;
-	case 2:
-	    DPRINTF("Chip reset (%2.2x)\n", val);
-	    esp_reset(s);
-	    break;
-	case 3:
-	    DPRINTF("Bus reset (%2.2x)\n", val);
-	    s->rregs[5] = INTR_RST;
+            s->rregs[5] = INTR_FC;
+            s->rregs[6] = 0;
+            break;
+        case 2:
+            DPRINTF("Chip reset (%2.2x)\n", val);
+            esp_reset(s);
+            break;
+        case 3:
+            DPRINTF("Bus reset (%2.2x)\n", val);
+            s->rregs[5] = INTR_RST;
             if (!(s->wregs[8] & 0x40)) {
                 qemu_irq_raise(s->irq);
             }
-	    break;
-	case 0x10:
-	    handle_ti(s);
-	    break;
-	case 0x11:
-	    DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
-	    write_response(s);
-	    break;
-	case 0x12:
-	    DPRINTF("Message Accepted (%2.2x)\n", val);
-	    write_response(s);
-	    s->rregs[5] = INTR_DC;
-	    s->rregs[6] = 0;
-	    break;
-	case 0x1a:
-	    DPRINTF("Set ATN (%2.2x)\n", val);
-	    break;
-	case 0x42:
-	    DPRINTF("Set ATN (%2.2x)\n", val);
-	    handle_satn(s);
-	    break;
-	case 0x43:
-	    DPRINTF("Set ATN & stop (%2.2x)\n", val);
-	    handle_satn_stop(s);
-	    break;
+            break;
+        case 0x10:
+            handle_ti(s);
+            break;
+        case 0x11:
+            DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
+            write_response(s);
+            break;
+        case 0x12:
+            DPRINTF("Message Accepted (%2.2x)\n", val);
+            write_response(s);
+            s->rregs[5] = INTR_DC;
+            s->rregs[6] = 0;
+            break;
+        case 0x1a:
+            DPRINTF("Set ATN (%2.2x)\n", val);
+            break;
+        case 0x42:
+            DPRINTF("Set ATN (%2.2x)\n", val);
+            handle_satn(s);
+            break;
+        case 0x43:
+            DPRINTF("Set ATN & stop (%2.2x)\n", val);
+            handle_satn_stop(s);
+            break;
         case 0x44:
             DPRINTF("Enable selection (%2.2x)\n", val);
             break;
-	default:
-	    DPRINTF("Unhandled ESP command (%2.2x)\n", val);
-	    break;
-	}
-	break;
+        default:
+            DPRINTF("Unhandled ESP command (%2.2x)\n", val);
+            break;
+        }
+        break;
     case 4 ... 7:
-	break;
+        break;
     case 8:
         s->rregs[saddr] = val;
         break;
@@ -492,7 +492,7 @@
         s->rregs[saddr] = val;
         break;
     default:
-	break;
+        break;
     }
     s->wregs[saddr] = val;
 }

Added: trunk/src/host/qemu-neo1973/hw/etraxfs.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/etraxfs.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/etraxfs.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,178 @@
+/*
+ * QEMU ETRAX System Emulator
+ *
+ * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <time.h>
+#include <sys/time.h>
+#include "vl.h"
+
+extern FILE *logfile;
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+    cpu_reset(env);
+}
+
+static uint32_t fs_mmio_readb (void *opaque, target_phys_addr_t addr)
+{
+	CPUState *env = opaque;
+	uint32_t r = 0;
+	printf ("%s %x pc=%x\n", __func__, addr, env->pc);
+	return r;
+}
+static uint32_t fs_mmio_readw (void *opaque, target_phys_addr_t addr)
+{
+	CPUState *env = opaque;
+	uint32_t r = 0;
+	printf ("%s %x pc=%x\n", __func__, addr, env->pc);
+	return r;
+}
+
+static uint32_t fs_mmio_readl (void *opaque, target_phys_addr_t addr)
+{
+	CPUState *env = opaque;
+	uint32_t r = 0;
+	printf ("%s %x p=%x\n", __func__, addr, env->pc);
+	return r;
+}
+
+static void
+fs_mmio_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+	CPUState *env = opaque;
+	printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+static void
+fs_mmio_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+	CPUState *env = opaque;
+	printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+static void
+fs_mmio_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+	CPUState *env = opaque;
+	printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+
+static CPUReadMemoryFunc *fs_mmio_read[] = {
+    &fs_mmio_readb,
+    &fs_mmio_readw,
+    &fs_mmio_readl,
+};
+
+static CPUWriteMemoryFunc *fs_mmio_write[] = {
+    &fs_mmio_writeb,
+    &fs_mmio_writew,
+    &fs_mmio_writel,
+};
+
+
+/* Init functions for different blocks.  */
+extern void etraxfs_timer_init(CPUState *env, qemu_irq *irqs);
+extern void etraxfs_ser_init(CPUState *env, qemu_irq *irqs);
+
+void etrax_ack_irq(CPUState *env, uint32_t mask)
+{
+	env->pending_interrupts &= ~mask;
+}
+
+static void dummy_cpu_set_irq(void *opaque, int irq, int level)
+{
+	CPUState *env = opaque;
+
+	/* Hmm, should this really be done here?  */
+	env->pending_interrupts |= 1 << irq;
+	cpu_interrupt(env, CPU_INTERRUPT_HARD);
+}
+
+static
+void bareetraxfs_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;
+    qemu_irq *irqs;
+    int kernel_size;
+    int internal_regs;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "crisv32";
+    }
+    env = cpu_init();
+/*    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); */
+    qemu_register_reset(main_cpu_reset, env);
+    irqs = qemu_allocate_irqs(dummy_cpu_set_irq, env, 32);
+
+    internal_regs = cpu_register_io_memory(0,
+					   fs_mmio_read, fs_mmio_write, env);
+    /* 0xb0050000 is the last reg.  */
+    cpu_register_physical_memory (0xac000000, 0x4010000, internal_regs);
+    /* allocate RAM */
+    cpu_register_physical_memory(0x40000000, ram_size, IO_MEM_RAM);
+
+    etraxfs_timer_init(env, irqs);
+    etraxfs_ser_init(env, irqs);
+
+    kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000);
+    /* magic for boot.  */
+    env->regs[8] = 0x56902387;
+    env->regs[9] = 0x40004000 + kernel_size;
+    env->pc = 0x40004000;
+
+    {
+       unsigned char *ptr = phys_ram_base + 0x4000;
+       int i;
+       for (i = 0; i < 8; i++)
+       {
+		printf ("%2.2x ", ptr[i]);
+       }
+	printf("\n");
+    }
+
+    printf ("pc =%x\n", env->pc);
+    printf ("ram size =%d\n", ram_size);
+    printf ("kernel name =%s\n", kernel_filename);
+    printf ("kernel size =%d\n", kernel_size);
+    printf ("cpu haltd =%d\n", env->halted);
+}
+
+void DMA_run(void)
+{
+}
+
+void pic_info()
+{
+}
+
+void irq_info()
+{
+}
+
+QEMUMachine bareetraxfs_machine = {
+    "bareetraxfs",
+    "Bare ETRAX FS board",
+    bareetraxfs_init,
+};

Added: trunk/src/host/qemu-neo1973/hw/etraxfs_ser.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/etraxfs_ser.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/etraxfs_ser.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,122 @@
+/*
+ * QEMU ETRAX System Emulator
+ *
+ * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "vl.h"
+
+#define RW_TR_DMA_EN 0xb0026004
+#define RW_DOUT 0xb002601c
+#define RW_STAT_DIN 0xb0026020
+#define R_STAT_DIN 0xb0026024
+
+static uint32_t ser_readb (void *opaque, target_phys_addr_t addr)
+{
+	CPUState *env = opaque;
+	uint32_t r = 0;
+	printf ("%s %x pc=%x\n", __func__, addr, env->pc);
+	return r;
+}
+static uint32_t ser_readw (void *opaque, target_phys_addr_t addr)
+{
+	CPUState *env = opaque;
+	uint32_t r = 0;
+	printf ("%s %x pc=%x\n", __func__, addr, env->pc);
+	return r;
+}
+
+static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
+{
+	CPUState *env = opaque;
+	uint32_t r = 0;
+
+	switch (addr)
+	{
+		case RW_TR_DMA_EN:
+			break;
+		case R_STAT_DIN:
+			r |= 1 << 24; /* set tr_rdy.  */
+			r |= 1 << 22; /* set tr_idle.  */
+			break;
+
+		default:
+			printf ("%s %x p=%x\n", __func__, addr, env->pc);
+			break;
+	}
+	return r;
+}
+
+static void
+ser_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+	CPUState *env = opaque;
+	printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+static void
+ser_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+	CPUState *env = opaque;
+	printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+static void
+ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+	CPUState *env = opaque;
+
+	switch (addr)
+	{
+		case RW_TR_DMA_EN:
+			break;
+		case RW_DOUT:
+			if (isprint(value) || isspace(value))
+				putchar(value);
+			else
+				putchar('.');
+			break;
+		default:
+			printf ("%s %x %x pc=%x\n",
+				__func__, addr, value, env->pc);
+			break;
+	}
+}
+
+static CPUReadMemoryFunc *ser_read[] = {
+    &ser_readb,
+    &ser_readw,
+    &ser_readl,
+};
+
+static CPUWriteMemoryFunc *ser_write[] = {
+    &ser_writeb,
+    &ser_writew,
+    &ser_writel,
+};
+
+void etraxfs_ser_init(CPUState *env, qemu_irq *irqs)
+{
+	int ser_regs;
+
+	ser_regs = cpu_register_io_memory(0, ser_read, ser_write, env);
+	cpu_register_physical_memory (0xb0026000, 0x3c, ser_regs);
+}

Added: trunk/src/host/qemu-neo1973/hw/etraxfs_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/etraxfs_timer.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/etraxfs_timer.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,268 @@
+/*
+ * QEMU ETRAX System Emulator
+ *
+ * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <stdio.h>
+#include <sys/time.h>
+#include "vl.h"
+
+void etrax_ack_irq(CPUState *env, uint32_t mask);
+
+#define R_TIME 0xb001e038
+#define RW_TMR0_DIV 0xb001e000
+#define R_TMR0_DATA 0xb001e004
+#define RW_TMR0_CTRL 0xb001e008
+#define RW_TMR1_DIV 0xb001e010
+#define R_TMR1_DATA 0xb001e014
+#define RW_TMR1_CTRL 0xb001e018
+
+#define RW_INTR_MASK 0xb001e048
+#define RW_ACK_INTR 0xb001e04c
+#define R_INTR 0xb001e050
+#define R_MASKED_INTR 0xb001e054
+
+
+uint32_t rw_intr_mask;
+uint32_t rw_ack_intr;
+uint32_t r_intr;
+
+struct fs_timer_t {
+	QEMUBH *bh;
+	unsigned int limit;
+	int scale;
+	ptimer_state *ptimer;
+	CPUState *env;
+	qemu_irq *irq;
+	uint32_t mask;
+};
+
+static struct fs_timer_t timer0;
+
+/* diff two timevals.  Return a single int in us. */
+int diff_timeval_us(struct timeval *a, struct timeval *b)
+{
+        int diff;
+
+        /* assume these values are signed.  */
+        diff = (a->tv_sec - b->tv_sec) * 1000 * 1000;
+        diff += (a->tv_usec - b->tv_usec);
+        return diff;
+}
+
+static uint32_t timer_readb (void *opaque, target_phys_addr_t addr)
+{
+	CPUState *env = opaque;
+	uint32_t r = 0;
+	printf ("%s %x pc=%x\n", __func__, addr, env->pc);
+	return r;
+}
+static uint32_t timer_readw (void *opaque, target_phys_addr_t addr)
+{
+	CPUState *env = opaque;
+	uint32_t r = 0;
+	printf ("%s %x pc=%x\n", __func__, addr, env->pc);
+	return r;
+}
+
+static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
+{
+	CPUState *env = opaque;
+	uint32_t r = 0;
+
+	switch (addr) {
+	case R_TMR0_DATA:
+		break;
+	case R_TMR1_DATA:
+		printf ("R_TMR1_DATA\n");
+		break;
+	case R_TIME:
+	{
+		static struct timeval last;
+		struct timeval now;
+		gettimeofday(&now, NULL);
+		if (!(last.tv_sec == 0 && last.tv_usec == 0)) {
+			r = diff_timeval_us(&now, &last);
+			r *= 1000; /* convert to ns.  */
+			r++; /* make sure we increase for each call.  */
+		}
+		last = now;
+		break;
+	}
+
+	case RW_INTR_MASK:
+		r = rw_intr_mask;
+		break;
+	case R_MASKED_INTR:
+		r = r_intr & rw_intr_mask;
+		break;
+	default:
+		printf ("%s %x p=%x\n", __func__, addr, env->pc);
+		break;
+	}
+	return r;
+}
+
+static void
+timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+	CPUState *env = opaque;
+	printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+static void
+timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+	CPUState *env = opaque;
+	printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
+}
+
+static void write_ctrl(struct fs_timer_t *t, uint32_t v)
+{
+	int op;
+	int freq;
+	int freq_hz;
+
+	op = v & 3;
+	freq = v >> 2;
+	freq_hz = 32000000;
+
+	switch (freq)
+	{
+	case 0:
+	case 1:
+		printf ("extern or disabled timer clock?\n");
+		break;
+	case 4: freq_hz =  29493000; break;
+	case 5: freq_hz =  32000000; break;
+	case 6: freq_hz =  32768000; break;
+	case 7: freq_hz = 100000000; break;
+	default:
+		abort();
+		break;
+	}
+
+	printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit);
+	t->scale = 0;
+	if (t->limit > 2048)
+	{
+		t->scale = 2048;
+		ptimer_set_period(timer0.ptimer, freq_hz / t->scale);
+	}
+
+	printf ("op=%d\n", op);
+	switch (op)
+	{
+		case 0:
+			printf ("limit=%d %d\n", t->limit, t->limit/t->scale);
+			ptimer_set_limit(t->ptimer, t->limit / t->scale, 1);
+			break;
+		case 1:
+			ptimer_stop(t->ptimer);
+			break;
+		case 2:
+			ptimer_run(t->ptimer, 0);
+			break;
+		default:
+			abort();
+			break;
+	}
+}
+
+static void timer_ack_irq(void)
+{
+	if (!(r_intr & timer0.mask & rw_intr_mask)) {
+		qemu_irq_lower(timer0.irq[0]);
+		etrax_ack_irq(timer0.env, 1 << 0x1b);
+	}
+}
+
+static void
+timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+	CPUState *env = opaque;
+	printf ("%s %x %x pc=%x\n",
+		__func__, addr, value, env->pc);
+	switch (addr)
+	{
+		case RW_TMR0_DIV:
+			printf ("RW_TMR0_DIV=%x\n", value);
+			timer0.limit = value;
+			break;
+		case RW_TMR0_CTRL:
+			printf ("RW_TMR0_CTRL=%x\n", value);
+			write_ctrl(&timer0, value);
+			break;
+		case RW_TMR1_DIV:
+			printf ("RW_TMR1_DIV=%x\n", value);
+			break;
+		case RW_TMR1_CTRL:
+			printf ("RW_TMR1_CTRL=%x\n", value);
+			break;
+		case RW_INTR_MASK:
+			printf ("RW_INTR_MASK=%x\n", value);
+			rw_intr_mask = value;
+			break;
+		case RW_ACK_INTR:
+			r_intr &= ~value;
+			timer_ack_irq();
+			break;
+		default:
+			printf ("%s %x %x pc=%x\n",
+				__func__, addr, value, env->pc);
+			break;
+	}
+}
+
+static CPUReadMemoryFunc *timer_read[] = {
+    &timer_readb,
+    &timer_readw,
+    &timer_readl,
+};
+
+static CPUWriteMemoryFunc *timer_write[] = {
+    &timer_writeb,
+    &timer_writew,
+    &timer_writel,
+};
+
+static void timer_irq(void *opaque)
+{
+	struct fs_timer_t *t = opaque;
+
+	r_intr |= t->mask;
+	if (t->mask & rw_intr_mask) {
+		qemu_irq_raise(t->irq[0]);
+	}
+}
+
+void etraxfs_timer_init(CPUState *env, qemu_irq *irqs)
+{
+	int timer_regs;
+
+	timer0.bh = qemu_bh_new(timer_irq, &timer0);
+	timer0.ptimer = ptimer_init(timer0.bh);
+	timer0.irq = irqs + 0x1b;
+	timer0.mask = 1;
+	timer0.env = env;
+
+	timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env);
+	cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs);
+}

Modified: trunk/src/host/qemu-neo1973/hw/grackle_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/grackle_pci.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/grackle_pci.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,7 +1,8 @@
 /*
- * QEMU Grackle (heathrow PPC) PCI host
+ * QEMU Grackle PCI host (heathrow OldWorld PowerMac)
  *
- * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2006-2007 Fabrice Bellard
+ * 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
@@ -23,6 +24,7 @@
  */
 
 #include "vl.h"
+#include "ppc_mac.h"
 typedef target_phys_addr_t pci_addr_t;
 #include "pci_host.h"
 
@@ -82,7 +84,7 @@
 
 static void pci_grackle_set_irq(qemu_irq *pic, int irq_num, int level)
 {
-    qemu_set_irq(pic[irq_num + 8], level);
+    qemu_set_irq(pic[irq_num + 0x15], level);
 }
 
 PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
@@ -93,7 +95,7 @@
 
     s = qemu_mallocz(sizeof(GrackleState));
     s->bus = pci_register_bus(pci_grackle_set_irq, pci_grackle_map_irq,
-                              pic, 0, 0);
+                              pic, 0, 4);
 
     pci_mem_config = cpu_register_io_memory(0, pci_grackle_config_read,
                                             pci_grackle_config_write, s);

Modified: trunk/src/host/qemu-neo1973/hw/gt64xxx.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/gt64xxx.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/gt64xxx.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -306,9 +306,8 @@
     GT64120State *s = opaque;
     uint32_t saddr;
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
+    if (!(s->regs[GT_PCI0_CMD] & 1))
+        val = bswap32(val);
 
     saddr = (addr & 0xfff) >> 2;
     switch (saddr) {
@@ -528,8 +527,7 @@
         s->pci->config_reg = val & 0x80fffffc;
         break;
     case GT_PCI0_CFGDATA:
-        if (s->pci->config_reg & (1u << 31))
-            pci_host_data_writel(s->pci, 0, val);
+        pci_host_data_writel(s->pci, 0, val);
         break;
 
     /* Interrupts */
@@ -585,9 +583,7 @@
     uint32_t val;
     uint32_t saddr;
 
-    val = 0;
     saddr = (addr & 0xfff) >> 2;
-
     switch (saddr) {
 
     /* CPU Configuration */
@@ -768,10 +764,7 @@
         val = s->pci->config_reg;
         break;
     case GT_PCI0_CFGDATA:
-        if (!(s->pci->config_reg & (1u << 31)))
-            val = 0xffffffff;
-        else
-            val = pci_host_data_readl(s->pci, 0);
+        val = pci_host_data_readl(s->pci, 0);
         break;
 
     case GT_PCI0_CMD:
@@ -844,9 +837,9 @@
         break;
     }
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
+    if (!(s->regs[GT_PCI0_CMD] & 1))
+        val = bswap32(val);
+
     return val;
 }
 
@@ -1083,19 +1076,12 @@
 
 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;
+    return pci_default_read_config(d, address, len);
 }
 
 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);
 }
 

Modified: trunk/src/host/qemu-neo1973/hw/heathrow_pic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/heathrow_pic.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/heathrow_pic.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,7 +1,8 @@
 /*
- * Heathrow PIC support (standard PowerMac PIC)
+ * Heathrow PIC support (OldWorld PowerMac)
  *
- * Copyright (c) 2005 Fabrice Bellard
+ * Copyright (c) 2005-2007 Fabrice Bellard
+ * 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
@@ -22,6 +23,7 @@
  * THE SOFTWARE.
  */
 #include "vl.h"
+#include "ppc_mac.h"
 
 //#define DEBUG
 
@@ -34,6 +36,7 @@
 
 typedef struct HeathrowPICS {
     HeathrowPIC pics[2];
+    qemu_irq *irqs;
 } HeathrowPICS;
 
 static inline int check_irq(HeathrowPIC *pic)
@@ -45,9 +48,9 @@
 static void heathrow_pic_update(HeathrowPICS *s)
 {
     if (check_irq(&s->pics[0]) || check_irq(&s->pics[1])) {
-        cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
+        qemu_irq_raise(s->irqs[0]);
     } else {
-        cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD);
+        qemu_irq_lower(s->irqs[0]);
     }
 }
 
@@ -57,12 +60,13 @@
     HeathrowPIC *pic;
     unsigned int n;
 
+#ifdef TARGET_WORDS_BIGENDIAN
     value = bswap32(value);
+#endif
+    n = ((addr & 0xfff) - 0x10) >> 4;
 #ifdef DEBUG
-    printf("pic_writel: %08x: %08x\n",
-           addr, value);
+    printf("pic_writel: " PADDRX " %u: %08x\n", addr, n, value);
 #endif
-    n = ((addr & 0xfff) - 0x10) >> 4;
     if (n >= 2)
         return;
     pic = &s->pics[n];
@@ -110,10 +114,11 @@
         }
     }
 #ifdef DEBUG
-    printf("pic_readl: %08x: %08x\n",
-           addr, value);
+    printf("pic_readl: " PADDRX " %u: %08x\n", addr, n, value);
 #endif
+#ifdef TARGET_WORDS_BIGENDIAN
     value = bswap32(value);
+#endif
     return value;
 }
 
@@ -156,13 +161,17 @@
     heathrow_pic_update(s);
 }
 
-qemu_irq *heathrow_pic_init(int *pmem_index)
+qemu_irq *heathrow_pic_init(int *pmem_index,
+                            int nb_cpus, qemu_irq **irqs)
 {
     HeathrowPICS *s;
 
     s = qemu_mallocz(sizeof(HeathrowPICS));
     s->pics[0].level_triggered = 0;
     s->pics[1].level_triggered = 0x1ff00000;
+    /* only 1 CPU */
+    s->irqs = irqs[0];
     *pmem_index = cpu_register_io_memory(0, pic_read, pic_write, s);
+
     return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64);
 }

Modified: trunk/src/host/qemu-neo1973/hw/i8259.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/i8259.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/i8259.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -164,7 +164,7 @@
     }
 
 /* all targets should do this rather than acking the IRQ in the cpu */
-#if defined(TARGET_MIPS)
+#if defined(TARGET_MIPS) || defined(TARGET_PPC)
     else {
         qemu_irq_lower(s->parent_irq);
     }

Modified: trunk/src/host/qemu-neo1973/hw/iommu.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/iommu.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/iommu.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -81,7 +81,7 @@
 #define IOMMU_SBCFG_BA16    0x00000004 /* Slave supports 16 byte bursts */
 #define IOMMU_SBCFG_BA8     0x00000002 /* Slave supports 8 byte bursts */
 #define IOMMU_SBCFG_BYPASS  0x00000001 /* Bypass IOMMU, treat all addresses
-       	                                  produced by this device as pure
+                                          produced by this device as pure
                                           physical. */
 #define IOMMU_SBCFG_MASK    0x00010003
 
@@ -98,7 +98,7 @@
 
 #define PAGE_SHIFT      12
 #define PAGE_SIZE       (1 << PAGE_SHIFT)
-#define PAGE_MASK	(PAGE_SIZE - 1)
+#define PAGE_MASK       (PAGE_SIZE - 1)
 
 typedef struct IOMMUState {
     target_phys_addr_t addr;
@@ -114,9 +114,9 @@
     saddr = (addr - s->addr) >> 2;
     switch (saddr) {
     default:
-	DPRINTF("read reg[%d] = %x\n", (int)saddr, s->regs[saddr]);
-	return s->regs[saddr];
-	break;
+        DPRINTF("read reg[%d] = %x\n", (int)saddr, s->regs[saddr]);
+        return s->regs[saddr];
+        break;
     }
     return 0;
 }
@@ -130,61 +130,61 @@
     DPRINTF("write reg[%d] = %x\n", (int)saddr, val);
     switch (saddr) {
     case IOMMU_CTRL:
-	switch (val & IOMMU_CTRL_RNGE) {
-	case IOMMU_RNGE_16MB:
-	    s->iostart = 0xffffffffff000000ULL;
-	    break;
-	case IOMMU_RNGE_32MB:
-	    s->iostart = 0xfffffffffe000000ULL;
-	    break;
-	case IOMMU_RNGE_64MB:
-	    s->iostart = 0xfffffffffc000000ULL;
-	    break;
-	case IOMMU_RNGE_128MB:
-	    s->iostart = 0xfffffffff8000000ULL;
-	    break;
-	case IOMMU_RNGE_256MB:
-	    s->iostart = 0xfffffffff0000000ULL;
-	    break;
-	case IOMMU_RNGE_512MB:
-	    s->iostart = 0xffffffffe0000000ULL;
-	    break;
-	case IOMMU_RNGE_1GB:
-	    s->iostart = 0xffffffffc0000000ULL;
-	    break;
-	default:
-	case IOMMU_RNGE_2GB:
-	    s->iostart = 0xffffffff80000000ULL;
-	    break;
-	}
-	DPRINTF("iostart = " TARGET_FMT_plx "\n", s->iostart);
-	s->regs[saddr] = ((val & IOMMU_CTRL_MASK) | IOMMU_VERSION);
-	break;
+        switch (val & IOMMU_CTRL_RNGE) {
+        case IOMMU_RNGE_16MB:
+            s->iostart = 0xffffffffff000000ULL;
+            break;
+        case IOMMU_RNGE_32MB:
+            s->iostart = 0xfffffffffe000000ULL;
+            break;
+        case IOMMU_RNGE_64MB:
+            s->iostart = 0xfffffffffc000000ULL;
+            break;
+        case IOMMU_RNGE_128MB:
+            s->iostart = 0xfffffffff8000000ULL;
+            break;
+        case IOMMU_RNGE_256MB:
+            s->iostart = 0xfffffffff0000000ULL;
+            break;
+        case IOMMU_RNGE_512MB:
+            s->iostart = 0xffffffffe0000000ULL;
+            break;
+        case IOMMU_RNGE_1GB:
+            s->iostart = 0xffffffffc0000000ULL;
+            break;
+        default:
+        case IOMMU_RNGE_2GB:
+            s->iostart = 0xffffffff80000000ULL;
+            break;
+        }
+        DPRINTF("iostart = " TARGET_FMT_plx "\n", s->iostart);
+        s->regs[saddr] = ((val & IOMMU_CTRL_MASK) | IOMMU_VERSION);
+        break;
     case IOMMU_BASE:
-	s->regs[saddr] = val & IOMMU_BASE_MASK;
-	break;
+        s->regs[saddr] = val & IOMMU_BASE_MASK;
+        break;
     case IOMMU_TLBFLUSH:
-	DPRINTF("tlb flush %x\n", val);
-	s->regs[saddr] = val & IOMMU_TLBFLUSH_MASK;
-	break;
+        DPRINTF("tlb flush %x\n", val);
+        s->regs[saddr] = val & IOMMU_TLBFLUSH_MASK;
+        break;
     case IOMMU_PGFLUSH:
-	DPRINTF("page flush %x\n", val);
-	s->regs[saddr] = val & IOMMU_PGFLUSH_MASK;
-	break;
+        DPRINTF("page flush %x\n", val);
+        s->regs[saddr] = val & IOMMU_PGFLUSH_MASK;
+        break;
     case IOMMU_SBCFG0:
     case IOMMU_SBCFG1:
     case IOMMU_SBCFG2:
     case IOMMU_SBCFG3:
-	s->regs[saddr] = val & IOMMU_SBCFG_MASK;
-	break;
+        s->regs[saddr] = val & IOMMU_SBCFG_MASK;
+        break;
     case IOMMU_ARBEN:
         // XXX implement SBus probing: fault when reading unmapped
         // addresses, fault cause and address stored to MMU/IOMMU
-	s->regs[saddr] = (val & IOMMU_ARBEN_MASK) | IOMMU_MID;
-	break;
+        s->regs[saddr] = (val & IOMMU_ARBEN_MASK) | IOMMU_MID;
+        break;
     default:
-	s->regs[saddr] = val;
-	break;
+        s->regs[saddr] = val;
+        break;
     }
 }
 
@@ -202,7 +202,8 @@
 
 static uint32_t iommu_page_get_flags(IOMMUState *s, target_phys_addr_t addr)
 {
-    uint32_t iopte, ret;
+    uint32_t ret;
+    target_phys_addr_t iopte;
 #ifdef DEBUG_IOMMU
     target_phys_addr_t pa = addr;
 #endif
@@ -210,9 +211,10 @@
     iopte = s->regs[IOMMU_BASE] << 4;
     addr &= ~s->iostart;
     iopte += (addr >> (PAGE_SHIFT - 2)) & ~3;
-    ret = ldl_phys(iopte);
-    DPRINTF("get flags addr " TARGET_FMT_plx " => pte %x, *ptes = %x\n", pa,
-            iopte, ret);
+    cpu_physical_memory_read(iopte, (uint8_t *)&ret, 4);
+    tswap32s(&ret);
+    DPRINTF("get flags addr " TARGET_FMT_plx " => pte " TARGET_FMT_plx
+            ", *pte = %x\n", pa, iopte, ret);
 
     return ret;
 }
@@ -281,7 +283,7 @@
     int i;
 
     for (i = 0; i < IOMMU_NREGS; i++)
-	qemu_put_be32s(f, &s->regs[i]);
+        qemu_put_be32s(f, &s->regs[i]);
     qemu_put_be64s(f, &s->iostart);
 }
 

Modified: trunk/src/host/qemu-neo1973/hw/irq.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/irq.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/irq.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -55,3 +55,14 @@
     return s;
 }
 
+static void qemu_notirq(void *opaque, int line, int level)
+{
+    struct IRQState *irq = opaque;
+
+    irq->handler(irq->opaque, irq->n, !level);
+}
+
+qemu_irq qemu_irq_invert(qemu_irq irq)
+{
+    return qemu_allocate_irqs(qemu_notirq, irq, 1)[0];
+}

Modified: trunk/src/host/qemu-neo1973/hw/irq.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/irq.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/irq.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -19,3 +19,5 @@
 /* Returns an array of N IRQs.  */
 qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
 
+/* Returns a new IRQ with opposite polarity.  */
+qemu_irq qemu_irq_invert(qemu_irq irq);

Modified: trunk/src/host/qemu-neo1973/hw/m48t59.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/m48t59.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/m48t59.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -161,10 +161,9 @@
     NVRAM->alarm = mktime(tm);
     if (NVRAM->alrm_timer != NULL) {
         qemu_del_timer(NVRAM->alrm_timer);
-	NVRAM->alrm_timer = NULL;
+        if (NVRAM->alarm - time(NULL) > 0)
+            qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
     }
-    if (NVRAM->alarm - time(NULL) > 0)
-	qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
 }
 
 /* Watchdog management */
@@ -188,21 +187,21 @@
 {
     uint64_t interval; /* in 1/16 seconds */
 
+    NVRAM->buffer[0x1FF0] &= ~0x80;
     if (NVRAM->wd_timer != NULL) {
         qemu_del_timer(NVRAM->wd_timer);
-	NVRAM->wd_timer = NULL;
+        if (value != 0) {
+            interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
+            qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
+                           ((interval * 1000) >> 4));
+        }
     }
-    NVRAM->buffer[0x1FF0] &= ~0x80;
-    if (value != 0) {
-	interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
-	qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
-		       ((interval * 1000) >> 4));
-    }
 }
 
 /* Direct access to NVRAM */
-void m48t59_write (m48t59_t *NVRAM, uint32_t addr, uint32_t val)
+void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
 {
+    m48t59_t *NVRAM = opaque;
     struct tm tm;
     int tmp;
 
@@ -359,8 +358,9 @@
     }
 }
 
-uint32_t m48t59_read (m48t59_t *NVRAM, uint32_t addr)
+uint32_t m48t59_read (void *opaque, uint32_t addr)
 {
+    m48t59_t *NVRAM = opaque;
     struct tm tm;
     uint32_t retval = 0xFF;
 
@@ -453,13 +453,17 @@
     return retval;
 }
 
-void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr)
+void m48t59_set_addr (void *opaque, uint32_t addr)
 {
+    m48t59_t *NVRAM = opaque;
+
     NVRAM->addr = addr;
 }
 
-void m48t59_toggle_lock (m48t59_t *NVRAM, int lock)
+void m48t59_toggle_lock (void *opaque, int lock)
 {
+    m48t59_t *NVRAM = opaque;
+
     NVRAM->lock ^= 1 << lock;
 }
 

Modified: trunk/src/host/qemu-neo1973/hw/m48t59.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/m48t59.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/m48t59.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -3,9 +3,9 @@
 
 typedef struct m48t59_t m48t59_t;
 
-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);
+void m48t59_write (void *private, uint32_t addr, uint32_t val);
+uint32_t m48t59_read (void *private, uint32_t addr);
+void m48t59_toggle_lock (void *private, int lock);
 m48t59_t *m48t59_init (qemu_irq IRQ, target_phys_addr_t mem_base,
                        uint32_t io_base, uint16_t size,
                        int type);

Added: trunk/src/host/qemu-neo1973/hw/mac_dbdma.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mac_dbdma.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mac_dbdma.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,79 @@
+/*
+ * PowerMac descriptor-based DMA emulation
+ *
+ * Copyright (c) 2005-2007 Fabrice Bellard
+ * 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 "ppc_mac.h"
+
+/* DBDMA: currently no op - should suffice right now */
+
+static void dbdma_writeb (void *opaque,
+                          target_phys_addr_t addr, uint32_t 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)
+{
+}
+
+static void dbdma_writel (void *opaque,
+                          target_phys_addr_t addr, uint32_t value)
+{
+}
+
+static uint32_t dbdma_readb (void *opaque, target_phys_addr_t addr)
+{
+    printf("%s: 0x" PADDRX " => 0x00000000\n", __func__, addr);
+
+    return 0;
+}
+
+static uint32_t dbdma_readw (void *opaque, target_phys_addr_t addr)
+{
+    return 0;
+}
+
+static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
+{
+    return 0;
+}
+
+static CPUWriteMemoryFunc *dbdma_write[] = {
+    &dbdma_writeb,
+    &dbdma_writew,
+    &dbdma_writel,
+};
+
+static CPUReadMemoryFunc *dbdma_read[] = {
+    &dbdma_readb,
+    &dbdma_readw,
+    &dbdma_readl,
+};
+
+void dbdma_init (int *dbdma_mem_index)
+{
+    *dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL);
+}
+

Added: trunk/src/host/qemu-neo1973/hw/mac_nvram.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mac_nvram.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mac_nvram.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,123 @@
+/*
+ * PowerMac NVRAM emulation
+ *
+ * Copyright (c) 2005-2007 Fabrice Bellard
+ * 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 "ppc_mac.h"
+
+struct MacIONVRAMState {
+    uint8_t data[0x2000];
+};
+
+/* Direct access to NVRAM */
+uint32_t macio_nvram_read (void *opaque, uint32_t addr)
+{
+    MacIONVRAMState *s = opaque;
+    uint32_t ret;
+
+    //    printf("%s: %p addr %04x\n", __func__, s, addr);
+    if (addr < 0x2000)
+        ret = s->data[addr];
+    else
+        ret = -1;
+
+    return ret;
+}
+
+void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val)
+{
+    MacIONVRAMState *s = opaque;
+
+    //    printf("%s: %p addr %04x val %02x\n", __func__, s, addr, val);
+    if (addr < 0x2000)
+        s->data[addr] = val;
+}
+
+/* macio style NVRAM device */
+static void macio_nvram_writeb (void *opaque,
+                                target_phys_addr_t addr, uint32_t value)
+{
+    MacIONVRAMState *s = opaque;
+    addr = (addr >> 4) & 0x1fff;
+    s->data[addr] = value;
+    //    printf("macio_nvram_writeb %04x = %02x\n", addr, value);
+}
+
+static uint32_t macio_nvram_readb (void *opaque, target_phys_addr_t addr)
+{
+    MacIONVRAMState *s = opaque;
+    uint32_t value;
+
+    addr = (addr >> 4) & 0x1fff;
+    value = s->data[addr];
+    //    printf("macio_nvram_readb %04x = %02x\n", addr, value);
+
+    return value;
+}
+
+static CPUWriteMemoryFunc *nvram_write[] = {
+    &macio_nvram_writeb,
+    &macio_nvram_writeb,
+    &macio_nvram_writeb,
+};
+
+static CPUReadMemoryFunc *nvram_read[] = {
+    &macio_nvram_readb,
+    &macio_nvram_readb,
+    &macio_nvram_readb,
+};
+
+MacIONVRAMState *macio_nvram_init (int *mem_index)
+{
+    MacIONVRAMState *s;
+    s = qemu_mallocz(sizeof(MacIONVRAMState));
+    if (!s)
+        return NULL;
+    *mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
+
+    return s;
+}
+
+static uint8_t nvram_chksum (const uint8_t *buf, int n)
+{
+    int sum, i;
+    sum = 0;
+    for(i = 0; i < n; i++)
+        sum += buf[i];
+    return (sum & 0xff) + (sum >> 8);
+}
+
+/* set a free Mac OS NVRAM partition */
+void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len)
+{
+    uint8_t *buf;
+    char partition_name[12] = "wwwwwwwwwwww";
+
+    buf = nvr->data;
+    buf[0] = 0x7f; /* free partition magic */
+    buf[1] = 0; /* checksum */
+    buf[2] = len >> 8;
+    buf[3] = len;
+    memcpy(buf + 4, partition_name, 12);
+    buf[1] = nvram_chksum(buf, 16);
+}

Added: trunk/src/host/qemu-neo1973/hw/macio.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/macio.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/macio.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,116 @@
+/*
+ * PowerMac MacIO device emulation
+ *
+ * Copyright (c) 2005-2007 Fabrice Bellard
+ * 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 "ppc_mac.h"
+
+typedef struct macio_state_t macio_state_t;
+struct macio_state_t {
+    int is_oldworld;
+    int pic_mem_index;
+    int dbdma_mem_index;
+    int cuda_mem_index;
+    int nvram_mem_index;
+    int nb_ide;
+    int ide_mem_index[4];
+};
+
+static void macio_map (PCIDevice *pci_dev, int region_num,
+                       uint32_t addr, uint32_t size, int type)
+{
+    macio_state_t *macio_state;
+    int i;
+
+    macio_state = (macio_state_t *)(pci_dev + 1);
+    if (macio_state->pic_mem_index >= 0) {
+        if (macio_state->is_oldworld) {
+            /* Heathrow PIC */
+            cpu_register_physical_memory(addr + 0x00000, 0x1000,
+                                         macio_state->pic_mem_index);
+        } else {
+            /* OpenPIC */
+            cpu_register_physical_memory(addr + 0x40000, 0x40000,
+                                         macio_state->pic_mem_index);
+        }
+    }
+    if (macio_state->dbdma_mem_index >= 0) {
+        cpu_register_physical_memory(addr + 0x08000, 0x1000,
+                                     macio_state->dbdma_mem_index);
+    }
+    if (macio_state->cuda_mem_index >= 0) {
+        cpu_register_physical_memory(addr + 0x16000, 0x2000,
+                                     macio_state->cuda_mem_index);
+    }
+    for (i = 0; i < macio_state->nb_ide; i++) {
+        if (macio_state->ide_mem_index[i] >= 0) {
+            cpu_register_physical_memory(addr + 0x1f000 + (i * 0x1000), 0x1000,
+                                         macio_state->ide_mem_index[i]);
+        }
+    }
+    if (macio_state->nvram_mem_index >= 0) {
+        cpu_register_physical_memory(addr + 0x60000, 0x20000,
+                                     macio_state->nvram_mem_index);
+    }
+}
+
+void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
+                 int dbdma_mem_index, int cuda_mem_index, int nvram_mem_index,
+                 int nb_ide, int *ide_mem_index)
+{
+    PCIDevice *d;
+    macio_state_t *macio_state;
+    int i;
+
+    d = pci_register_device(bus, "macio",
+                            sizeof(PCIDevice) + sizeof(macio_state_t),
+                            -1, NULL, NULL);
+    macio_state = (macio_state_t *)(d + 1);
+    macio_state->is_oldworld = is_oldworld;
+    macio_state->pic_mem_index = pic_mem_index;
+    macio_state->dbdma_mem_index = dbdma_mem_index;
+    macio_state->cuda_mem_index = cuda_mem_index;
+    macio_state->nvram_mem_index = nvram_mem_index;
+    if (nb_ide > 4)
+        nb_ide = 4;
+    macio_state->nb_ide = nb_ide;
+    for (i = 0; i < nb_ide; i++)
+        macio_state->ide_mem_index[i] = ide_mem_index[i];
+    for (; i < 4; i++)
+        macio_state->ide_mem_index[i] = -1;
+    /* Note: this code is strongly inspirated from the corresponding code
+       in PearPC */
+    d->config[0x00] = 0x6b; // vendor_id
+    d->config[0x01] = 0x10;
+    d->config[0x02] = device_id;
+    d->config[0x03] = device_id >> 8;
+
+    d->config[0x0a] = 0x00; // class_sub = pci2pci
+    d->config[0x0b] = 0xff; // class_base = bridge
+    d->config[0x0e] = 0x00; // header_type
+
+    d->config[0x3d] = 0x01; // interrupt on pin 1
+
+    pci_register_io_region(d, 0, 0x80000,
+                           PCI_ADDRESS_SPACE_MEM, macio_map);
+}

Modified: trunk/src/host/qemu-neo1973/hw/mips_malta.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_malta.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mips_malta.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -791,7 +791,9 @@
 
     /* Load a BIOS image unless a kernel image has been specified. */
     if (!kernel_filename) {
-        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+        if (bios_name == NULL)
+            bios_name = BIOS_FILENAME;
+        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
         ret = load_image(buf, phys_ram_base + bios_offset);
         if (ret < 0 || ret > BIOS_SIZE) {
             fprintf(stderr,

Added: trunk/src/host/qemu-neo1973/hw/mips_mipssim.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_mipssim.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mips_mipssim.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,166 @@
+/*
+ * QEMU/mipssim emulation
+ *
+ * Emulates a very simple machine model similiar to the one use by the
+ * proprietary MIPS emulator.
+ */
+#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 void load_kernel (CPUState *env)
+{
+    int64_t entry, kernel_low, kernel_high;
+    long kernel_size;
+    long initrd_size;
+    ram_addr_t initrd_offset;
+
+    kernel_size = load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND,
+                           &entry, &kernel_low, &kernel_high);
+    if (kernel_size >= 0) {
+        if ((entry & ~0x7fffffffULL) == 0x80000000)
+            entry = (int32_t)entry;
+        env->PC[env->current_tc] = entry;
+    } else {
+        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);
+        }
+    }
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+    cpu_reset(env);
+    cpu_mips_register(env, NULL);
+
+    if (env->kernel_filename)
+        load_kernel (env);
+}
+
+static void
+mips_mipssim_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;
+    CPUState *env;
+    int bios_size;
+    mips_def_t *def;
+
+    /* Init CPUs. */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "5Kf";
+#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);
+
+    /* Load a BIOS / boot exception handler image. */
+    bios_offset = ram_size + vga_ram_size;
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
+    bios_size = load_image(buf, phys_ram_base + bios_offset);
+    if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
+        /* Bail out if we have neither a kernel image nor boot vector code. */
+        fprintf(stderr,
+                "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
+                buf);
+        exit(1);
+    } else {
+        /* Map the BIOS / boot exception handler. */
+        cpu_register_physical_memory(0x1fc00000LL,
+                                     bios_size, bios_offset | IO_MEM_ROM);
+        /* We have a boot vector start address. */
+        env->PC[env->current_tc] = (target_long)(int32_t)0xbfc00000;
+    }
+
+    if (kernel_filename) {
+        env->ram_size = ram_size;
+        env->kernel_filename = kernel_filename;
+        env->kernel_cmdline = kernel_cmdline;
+        env->initrd_filename = initrd_filename;
+        load_kernel(env);
+    }
+
+    /* 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 0x1fd00000. */
+    isa_mmio_init(0x1fd00000, 0x00010000);
+
+    /* A single 16450 sits at offset 0x3f8. It is attached to
+       MIPS CPU INT2, which is interrupt 4. */
+    if (serial_hds[0])
+        serial_init(0x3f8, env->irq[4], serial_hds[0]);
+
+    if (nd_table[0].vlan) {
+        if (nd_table[0].model == NULL
+            || strcmp(nd_table[0].model, "mipsnet") == 0) {
+            /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
+            mipsnet_init(0x4200, env->irq[2], &nd_table[0]);
+        } else if (strcmp(nd_table[0].model, "?") == 0) {
+            fprintf(stderr, "qemu: Supported NICs: mipsnet\n");
+            exit (1);
+        } else {
+            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
+            exit (1);
+        }
+    }
+}
+
+QEMUMachine mips_mipssim_machine = {
+    "mipssim",
+    "MIPS MIPSsim platform",
+    mips_mipssim_init,
+};

Modified: trunk/src/host/qemu-neo1973/hw/mips_pica61.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_pica61.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mips_pica61.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -94,7 +94,9 @@
 
     /* load a BIOS image */
     bios_offset = ram_size + vga_ram_size;
-    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
     bios_size = load_image(buf, phys_ram_base + bios_offset);
     if ((bios_size <= 0) || (bios_size > BIOS_SIZE)) {
         /* fatal */

Modified: trunk/src/host/qemu-neo1973/hw/mips_r4k.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_r4k.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mips_r4k.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -64,9 +64,10 @@
 
 static int mips_qemu_iomemtype = 0;
 
-void load_kernel (CPUState *env, int ram_size, const char *kernel_filename,
-		  const char *kernel_cmdline,
-		  const char *initrd_filename)
+static void load_kernel (CPUState *env, int ram_size,
+                         const char *kernel_filename,
+                         const char *kernel_cmdline,
+                         const char *initrd_filename)
 {
     int64_t entry, kernel_low, kernel_high;
     long kernel_size, initrd_size;
@@ -179,7 +180,9 @@
        preloaded we also initialize the hardware, since the BIOS wasn't
        run. */
     bios_offset = ram_size + vga_ram_size;
-    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
     bios_size = load_image(buf, phys_ram_base + bios_offset);
     if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
 	cpu_register_physical_memory(0x1fc00000,

Modified: trunk/src/host/qemu-neo1973/hw/mips_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_timer.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mips_timer.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -17,9 +17,12 @@
 /* MIPS R4K timer */
 uint32_t cpu_mips_get_count (CPUState *env)
 {
-    return env->CP0_Count +
-        (uint32_t)muldiv64(qemu_get_clock(vm_clock),
-                           100 * 1000 * 1000, ticks_per_sec);
+    if (env->CP0_Cause & (1 << CP0Ca_DC))
+        return env->CP0_Count;
+    else
+        return env->CP0_Count +
+            (uint32_t)muldiv64(qemu_get_clock(vm_clock),
+                               100 * 1000 * 1000, ticks_per_sec);
 }
 
 void cpu_mips_store_count (CPUState *env, uint32_t count)
@@ -63,9 +66,21 @@
     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]);
+    qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
 }
 
+void cpu_mips_start_count(CPUState *env)
+{
+    cpu_mips_store_count(env, env->CP0_Count);
+}
+
+void cpu_mips_stop_count(CPUState *env)
+{
+    /* Store the current value */
+    env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock),
+                                         100 * 1000 * 1000, ticks_per_sec);
+}
+
 static void mips_timer_cb (void *opaque)
 {
     CPUState *env;
@@ -76,10 +91,14 @@
         fprintf(logfile, "%s\n", __func__);
     }
 #endif
+
+    if (env->CP0_Cause & (1 << CP0Ca_DC))
+        return;
+
     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]);
+    qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
 }
 
 void cpu_mips_clock_init (CPUState *env)

Added: trunk/src/host/qemu-neo1973/hw/mipsnet.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mipsnet.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/mipsnet.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,269 @@
+#include "vl.h"
+
+//#define DEBUG_MIPSNET_SEND
+//#define DEBUG_MIPSNET_RECEIVE
+//#define DEBUG_MIPSNET_DATA
+//#define DEBUG_MIPSNET_IRQ
+
+/* MIPSnet register offsets */
+
+#define MIPSNET_DEV_ID		0x00
+# define MIPSNET_DEV_ID_STRING	"MIPSNET0"
+#define MIPSNET_BUSY		0x08
+#define MIPSNET_RX_DATA_COUNT	0x0c
+#define MIPSNET_TX_DATA_COUNT	0x10
+#define MIPSNET_INT_CTL		0x14
+# define MIPSNET_INTCTL_TXDONE		0x00000001
+# define MIPSNET_INTCTL_RXDONE		0x00000002
+# define MIPSNET_INTCTL_TESTBIT		0x80000000
+#define MIPSNET_INTERRUPT_INFO	0x18
+#define MIPSNET_RX_DATA_BUFFER	0x1c
+#define MIPSNET_TX_DATA_BUFFER	0x20
+
+#define MAX_ETH_FRAME_SIZE	1514
+
+typedef struct MIPSnetState {
+    uint32_t busy;
+    uint32_t rx_count;
+    uint32_t rx_read;
+    uint32_t tx_count;
+    uint32_t tx_written;
+    uint32_t intctl;
+    uint8_t rx_buffer[MAX_ETH_FRAME_SIZE];
+    uint8_t tx_buffer[MAX_ETH_FRAME_SIZE];
+    qemu_irq irq;
+    VLANClientState *vc;
+    NICInfo *nd;
+} MIPSnetState;
+
+static void mipsnet_reset(MIPSnetState *s)
+{
+    s->busy = 1;
+    s->rx_count = 0;
+    s->rx_read = 0;
+    s->tx_count = 0;
+    s->tx_written = 0;
+    s->intctl = 0;
+    memset(s->rx_buffer, 0, MAX_ETH_FRAME_SIZE);
+    memset(s->tx_buffer, 0, MAX_ETH_FRAME_SIZE);
+}
+
+static void mipsnet_update_irq(MIPSnetState *s)
+{
+    int isr = !!s->intctl;
+#ifdef DEBUG_MIPSNET_IRQ
+    printf("mipsnet: Set IRQ to %d (%02x)\n", isr, s->intctl);
+#endif
+    qemu_set_irq(s->irq, isr);
+}
+
+static int mipsnet_buffer_full(MIPSnetState *s)
+{
+    if (s->rx_count >= MAX_ETH_FRAME_SIZE)
+        return 1;
+    return 0;
+}
+
+static int mipsnet_can_receive(void *opaque)
+{
+    MIPSnetState *s = opaque;
+
+    if (s->busy)
+        return 0;
+    return !mipsnet_buffer_full(s);
+}
+
+static void mipsnet_receive(void *opaque, const uint8_t *buf, int size)
+{
+    MIPSnetState *s = opaque;
+
+#ifdef DEBUG_MIPSNET_RECEIVE
+    printf("mipsnet: receiving len=%d\n", size);
+#endif
+    if (!mipsnet_can_receive(opaque))
+        return;
+
+    s->busy = 1;
+
+    /* Just accept everything. */
+
+    /* Write packet data. */
+    memcpy(s->rx_buffer, buf, size);
+
+    s->rx_count = size;
+    s->rx_read = 0;
+
+    /* Now we can signal we have received something. */
+    s->intctl |= MIPSNET_INTCTL_RXDONE;
+    mipsnet_update_irq(s);
+}
+
+static uint32_t mipsnet_ioport_read(void *opaque, uint32_t addr)
+{
+    MIPSnetState *s = opaque;
+    int ret = 0;
+    const char *devid = MIPSNET_DEV_ID_STRING;
+
+    addr &= 0x3f;
+    switch (addr) {
+    case MIPSNET_DEV_ID:
+	ret = *((uint32_t *)&devid);
+        break;
+    case MIPSNET_DEV_ID + 4:
+	ret = *((uint32_t *)(&devid + 4));
+        break;
+    case MIPSNET_BUSY:
+	ret = s->busy;
+        break;
+    case MIPSNET_RX_DATA_COUNT:
+	ret = s->rx_count;
+        break;
+    case MIPSNET_TX_DATA_COUNT:
+	ret = s->tx_count;
+        break;
+    case MIPSNET_INT_CTL:
+	ret = s->intctl;
+        s->intctl &= ~MIPSNET_INTCTL_TESTBIT;
+        break;
+    case MIPSNET_INTERRUPT_INFO:
+        /* XXX: This seems to be a per-VPE interrupt number. */
+	ret = 0;
+        break;
+    case MIPSNET_RX_DATA_BUFFER:
+        if (s->rx_count) {
+            s->rx_count--;
+            ret = s->rx_buffer[s->rx_read++];
+        }
+        break;
+    /* Reads as zero. */
+    case MIPSNET_TX_DATA_BUFFER:
+    default:
+        break;
+    }
+#ifdef DEBUG_MIPSNET_DATA
+    printf("mipsnet: read addr=0x%02x val=0x%02x\n", addr, ret);
+#endif
+    return ret;
+}
+
+static void mipsnet_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    MIPSnetState *s = opaque;
+
+    addr &= 0x3f;
+#ifdef DEBUG_MIPSNET_DATA
+    printf("mipsnet: write addr=0x%02x val=0x%02x\n", addr, val);
+#endif
+    switch (addr) {
+    case MIPSNET_TX_DATA_COUNT:
+	s->tx_count = (val <= MAX_ETH_FRAME_SIZE) ? val : 0;
+        s->tx_written = 0;
+        break;
+    case MIPSNET_INT_CTL:
+        if (val & MIPSNET_INTCTL_TXDONE) {
+            s->intctl &= ~MIPSNET_INTCTL_TXDONE;
+        } else if (val & MIPSNET_INTCTL_RXDONE) {
+            s->intctl &= ~MIPSNET_INTCTL_RXDONE;
+        } else if (val & MIPSNET_INTCTL_TESTBIT) {
+            mipsnet_reset(s);
+            s->intctl |= MIPSNET_INTCTL_TESTBIT;
+        } else if (!val) {
+            /* ACK testbit interrupt, flag was cleared on read. */
+        }
+        s->busy = !!s->intctl;
+        mipsnet_update_irq(s);
+        break;
+    case MIPSNET_TX_DATA_BUFFER:
+        s->tx_buffer[s->tx_written++] = val;
+        if (s->tx_written == s->tx_count) {
+            /* Send buffer. */
+#ifdef DEBUG_MIPSNET_SEND
+            printf("mipsnet: sending len=%d\n", s->tx_count);
+#endif
+            qemu_send_packet(s->vc, s->tx_buffer, s->tx_count);
+            s->tx_count = s->tx_written = 0;
+            s->intctl |= MIPSNET_INTCTL_TXDONE;
+            s->busy = 1;
+            mipsnet_update_irq(s);
+        }
+        break;
+    /* Read-only registers */
+    case MIPSNET_DEV_ID:
+    case MIPSNET_BUSY:
+    case MIPSNET_RX_DATA_COUNT:
+    case MIPSNET_INTERRUPT_INFO:
+    case MIPSNET_RX_DATA_BUFFER:
+    default:
+        break;
+    }
+}
+
+static void mipsnet_save(QEMUFile *f, void *opaque)
+{
+    MIPSnetState *s = opaque;
+
+    qemu_put_be32s(f, &s->busy);
+    qemu_put_be32s(f, &s->rx_count);
+    qemu_put_be32s(f, &s->rx_read);
+    qemu_put_be32s(f, &s->tx_count);
+    qemu_put_be32s(f, &s->tx_written);
+    qemu_put_be32s(f, &s->intctl);
+    qemu_put_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
+    qemu_put_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
+}
+
+static int mipsnet_load(QEMUFile *f, void *opaque, int version_id)
+{
+    MIPSnetState *s = opaque;
+
+    if (version_id > 0)
+        return -EINVAL;
+
+    qemu_get_be32s(f, &s->busy);
+    qemu_get_be32s(f, &s->rx_count);
+    qemu_get_be32s(f, &s->rx_read);
+    qemu_get_be32s(f, &s->tx_count);
+    qemu_get_be32s(f, &s->tx_written);
+    qemu_get_be32s(f, &s->intctl);
+    qemu_get_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
+    qemu_get_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
+
+    return 0;
+}
+
+void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
+{
+    MIPSnetState *s;
+
+    s = qemu_mallocz(sizeof(MIPSnetState));
+    if (!s)
+        return;
+
+    register_ioport_write(base, 36, 1, mipsnet_ioport_write, s);
+    register_ioport_read(base, 36, 1, mipsnet_ioport_read, s);
+    register_ioport_write(base, 36, 2, mipsnet_ioport_write, s);
+    register_ioport_read(base, 36, 2, mipsnet_ioport_read, s);
+    register_ioport_write(base, 36, 4, mipsnet_ioport_write, s);
+    register_ioport_read(base, 36, 4, mipsnet_ioport_read, s);
+
+    s->irq = irq;
+    s->nd = nd;
+    if (nd && nd->vlan) {
+        s->vc = qemu_new_vlan_client(nd->vlan, mipsnet_receive,
+                                     mipsnet_can_receive, s);
+    } else {
+        s->vc = NULL;
+    }
+
+    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
+             "mipsnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
+              s->nd->macaddr[0],
+              s->nd->macaddr[1],
+              s->nd->macaddr[2],
+              s->nd->macaddr[3],
+              s->nd->macaddr[4],
+              s->nd->macaddr[5]);
+
+    mipsnet_reset(s);
+    register_savevm("mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
+}

Modified: trunk/src/host/qemu-neo1973/hw/omap.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/omap.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/omap.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -2787,6 +2787,626 @@
     cpu_register_physical_memory(s->clkm.dsp_base, 0x1000, iomemtype[1]);
 }
 
+/* MPU I/O */
+struct omap_mpuio_s {
+    target_phys_addr_t base;
+    qemu_irq irq;
+    qemu_irq kbd_irq;
+    qemu_irq *in;
+    qemu_irq handler[16];
+    qemu_irq wakeup;
+
+    uint16_t inputs;
+    uint16_t outputs;
+    uint16_t dir;
+    uint16_t edge;
+    uint16_t mask;
+    uint16_t ints;
+
+    uint16_t debounce;
+    uint16_t latch;
+    uint8_t event;
+
+    uint8_t buttons[5];
+    uint8_t row_latch;
+    uint8_t cols;
+    int kbd_mask;
+    int clk;
+};
+
+static void omap_mpuio_set(void *opaque, int line, int level)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+    uint16_t prev = s->inputs;
+
+    if (level)
+        s->inputs |= 1 << line;
+    else
+        s->inputs &= ~(1 << line);
+
+    if (((1 << line) & s->dir & ~s->mask) && s->clk) {
+        if ((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) {
+            s->ints |= 1 << line;
+            qemu_irq_raise(s->irq);
+            /* TODO: wakeup */
+        }
+        if ((s->event & (1 << 0)) &&		/* SET_GPIO_EVENT_MODE */
+                (s->event >> 1) == line)	/* PIN_SELECT */
+            s->latch = s->inputs;
+    }
+}
+
+static void omap_mpuio_kbd_update(struct omap_mpuio_s *s)
+{
+    int i;
+    uint8_t *row, rows = 0, cols = ~s->cols;
+
+    for (row = s->buttons + 4, i = 1 << 4; i; row --, i >>= 1)
+        if (*row & cols)
+            rows |= i;
+
+    qemu_set_irq(s->kbd_irq, rows && ~s->kbd_mask && s->clk);
+    s->row_latch = rows ^ 0x1f;
+}
+
+static uint32_t omap_mpuio_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+    int offset = addr - s->base;
+    uint16_t ret;
+
+    switch (offset) {
+    case 0x00:	/* INPUT_LATCH */
+        return s->inputs;
+
+    case 0x04:	/* OUTPUT_REG */
+        return s->outputs;
+
+    case 0x08:	/* IO_CNTL */
+        return s->dir;
+
+    case 0x10:	/* KBR_LATCH */
+        return s->row_latch;
+
+    case 0x14:	/* KBC_REG */
+        return s->cols;
+
+    case 0x18:	/* GPIO_EVENT_MODE_REG */
+        return s->event;
+
+    case 0x1c:	/* GPIO_INT_EDGE_REG */
+        return s->edge;
+
+    case 0x20:	/* KBD_INT */
+        return (s->row_latch != 0x1f) && !s->kbd_mask;
+
+    case 0x24:	/* GPIO_INT */
+        ret = s->ints;
+        s->ints &= s->mask;
+        if (ret)
+            qemu_irq_lower(s->irq);
+        return ret;
+
+    case 0x28:	/* KBD_MASKIT */
+        return s->kbd_mask;
+
+    case 0x2c:	/* GPIO_MASKIT */
+        return s->mask;
+
+    case 0x30:	/* GPIO_DEBOUNCING_REG */
+        return s->debounce;
+
+    case 0x34:	/* GPIO_LATCH_REG */
+        return s->latch;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_mpuio_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+    int offset = addr - s->base;
+    uint16_t diff;
+    int ln;
+
+    switch (offset) {
+    case 0x04:	/* OUTPUT_REG */
+        diff = s->outputs ^ (value & ~s->dir);
+        s->outputs = value;
+	value &= ~s->dir;
+        while ((ln = ffs(diff))) {
+            ln --;
+            if (s->handler[ln])
+                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+            diff &= ~(1 << ln);
+        }
+        break;
+
+    case 0x08:	/* IO_CNTL */
+        diff = s->outputs & (s->dir ^ value);
+        s->dir = value;
+
+        value = s->outputs & ~s->dir;
+        while ((ln = ffs(diff))) {
+            ln --;
+            if (s->handler[ln])
+                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+            diff &= ~(1 << ln);
+        }
+        break;
+
+    case 0x14:	/* KBC_REG */
+        s->cols = value;
+        omap_mpuio_kbd_update(s);
+        break;
+
+    case 0x18:	/* GPIO_EVENT_MODE_REG */
+        s->event = value & 0x1f;
+        break;
+
+    case 0x1c:	/* GPIO_INT_EDGE_REG */
+        s->edge = value;
+        break;
+
+    case 0x28:	/* KBD_MASKIT */
+        s->kbd_mask = value & 1;
+        omap_mpuio_kbd_update(s);
+        break;
+
+    case 0x2c:	/* GPIO_MASKIT */
+        s->mask = value;
+        break;
+
+    case 0x30:	/* GPIO_DEBOUNCING_REG */
+        s->debounce = value & 0x1ff;
+        break;
+
+    case 0x00:	/* INPUT_LATCH */
+    case 0x10:	/* KBR_LATCH */
+    case 0x20:	/* KBD_INT */
+    case 0x24:	/* GPIO_INT */
+    case 0x34:	/* GPIO_LATCH_REG */
+        OMAP_RO_REG(addr);
+        return;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static CPUReadMemoryFunc *omap_mpuio_readfn[] = {
+    omap_badwidth_read16,
+    omap_mpuio_read,
+    omap_badwidth_read16,
+};
+
+static CPUWriteMemoryFunc *omap_mpuio_writefn[] = {
+    omap_badwidth_write16,
+    omap_mpuio_write,
+    omap_badwidth_write16,
+};
+
+void omap_mpuio_reset(struct omap_mpuio_s *s)
+{
+    s->inputs = 0;
+    s->outputs = 0;
+    s->dir = ~0;
+    s->event = 0;
+    s->edge = 0;
+    s->kbd_mask = 0;
+    s->mask = 0;
+    s->debounce = 0;
+    s->latch = 0;
+    s->ints = 0;
+    s->row_latch = 0x1f;
+    s->clk = 1;
+}
+
+static void omap_mpuio_onoff(void *opaque, int line, int on)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+
+    s->clk = on;
+    if (on)
+        omap_mpuio_kbd_update(s);
+}
+
+struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
+                qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
+                omap_clk clk)
+{
+    int iomemtype;
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *)
+            qemu_mallocz(sizeof(struct omap_mpuio_s));
+
+    s->base = base;
+    s->irq = gpio_int;
+    s->kbd_irq = kbd_int;
+    s->wakeup = wakeup;
+    s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16);
+    omap_mpuio_reset(s);
+
+    iomemtype = cpu_register_io_memory(0, omap_mpuio_readfn,
+                    omap_mpuio_writefn, s);
+    cpu_register_physical_memory(s->base, 0x800, iomemtype);
+
+    omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
+
+    return s;
+}
+
+qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s)
+{
+    return s->in;
+}
+
+void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler)
+{
+    if (line >= 16 || line < 0)
+        cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
+    s->handler[line] = handler;
+}
+
+void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
+{
+    if (row >= 5 || row < 0)
+        cpu_abort(cpu_single_env, "%s: No key %i-%i\n",
+                        __FUNCTION__, col, row);
+
+    if (down)
+        s->buttons[row] |= 1 << col;
+    else
+        s->buttons[row] &= ~(1 << col);
+
+    omap_mpuio_kbd_update(s);
+}
+
+/* General-Purpose I/O */
+struct omap_gpio_s {
+    target_phys_addr_t base;
+    qemu_irq irq;
+    qemu_irq *in;
+    qemu_irq handler[16];
+
+    uint16_t inputs;
+    uint16_t outputs;
+    uint16_t dir;
+    uint16_t edge;
+    uint16_t mask;
+    uint16_t ints;
+};
+
+static void omap_gpio_set(void *opaque, int line, int level)
+{
+    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
+    uint16_t prev = s->inputs;
+
+    if (level)
+        s->inputs |= 1 << line;
+    else
+        s->inputs &= ~(1 << line);
+
+    if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
+                    (1 << line) & s->dir & ~s->mask) {
+        s->ints |= 1 << line;
+        qemu_irq_raise(s->irq);
+    }
+}
+
+static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
+    int offset = addr - s->base;
+
+    switch (offset) {
+    case 0x00:	/* DATA_INPUT */
+        return s->inputs;
+
+    case 0x04:	/* DATA_OUTPUT */
+        return s->outputs;
+
+    case 0x08:	/* DIRECTION_CONTROL */
+        return s->dir;
+
+    case 0x0c:	/* INTERRUPT_CONTROL */
+        return s->edge;
+
+    case 0x10:	/* INTERRUPT_MASK */
+        return s->mask;
+
+    case 0x14:	/* INTERRUPT_STATUS */
+        return s->ints;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
+    int offset = addr - s->base;
+    uint16_t diff;
+    int ln;
+
+    switch (offset) {
+    case 0x00:	/* DATA_INPUT */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x04:	/* DATA_OUTPUT */
+        diff = s->outputs ^ (value & ~s->dir);
+        s->outputs = value;
+	value &= ~s->dir;
+        while ((ln = ffs(diff))) {
+            ln --;
+            if (s->handler[ln])
+                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+            diff &= ~(1 << ln);
+        }
+        break;
+
+    case 0x08:	/* DIRECTION_CONTROL */
+        diff = s->outputs & (s->dir ^ value);
+        s->dir = value;
+
+        value = s->outputs & ~s->dir;
+        while ((ln = ffs(diff))) {
+            ln --;
+            if (s->handler[ln])
+                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+            diff &= ~(1 << ln);
+        }
+        break;
+
+    case 0x0c:	/* INTERRUPT_CONTROL */
+        s->edge = value;
+        break;
+
+    case 0x10:	/* INTERRUPT_MASK */
+        s->mask = value;
+        break;
+
+    case 0x14:	/* INTERRUPT_STATUS */
+        s->ints &= ~value;
+        if (!s->ints)
+            qemu_irq_lower(s->irq);
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+/* *Some* sources say the memory region is 32-bit.  */
+static CPUReadMemoryFunc *omap_gpio_readfn[] = {
+    omap_badwidth_read16,
+    omap_gpio_read,
+    omap_badwidth_read16,
+};
+
+static CPUWriteMemoryFunc *omap_gpio_writefn[] = {
+    omap_badwidth_write16,
+    omap_gpio_write,
+    omap_badwidth_write16,
+};
+
+void omap_gpio_reset(struct omap_gpio_s *s)
+{
+    s->inputs = 0;
+    s->outputs = ~0;
+    s->dir = ~0;
+    s->edge = ~0;
+    s->mask = ~0;
+    s->ints = 0;
+}
+
+struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
+                qemu_irq irq, omap_clk clk)
+{
+    int iomemtype;
+    struct omap_gpio_s *s = (struct omap_gpio_s *)
+            qemu_mallocz(sizeof(struct omap_gpio_s));
+
+    s->base = base;
+    s->irq = irq;
+    s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
+    omap_gpio_reset(s);
+
+    iomemtype = cpu_register_io_memory(0, omap_gpio_readfn,
+                    omap_gpio_writefn, s);
+    cpu_register_physical_memory(s->base, 0x1000, iomemtype);
+
+    return s;
+}
+
+qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
+{
+    return s->in;
+}
+
+void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
+{
+    if (line >= 16 || line < 0)
+        cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
+    s->handler[line] = handler;
+}
+
+/* MicroWire Interface */
+struct omap_uwire_s {
+    target_phys_addr_t base;
+    qemu_irq txirq;
+    qemu_irq rxirq;
+    qemu_irq txdrq;
+
+    uint16_t txbuf;
+    uint16_t rxbuf;
+    uint16_t control;
+    uint16_t setup[5];
+
+    struct uwire_slave_s *chip[4];
+};
+
+static void omap_uwire_transfer_start(struct omap_uwire_s *s)
+{
+    int chipselect = (s->control >> 10) & 3;		/* INDEX */
+    struct uwire_slave_s *slave = s->chip[chipselect];
+
+    if ((s->control >> 5) & 0x1f) {			/* NB_BITS_WR */
+        if (s->control & (1 << 12))			/* CS_CMD */
+            if (slave && slave->send)
+                slave->send(slave->opaque,
+                                s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
+        s->control &= ~(1 << 14);			/* CSRB */
+        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
+         * a DRQ.  When is the level IRQ supposed to be reset?  */
+    }
+
+    if ((s->control >> 0) & 0x1f) {			/* NB_BITS_RD */
+        if (s->control & (1 << 12))			/* CS_CMD */
+            if (slave && slave->receive)
+                s->rxbuf = slave->receive(slave->opaque);
+        s->control |= 1 << 15;				/* RDRB */
+        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
+         * a DRQ.  When is the level IRQ supposed to be reset?  */
+    }
+}
+
+static uint32_t omap_uwire_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
+    int offset = addr - s->base;
+
+    switch (offset) {
+    case 0x00:	/* RDR */
+        s->control &= ~(1 << 15);			/* RDRB */
+        return s->rxbuf;
+
+    case 0x04:	/* CSR */
+        return s->control;
+
+    case 0x08:	/* SR1 */
+        return s->setup[0];
+    case 0x0c:	/* SR2 */
+        return s->setup[1];
+    case 0x10:	/* SR3 */
+        return s->setup[2];
+    case 0x14:	/* SR4 */
+        return s->setup[3];
+    case 0x18:	/* SR5 */
+        return s->setup[4];
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_uwire_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
+    int offset = addr - s->base;
+
+    switch (offset) {
+    case 0x00:	/* TDR */
+        s->txbuf = value;				/* TD */
+        s->control |= 1 << 14;				/* CSRB */
+        if ((s->setup[4] & (1 << 2)) &&			/* AUTO_TX_EN */
+                        ((s->setup[4] & (1 << 3)) ||	/* CS_TOGGLE_TX_EN */
+                         (s->control & (1 << 12))))	/* CS_CMD */
+            omap_uwire_transfer_start(s);
+        break;
+
+    case 0x04:	/* CSR */
+        s->control = value & 0x1fff;
+        if (value & (1 << 13))				/* START */
+            omap_uwire_transfer_start(s);
+        break;
+
+    case 0x08:	/* SR1 */
+        s->setup[0] = value & 0x003f;
+        break;
+
+    case 0x0c:	/* SR2 */
+        s->setup[1] = value & 0x0fc0;
+        break;
+
+    case 0x10:	/* SR3 */
+        s->setup[2] = value & 0x0003;
+        break;
+
+    case 0x14:	/* SR4 */
+        s->setup[3] = value & 0x0001;
+        break;
+
+    case 0x18:	/* SR5 */
+        s->setup[4] = value & 0x000f;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static CPUReadMemoryFunc *omap_uwire_readfn[] = {
+    omap_badwidth_read16,
+    omap_uwire_read,
+    omap_badwidth_read16,
+};
+
+static CPUWriteMemoryFunc *omap_uwire_writefn[] = {
+    omap_badwidth_write16,
+    omap_uwire_write,
+    omap_badwidth_write16,
+};
+
+void omap_uwire_reset(struct omap_uwire_s *s)
+{
+    s->control= 0;
+    s->setup[0] = 0;
+    s->setup[1] = 0;
+    s->setup[2] = 0;
+    s->setup[3] = 0;
+    s->setup[4] = 0;
+}
+
+struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
+                qemu_irq *irq, qemu_irq dma, omap_clk clk)
+{
+    int iomemtype;
+    struct omap_uwire_s *s = (struct omap_uwire_s *)
+            qemu_mallocz(sizeof(struct omap_uwire_s));
+
+    s->base = base;
+    s->txirq = irq[0];
+    s->rxirq = irq[1];
+    s->txdrq = dma;
+    omap_uwire_reset(s);
+
+    iomemtype = cpu_register_io_memory(0, omap_uwire_readfn,
+                    omap_uwire_writefn, s);
+    cpu_register_physical_memory(s->base, 0x800, iomemtype);
+
+    return s;
+}
+
+void omap_uwire_attach(struct omap_uwire_s *s,
+                struct uwire_slave_s *slave, int chipselect)
+{
+    if (chipselect < 0 || chipselect > 3)
+        cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", __FUNCTION__,
+                        chipselect);
+
+    s->chip[chipselect] = slave;
+}
+
 /* General chip reset */
 static void omap_mpu_reset(void *opaque)
 {
@@ -2810,10 +3430,13 @@
     omap_dpll_reset(&mpu->dpll[0]);
     omap_dpll_reset(&mpu->dpll[1]);
     omap_dpll_reset(&mpu->dpll[2]);
-    omap_uart_reset(mpu->uart1);
-    omap_uart_reset(mpu->uart2);
-    omap_uart_reset(mpu->uart3);
+    omap_uart_reset(mpu->uart[0]);
+    omap_uart_reset(mpu->uart[1]);
+    omap_uart_reset(mpu->uart[2]);
     omap_mmc_reset(mpu->mmc);
+    omap_mpuio_reset(mpu->mpuio);
+    omap_gpio_reset(mpu->gpio);
+    omap_uwire_reset(mpu->microwire);
     cpu_reset(mpu->env);
 }
 
@@ -2821,7 +3444,8 @@
 {
     struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
 
-    cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
+    if (mpu->env->halted)
+        cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
 }
 
 struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
@@ -2839,6 +3463,8 @@
 
     cpu_arm_set_model(s->env, core ?: "ti925t");
 
+    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
+
     /* Clocks */
     omap_clk_init(s);
 
@@ -2905,13 +3531,13 @@
 
     omap_tcmi_init(0xfffecc00, s);
 
-    s->uart1 = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
+    s->uart[0] = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
                     omap_findclk(s, "uart1_ck"),
                     serial_hds[0]);
-    s->uart2 = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
+    s->uart[1] = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
                     omap_findclk(s, "uart2_ck"),
                     serial_hds[0] ? serial_hds[1] : 0);
-    s->uart3 = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
+    s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
                     omap_findclk(s, "uart3_ck"),
                     serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0);
 
@@ -2922,8 +3548,17 @@
     s->mmc = omap_mmc_init(0xfffb7800, s->irq[1][OMAP_INT_OQN],
                     &s->drq[OMAP_DMA_MMC_TX], omap_findclk(s, "mmc_ck"));
 
+    s->mpuio = omap_mpuio_init(0xfffb5000,
+                    s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
+                    s->wakeup, omap_findclk(s, "clk32-kHz"));
+
+    s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1],
+                    omap_findclk(s, "mpuper_ck"));
+
+    s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
+                    s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
+
     qemu_register_reset(omap_mpu_reset, s);
-    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
 
     return s;
 }

Modified: trunk/src/host/qemu-neo1973/hw/omap.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/omap.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/omap.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -450,6 +450,31 @@
 struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
                 qemu_irq irq, omap_clk clk, CharDriverState *chr);
 
+struct omap_mpuio_s;
+struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
+                qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
+                omap_clk clk);
+qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
+void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
+void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
+
+struct omap_gpio_s;
+struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
+                qemu_irq irq, omap_clk clk);
+qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
+void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
+
+struct uwire_slave_s {
+    uint16_t (*receive)(void *opaque);
+    void (*send)(void *opaque, uint16_t data);
+    void *opaque;
+};
+struct omap_uwire_s;
+struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
+                qemu_irq *irq, qemu_irq dma, omap_clk clk);
+void omap_uwire_attach(struct omap_uwire_s *s,
+                struct uwire_slave_s *slave, int chipselect);
+
 /* omap_lcdc.c */
 struct omap_lcd_panel_s;
 void omap_lcdc_reset(struct omap_lcd_panel_s *s);
@@ -462,6 +487,7 @@
 struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
                 qemu_irq irq, qemu_irq dma[], omap_clk clk);
 void omap_mmc_reset(struct omap_mmc_s *s);
+void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover);
 
 # define cpu_is_omap310(cpu)		(cpu->mpu_model == omap310)
 # define cpu_is_omap1510(cpu)		(cpu->mpu_model == omap1510)
@@ -495,16 +521,19 @@
     unsigned long sram_size;
 
     /* MPUI-TIPB peripherals */
-    struct omap_uart_s *uart3;
+    struct omap_uart_s *uart[3];
 
+    struct omap_gpio_s *gpio;
+
     /* MPU public TIPB peripherals */
     struct omap_32khz_timer_s *os_timer;
 
-    struct omap_uart_s *uart1;
-    struct omap_uart_s *uart2;
-
     struct omap_mmc_s *mmc;
 
+    struct omap_mpuio_s *mpuio;
+
+    struct omap_uwire_s *microwire;
+
     /* MPU private TIPB peripherals */
     struct omap_intr_handler_s *ih[2];
 

Modified: trunk/src/host/qemu-neo1973/hw/omap_mmc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/omap_mmc.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/omap_mmc.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -25,6 +25,7 @@
     target_phys_addr_t base;
     qemu_irq irq;
     qemu_irq *dma;
+    qemu_irq handler[2];
     omap_clk clk;
     SDState *card;
     uint16_t last_cmd;
@@ -506,6 +507,22 @@
     host->transfer = 0;
 }
 
+static void omap_mmc_ro_cb(void *opaque, int level)
+{
+    struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
+
+    if (s->handler[0])
+        qemu_set_irq(s->handler[0], level);
+}
+
+static void omap_mmc_cover_cb(void *opaque, int level)
+{
+    struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
+
+    if (s->handler[1])
+        qemu_set_irq(s->handler[1], level);
+}
+
 struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
                 qemu_irq irq, qemu_irq dma[], omap_clk clk)
 {
@@ -525,7 +542,13 @@
     /* Instantiate the storage */
     s->card = sd_init(sd_bdrv);
 
+    sd_set_cb(s->card, s, omap_mmc_ro_cb, omap_mmc_cover_cb);
+
     return s;
 }
 
-/* TODO: insertion and read-only handlers */
+void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover)
+{
+    s->handler[0] = ro;
+    s->handler[1] = cover;
+}

Modified: trunk/src/host/qemu-neo1973/hw/palm.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/palm.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/palm.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -37,7 +37,8 @@
 }
 
 static void static_write(void *opaque, target_phys_addr_t offset,
-                uint32_t value) {
+                uint32_t value)
+{
 #ifdef SPY
     printf("%s: value %08lx written at " PA_FMT "\n",
                     __FUNCTION__, value, offset);
@@ -57,10 +58,63 @@
 };
 
 /* Palm Tunsgten|E support */
+
+/* Shared GPIOs */
+#define PALMTE_USBDETECT_GPIO	0
+#define PALMTE_USB_OR_DC_GPIO	1
+#define PALMTE_TSC_GPIO		4
+#define PALMTE_PINTDAV_GPIO	6
+#define PALMTE_MMC_WP_GPIO	8
+#define PALMTE_MMC_POWER_GPIO	9
+#define PALMTE_HDQ_GPIO		11
+#define PALMTE_HEADPHONES_GPIO	14
+#define PALMTE_SPEAKER_GPIO	15
+/* MPU private GPIOs */
+#define PALMTE_DC_GPIO		2
+#define PALMTE_MMC_SWITCH_GPIO	4
+#define PALMTE_MMC1_GPIO	6
+#define PALMTE_MMC2_GPIO	7
+#define PALMTE_MMC3_GPIO	11
+
 static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
 {
+    qemu_irq p_int = omap_gpio_in_get(cpu->gpio)[PALMTE_PINTDAV_GPIO];
+
+    omap_uwire_attach(
+                    cpu->microwire,
+                    tsc2102_init(qemu_irq_invert(p_int)),
+                    0);
 }
 
+static struct {
+    int row;
+    int column;
+} palmte_keymap[0x80] = {
+    [0 ... 0x7f] = { -1, -1 },
+    [0x3b] = { 0, 0 },	/* F1	-> Calendar */
+    [0x3c] = { 1, 0 },	/* F2	-> Contacts */
+    [0x3d] = { 2, 0 },	/* F3	-> Tasks List */
+    [0x3e] = { 3, 0 },	/* F4	-> Note Pad */
+    [0x01] = { 4, 0 },	/* Esc	-> Power */
+    [0x4b] = { 0, 1 },	/* 	   Left */
+    [0x50] = { 1, 1 },	/* 	   Down */
+    [0x48] = { 2, 1 },	/*	   Up */
+    [0x4d] = { 3, 1 },	/*	   Right */
+    [0x4c] = { 4, 1 },	/* 	   Centre */
+    [0x39] = { 4, 1 },	/* Spc	-> Centre */
+};
+
+static void palmte_button_event(void *opaque, int keycode)
+{
+    struct omap_mpu_state_s *cpu = (struct omap_mpu_state_s *) opaque;
+
+    if (palmte_keymap[keycode & 0x7f].row != -1)
+        omap_mpuio_key(cpu->mpuio,
+                        palmte_keymap[keycode & 0x7f].row,
+                        palmte_keymap[keycode & 0x7f].column,
+                        !(keycode & 0x80));
+}
+
 static void palmte_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,
@@ -101,6 +155,13 @@
 
     palmte_microwire_setup(cpu);
 
+    qemu_add_kbd_event_handler(palmte_button_event, cpu);
+
+    omap_mmc_handlers(cpu->mmc,
+                    omap_gpio_in_get(cpu->gpio)[PALMTE_MMC_WP_GPIO],
+                    qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
+                            [PALMTE_MMC_SWITCH_GPIO]));
+
     /* Setup initial (reset) machine state */
     if (nb_option_roms) {
         rom_size = get_image_size(option_rom[0]);

Modified: trunk/src/host/qemu-neo1973/hw/pc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pc.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/pc.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -93,6 +93,9 @@
         return intno;
     }
     /* read the irq from the PIC */
+    if (!apic_accept_pic_intr(env))
+        return -1;
+
     intno = pic_read_irq(isa_pic);
     return intno;
 }
@@ -100,10 +103,8 @@
 static void pic_irq_request(void *opaque, int irq, int level)
 {
     CPUState *env = opaque;
-    if (level)
+    if (level && apic_accept_pic_intr(env))
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    else
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
 }
 
 /* PC cmos mappings */
@@ -706,7 +707,9 @@
     vga_ram_addr = qemu_ram_alloc(vga_ram_size);
 
     /* BIOS load */
-    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
     bios_size = get_image_size(buf);
     if (bios_size <= 0 ||
         (bios_size % 65536) != 0) {

Modified: trunk/src/host/qemu-neo1973/hw/pckbd.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pckbd.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/pckbd.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -207,7 +207,7 @@
 #endif
     switch(val) {
     case KBD_CCMD_READ_MODE:
-        kbd_queue(s, s->mode, 0);
+        kbd_queue(s, s->mode, 1);
         break;
     case KBD_CCMD_WRITE_MODE:
     case KBD_CCMD_WRITE_OBUF:

Modified: trunk/src/host/qemu-neo1973/hw/piix_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/piix_pci.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/piix_pci.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -208,6 +208,7 @@
 {
     int i, pic_irq, pic_level;
 
+    piix3_dev->config[0x60 + irq_num] &= ~0x80;   // enable bit
     pci_irq_levels[irq_num] = level;
 
     /* now we change the pic irq level according to the piix irq mappings */

Modified: trunk/src/host/qemu-neo1973/hw/pl110.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl110.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/pl110.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -10,6 +10,7 @@
 #include "vl.h"
 
 #define PL110_CR_EN   0x001
+#define PL110_CR_BGR  0x100
 #define PL110_CR_BEBO 0x200
 #define PL110_CR_BEPO 0x400
 #define PL110_CR_PWR  0x800
@@ -114,6 +115,7 @@
     int first, last = 0;
     int dirty, new_dirty;
     int i;
+    int bpp_offset;
 
     if (!pl110_enabled(s))
         return;
@@ -145,12 +147,17 @@
         fprintf(stderr, "pl110: Bad color depth\n");
         exit(1);
     }
+    if (s->cr & PL110_CR_BGR)
+        bpp_offset = 0;
+    else
+        bpp_offset = 18;
+
     if (s->cr & PL110_CR_BEBO)
-      fn = fntable[s->bpp + 6];
+        fn = fntable[s->bpp + 6 + bpp_offset];
     else if (s->cr & PL110_CR_BEPO)
-      fn = fntable[s->bpp + 12];
+        fn = fntable[s->bpp + 12 + bpp_offset];
     else
-      fn = fntable[s->bpp];
+        fn = fntable[s->bpp + bpp_offset];
 
     src_width = s->cols;
     switch (s->bpp) {

Modified: trunk/src/host/qemu-neo1973/hw/pl110_template.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl110_template.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/pl110_template.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -24,35 +24,68 @@
 #error unknown bit depth
 #endif
 
+#undef RGB
+#define BORDER bgr
 #define ORDER 0
 #include "pl110_template.h"
 #define ORDER 1
 #include "pl110_template.h"
 #define ORDER 2
 #include "pl110_template.h"
+#undef BORDER
+#define RGB
+#define BORDER rgb
+#define ORDER 0
+#include "pl110_template.h"
+#define ORDER 1
+#include "pl110_template.h"
+#define ORDER 2
+#include "pl110_template.h"
+#undef BORDER
 
-static drawfn glue(pl110_draw_fn_,BITS)[18] =
+static drawfn glue(pl110_draw_fn_,BITS)[36] =
 {
-    glue(pl110_draw_line1_lblp,BITS),
-    glue(pl110_draw_line2_lblp,BITS),
-    glue(pl110_draw_line4_lblp,BITS),
-    glue(pl110_draw_line8_lblp,BITS),
-    glue(pl110_draw_line16_lblp,BITS),
-    glue(pl110_draw_line32_lblp,BITS),
+    glue(pl110_draw_line1_lblp_bgr,BITS),
+    glue(pl110_draw_line2_lblp_bgr,BITS),
+    glue(pl110_draw_line4_lblp_bgr,BITS),
+    glue(pl110_draw_line8_lblp_bgr,BITS),
+    glue(pl110_draw_line16_lblp_bgr,BITS),
+    glue(pl110_draw_line32_lblp_bgr,BITS),
 
-    glue(pl110_draw_line1_bbbp,BITS),
-    glue(pl110_draw_line2_bbbp,BITS),
-    glue(pl110_draw_line4_bbbp,BITS),
-    glue(pl110_draw_line8_bbbp,BITS),
-    glue(pl110_draw_line16_bbbp,BITS),
-    glue(pl110_draw_line32_bbbp,BITS),
+    glue(pl110_draw_line1_bbbp_bgr,BITS),
+    glue(pl110_draw_line2_bbbp_bgr,BITS),
+    glue(pl110_draw_line4_bbbp_bgr,BITS),
+    glue(pl110_draw_line8_bbbp_bgr,BITS),
+    glue(pl110_draw_line16_bbbp_bgr,BITS),
+    glue(pl110_draw_line32_bbbp_bgr,BITS),
 
-    glue(pl110_draw_line1_lbbp,BITS),
-    glue(pl110_draw_line2_lbbp,BITS),
-    glue(pl110_draw_line4_lbbp,BITS),
-    glue(pl110_draw_line8_lbbp,BITS),
-    glue(pl110_draw_line16_lbbp,BITS),
-    glue(pl110_draw_line32_lbbp,BITS)
+    glue(pl110_draw_line1_lbbp_bgr,BITS),
+    glue(pl110_draw_line2_lbbp_bgr,BITS),
+    glue(pl110_draw_line4_lbbp_bgr,BITS),
+    glue(pl110_draw_line8_lbbp_bgr,BITS),
+    glue(pl110_draw_line16_lbbp_bgr,BITS),
+    glue(pl110_draw_line32_lbbp_bgr,BITS),
+
+    glue(pl110_draw_line1_lblp_rgb,BITS),
+    glue(pl110_draw_line2_lblp_rgb,BITS),
+    glue(pl110_draw_line4_lblp_rgb,BITS),
+    glue(pl110_draw_line8_lblp_rgb,BITS),
+    glue(pl110_draw_line16_lblp_rgb,BITS),
+    glue(pl110_draw_line32_lblp_rgb,BITS),
+
+    glue(pl110_draw_line1_bbbp_rgb,BITS),
+    glue(pl110_draw_line2_bbbp_rgb,BITS),
+    glue(pl110_draw_line4_bbbp_rgb,BITS),
+    glue(pl110_draw_line8_bbbp_rgb,BITS),
+    glue(pl110_draw_line16_bbbp_rgb,BITS),
+    glue(pl110_draw_line32_bbbp_rgb,BITS),
+
+    glue(pl110_draw_line1_lbbp_rgb,BITS),
+    glue(pl110_draw_line2_lbbp_rgb,BITS),
+    glue(pl110_draw_line4_lbbp_rgb,BITS),
+    glue(pl110_draw_line8_lbbp_rgb,BITS),
+    glue(pl110_draw_line16_lbbp_rgb,BITS),
+    glue(pl110_draw_line32_lbbp_rgb,BITS),
 };
 
 #undef BITS
@@ -61,18 +94,18 @@
 #else
 
 #if ORDER == 0
-#define NAME glue(lblp, BITS)
+#define NAME glue(glue(lblp_, BORDER), BITS)
 #ifdef WORDS_BIGENDIAN
 #define SWAP_WORDS 1
 #endif
 #elif ORDER == 1
-#define NAME glue(bbbp, BITS)
+#define NAME glue(glue(bbbp_, BORDER), BITS)
 #ifndef WORDS_BIGENDIAN
 #define SWAP_WORDS 1
 #endif
 #else
 #define SWAP_PIXELS 1
-#define NAME glue(lbbp, BITS)
+#define NAME glue(glue(lbbp_, BORDER), BITS)
 #ifdef WORDS_BIGENDIAN
 #define SWAP_WORDS 1
 #endif
@@ -195,29 +228,38 @@
 #ifdef SWAP_WORDS
         data = bswap32(data);
 #endif
+#ifdef RGB
+#define LSB r
+#define MSB b
+#else
+#define LSB b
+#define MSB r
+#endif
 #if 0
-        r = data & 0x1f;
+        LSB = data & 0x1f;
         data >>= 5;
         g = data & 0x3f;
         data >>= 6;
-        b = data & 0x1f;
+        MSB = data & 0x1f;
         data >>= 5;
 #else
-        r = (data & 0x1f) << 3;
+        LSB = (data & 0x1f) << 3;
         data >>= 5;
         g = (data & 0x3f) << 2;
         data >>= 6;
-        b = (data & 0x1f) << 3;
+        MSB = (data & 0x1f) << 3;
         data >>= 5;
 #endif
         COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
-        r = (data & 0x1f) << 3;
+        LSB = (data & 0x1f) << 3;
         data >>= 5;
         g = (data & 0x3f) << 2;
         data >>= 6;
-        b = (data & 0x1f) << 3;
+        MSB = (data & 0x1f) << 3;
         data >>= 5;
         COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
+#undef MSB
+#undef LSB
         width -= 2;
         src += 4;
     }
@@ -229,16 +271,25 @@
     unsigned int r, g, b;
     while (width > 0) {
         data = *(uint32_t *)src;
+#ifdef RGB
+#define LSB r
+#define MSB b
+#else
+#define LSB b
+#define MSB r
+#endif
 #ifdef SWAP_WORDS
-        r = data & 0xff;
+        LSB = data & 0xff;
         g = (data >> 8) & 0xff;
-        b = (data >> 16) & 0xff;
+        MSB = (data >> 16) & 0xff;
 #else
-        r = (data >> 24) & 0xff;
+        LSB = (data >> 24) & 0xff;
         g = (data >> 16) & 0xff;
-        b = (data >> 8) & 0xff;
+        MSB = (data >> 8) & 0xff;
 #endif
         COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
+#undef MSB
+#undef LSB
         width--;
         src += 4;
     }

Modified: trunk/src/host/qemu-neo1973/hw/ppc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -22,7 +22,6 @@
  * THE SOFTWARE.
  */
 #include "vl.h"
-#include "m48t59.h"
 
 //#define PPC_DEBUG_IRQ
 //#define PPC_DEBUG_TB
@@ -30,7 +29,10 @@
 extern FILE *logfile;
 extern int loglevel;
 
-void ppc_set_irq (CPUState *env, int n_IRQ, int level)
+static void cpu_ppc_tb_stop (CPUState *env);
+static void cpu_ppc_tb_start (CPUState *env);
+
+static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
 {
     if (level) {
         env->pending_interrupts |= 1 << n_IRQ;
@@ -65,6 +67,19 @@
     /* Don't generate spurious events */
     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
         switch (pin) {
+        case PPC6xx_INPUT_TBEN:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: %s the time base\n",
+                        __func__, level ? "start" : "stop");
+            }
+#endif
+            if (level) {
+                cpu_ppc_tb_start(env);
+            } else {
+                cpu_ppc_tb_stop(env);
+            }
         case PPC6xx_INPUT_INT:
             /* Level sensitive - active high */
 #if defined(PPC_DEBUG_IRQ)
@@ -103,6 +118,7 @@
         case PPC6xx_INPUT_CKSTP_IN:
             /* Level sensitive - active low */
             /* XXX: TODO: relay the signal to CKSTP_OUT pin */
+            /* XXX: Note that the only way to restart the CPU is to reset it */
             if (level) {
 #if defined(PPC_DEBUG_IRQ)
                 if (loglevel & CPU_LOG_INT) {
@@ -110,25 +126,22 @@
                 }
 #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);
+                env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+                /* XXX: TOFIX */
+#if 0
+                cpu_ppc_reset(env);
+#else
+                qemu_system_reset_request();
 #endif
             }
             break;
@@ -162,6 +175,7 @@
     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6);
 }
 
+#if defined(TARGET_PPC64)
 /* PowerPC 970 internal IRQ controller */
 static void ppc970_set_irq (void *opaque, int pin, int level)
 {
@@ -283,9 +297,10 @@
 {
     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, 7);
 }
+#endif /* defined(TARGET_PPC64) */
 
-/* PowerPC 405 internal IRQ controller */
-static void ppc405_set_irq (void *opaque, int pin, int level)
+/* PowerPC 40x internal IRQ controller */
+static void ppc40x_set_irq (void *opaque, int pin, int level)
 {
     CPUState *env = opaque;
     int cur_level;
@@ -300,7 +315,7 @@
     /* Don't generate spurious events */
     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
         switch (pin) {
-        case PPC405_INPUT_RESET_SYS:
+        case PPC40x_INPUT_RESET_SYS:
             if (level) {
 #if defined(PPC_DEBUG_IRQ)
                 if (loglevel & CPU_LOG_INT) {
@@ -311,7 +326,7 @@
                 ppc40x_system_reset(env);
             }
             break;
-        case PPC405_INPUT_RESET_CHIP:
+        case PPC40x_INPUT_RESET_CHIP:
             if (level) {
 #if defined(PPC_DEBUG_IRQ)
                 if (loglevel & CPU_LOG_INT) {
@@ -321,8 +336,7 @@
                 ppc40x_chip_reset(env);
             }
             break;
-            /* No break here */
-        case PPC405_INPUT_RESET_CORE:
+        case PPC40x_INPUT_RESET_CORE:
             /* XXX: TODO: update DBSR[MRR] */
             if (level) {
 #if defined(PPC_DEBUG_IRQ)
@@ -333,7 +347,7 @@
                 ppc40x_core_reset(env);
             }
             break;
-        case PPC405_INPUT_CINT:
+        case PPC40x_INPUT_CINT:
             /* Level sensitive - active high */
 #if defined(PPC_DEBUG_IRQ)
             if (loglevel & CPU_LOG_INT) {
@@ -341,10 +355,9 @@
                         __func__, level);
             }
 #endif
-            /* XXX: TOFIX */
-            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
+            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
             break;
-        case PPC405_INPUT_INT:
+        case PPC40x_INPUT_INT:
             /* Level sensitive - active high */
 #if defined(PPC_DEBUG_IRQ)
             if (loglevel & CPU_LOG_INT) {
@@ -354,7 +367,7 @@
 #endif
             ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
             break;
-        case PPC405_INPUT_HALT:
+        case PPC40x_INPUT_HALT:
             /* Level sensitive - active low */
             if (level) {
 #if defined(PPC_DEBUG_IRQ)
@@ -372,15 +385,15 @@
                 env->halted = 0;
             }
             break;
-        case PPC405_INPUT_DEBUG:
+        case PPC40x_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",
+                fprintf(logfile, "%s: set the debug pin state to %d\n",
                         __func__, level);
             }
 #endif
-            ppc_set_irq(env, EXCP_40x_DEBUG, level);
+            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
             break;
         default:
             /* Unknown pin - do nothing */
@@ -398,28 +411,38 @@
     }
 }
 
-void ppc405_irq_init (CPUState *env)
+void ppc40x_irq_init (CPUState *env)
 {
-    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc405_set_irq, env, 7);
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
+                                                  env, PPC40x_INPUT_NB);
 }
 
 /*****************************************************************************/
 /* PowerPC time base and decrementer emulation */
 struct ppc_tb_t {
     /* Time base management */
-    int64_t  tb_offset;    /* Compensation               */
-    uint32_t tb_freq;      /* TB frequency               */
+    int64_t  tb_offset;    /* Compensation                    */
+    int64_t  atb_offset;   /* Compensation                    */
+    uint32_t tb_freq;      /* TB frequency                    */
     /* Decrementer management */
-    uint64_t decr_next;    /* Tick for next decr interrupt  */
+    uint64_t decr_next;    /* Tick for next decr interrupt    */
+    uint32_t decr_freq;    /* decrementer frequency           */
     struct QEMUTimer *decr_timer;
+#if defined(TARGET_PPC64H)
+    /* Hypervisor decrementer management */
+    uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
+    struct QEMUTimer *hdecr_timer;
+    uint64_t purr_load;
+    uint64_t purr_start;
+#endif
     void *opaque;
 };
 
-static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env)
+static always_inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, uint64_t vmclk,
+                                              int64_t tb_offset)
 {
     /* TB time in tb periods */
-    return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset,
-                    tb_env->tb_freq, ticks_per_sec);
+    return muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec) + tb_offset;
 }
 
 uint32_t cpu_ppc_load_tbl (CPUState *env)
@@ -427,31 +450,22 @@
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
 
-    tb = cpu_ppc_get_tb(tb_env);
-#ifdef PPC_DEBUG_TB
-    {
-        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);
-            }
-        }
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
+#if defined(PPC_DEBUG_TB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
     }
 #endif
 
     return tb & 0xFFFFFFFF;
 }
 
-uint32_t cpu_ppc_load_tbu (CPUState *env)
+static always_inline uint32_t _cpu_ppc_load_tbu (CPUState *env)
 {
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t tb;
 
-    tb = cpu_ppc_get_tb(tb_env);
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
 #if defined(PPC_DEBUG_TB)
     if (loglevel != 0) {
         fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
@@ -461,45 +475,158 @@
     return tb >> 32;
 }
 
-static void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t value)
+uint32_t cpu_ppc_load_tbu (CPUState *env)
 {
-    tb_env->tb_offset = muldiv64(value, ticks_per_sec, tb_env->tb_freq)
-        - qemu_get_clock(vm_clock);
+    return _cpu_ppc_load_tbu(env);
+}
+
+static always_inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t vmclk,
+                                            int64_t *tb_offsetp,
+                                            uint64_t value)
+{
+    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec);
 #ifdef PPC_DEBUG_TB
     if (loglevel != 0) {
         fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value,
-                tb_env->tb_offset);
+                *tb_offsetp);
     }
 #endif
 }
 
+void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
+    tb &= 0xFFFFFFFF00000000ULL;
+    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
+                     &tb_env->tb_offset, tb | (uint64_t)value);
+}
+
+static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
+    tb &= 0x00000000FFFFFFFFULL;
+    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
+                     &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
+}
+
 void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
 {
+    _cpu_ppc_store_tbu(env, value);
+}
+
+uint32_t cpu_ppc_load_atbl (CPUState *env)
+{
     ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
 
-    cpu_ppc_store_tb(tb_env,
-                     ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
+#if defined(PPC_DEBUG_TB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
+    }
+#endif
+
+    return tb & 0xFFFFFFFF;
 }
 
-void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
+uint32_t cpu_ppc_load_atbu (CPUState *env)
 {
     ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
 
-    cpu_ppc_store_tb(tb_env,
-                     ((uint64_t)cpu_ppc_load_tbu(env) << 32) | value);
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
+#if defined(PPC_DEBUG_TB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
+    }
+#endif
+
+    return tb >> 32;
 }
 
-uint32_t cpu_ppc_load_decr (CPUState *env)
+void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
 {
     ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
+    tb &= 0xFFFFFFFF00000000ULL;
+    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
+                     &tb_env->atb_offset, tb | (uint64_t)value);
+}
+
+void cpu_ppc_store_atbu (CPUState *env, uint32_t value)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
+    tb &= 0x00000000FFFFFFFFULL;
+    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
+                     &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
+}
+
+static void cpu_ppc_tb_stop (CPUState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb, atb, vmclk;
+
+    /* If the time base is already frozen, do nothing */
+    if (tb_env->tb_freq != 0) {
+        vmclk = qemu_get_clock(vm_clock);
+        /* Get the time base */
+        tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
+        /* Get the alternate time base */
+        atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
+        /* Store the time base value (ie compute the current offset) */
+        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
+        /* Store the alternate time base value (compute the current offset) */
+        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
+        /* Set the time base frequency to zero */
+        tb_env->tb_freq = 0;
+        /* Now, the time bases are frozen to tb_offset / atb_offset value */
+    }
+}
+
+static void cpu_ppc_tb_start (CPUState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb, atb, vmclk;
+    
+    /* If the time base is not frozen, do nothing */
+    if (tb_env->tb_freq == 0) {
+        vmclk = qemu_get_clock(vm_clock);
+        /* Get the time base from tb_offset */
+        tb = tb_env->tb_offset;
+        /* Get the alternate time base from atb_offset */
+        atb = tb_env->atb_offset;
+        /* Restore the tb frequency from the decrementer frequency */
+        tb_env->tb_freq = tb_env->decr_freq;
+        /* Store the time base value */
+        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
+        /* Store the alternate time base value */
+        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
+    }
+}
+
+static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env,
+                                                  uint64_t *next)
+{
+    ppc_tb_t *tb_env = env->tb_env;
     uint32_t decr;
     int64_t diff;
 
     diff = tb_env->decr_next - qemu_get_clock(vm_clock);
     if (diff >= 0)
-        decr = muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
+        decr = muldiv64(diff, tb_env->decr_freq, ticks_per_sec);
     else
-        decr = -muldiv64(-diff, tb_env->tb_freq, ticks_per_sec);
+        decr = -muldiv64(-diff, tb_env->decr_freq, ticks_per_sec);
 #if defined(PPC_DEBUG_TB)
     if (loglevel != 0) {
         fprintf(logfile, "%s: 0x%08x\n", __func__, decr);
@@ -509,10 +636,36 @@
     return decr;
 }
 
+uint32_t cpu_ppc_load_decr (CPUState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+
+    return _cpu_ppc_load_decr(env, &tb_env->decr_next);
+}
+
+#if defined(TARGET_PPC64H)
+uint32_t cpu_ppc_load_hdecr (CPUState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+
+    return _cpu_ppc_load_decr(env, &tb_env->hdecr_next);
+}
+
+uint64_t cpu_ppc_load_purr (CPUState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t diff;
+
+    diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
+
+    return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
+}
+#endif /* defined(TARGET_PPC64H) */
+
 /* When decrementer expires,
  * all we need to do is generate or queue a CPU exception
  */
-static inline void cpu_ppc_decr_excp (CPUState *env)
+static always_inline void cpu_ppc_decr_excp (CPUState *env)
 {
     /* Raise it */
 #ifdef PPC_DEBUG_TB
@@ -523,9 +676,23 @@
     ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
 }
 
-static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
-                                 uint32_t value, int is_excp)
+static always_inline void cpu_ppc_hdecr_excp (CPUState *env)
 {
+    /* Raise it */
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "raise decrementer exception\n");
+    }
+#endif
+    ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
+}
+
+static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
+                                  struct QEMUTimer *timer,
+                                  void (*raise_excp)(CPUState *),
+                                  uint32_t decr, uint32_t value,
+                                  int is_excp)
+{
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t now, next;
 
@@ -535,21 +702,30 @@
     }
 #endif
     now = qemu_get_clock(vm_clock);
-    next = now + muldiv64(value, ticks_per_sec, tb_env->tb_freq);
+    next = now + muldiv64(value, ticks_per_sec, tb_env->decr_freq);
     if (is_excp)
-        next += tb_env->decr_next - now;
+        next += *nextp - now;
     if (next == now)
         next++;
-    tb_env->decr_next = next;
+    *nextp = next;
     /* Adjust timer */
-    qemu_mod_timer(tb_env->decr_timer, next);
+    qemu_mod_timer(timer, next);
     /* If we set a negative value and the decrementer was positive,
      * raise an exception.
      */
     if ((value & 0x80000000) && !(decr & 0x80000000))
-        cpu_ppc_decr_excp(env);
+        (*raise_excp)(env);
 }
 
+static always_inline void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
+                                               uint32_t value, int is_excp)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+
+    __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
+                         &cpu_ppc_decr_excp, decr, value, is_excp);
+}
+
 void cpu_ppc_store_decr (CPUState *env, uint32_t value)
 {
     _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
@@ -560,17 +736,51 @@
     _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
 }
 
+#if defined(TARGET_PPC64H)
+static always_inline void _cpu_ppc_store_hdecr (CPUState *env, uint32_t hdecr,
+                                                uint32_t value, int is_excp)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+
+    __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
+                         &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
+}
+
+void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
+{
+    _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
+}
+
+static void cpu_ppc_hdecr_cb (void *opaque)
+{
+    _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
+}
+
+void cpu_ppc_store_purr (CPUState *env, uint64_t value)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+
+    tb_env->purr_load = value;
+    tb_env->purr_start = qemu_get_clock(vm_clock);
+}
+#endif /* defined(TARGET_PPC64H) */
+
 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;
+    tb_env->decr_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);
+#if defined(TARGET_PPC64H)
+    _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
+    cpu_ppc_store_purr(env, 0x0000000000000000ULL);
+#endif /* defined(TARGET_PPC64H) */
 }
 
 /* Set up (once) timebase frequency (in Hz) */
@@ -584,6 +794,9 @@
     env->tb_env = tb_env;
     /* Create new timer */
     tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
+#if defined(TARGET_PPC64H)
+    tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
+#endif /* defined(TARGET_PPC64H) */
     cpu_ppc_set_tb_clk(env, freq);
 
     return &cpu_ppc_set_tb_clk;
@@ -596,10 +809,14 @@
 }
 
 void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
-__attribute__ (( alias ("cpu_ppc_store_tbu") ));
+{
+    _cpu_ppc_store_tbu(env, value);
+}
 
 uint32_t cpu_ppc601_load_rtcu (CPUState *env)
-__attribute__ (( alias ("cpu_ppc_load_tbu") ));
+{
+    return _cpu_ppc_load_tbu(env);
+}
 
 void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
 {
@@ -695,7 +912,7 @@
 #endif
         now = qemu_get_clock(vm_clock);
         next = now + muldiv64(ppcemb_timer->pit_reload,
-                              ticks_per_sec, tb_env->tb_freq);
+                              ticks_per_sec, tb_env->decr_freq);
         if (is_excp)
             next += tb_env->decr_next - now;
         if (next == now)
@@ -759,7 +976,7 @@
         /* Cannot occur, but makes gcc happy */
         return;
     }
-    next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
+    next = now + muldiv64(next, ticks_per_sec, tb_env->decr_freq);
     if (next == now)
         next++;
 #ifdef PPC_DEBUG_TB
@@ -861,6 +1078,7 @@
     }
 #endif
     tb_env->tb_freq = freq;
+    tb_env->decr_freq = freq;
     /* XXX: we should also update all timers */
 }
 
@@ -876,6 +1094,7 @@
     env->tb_env = tb_env;
     ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
     tb_env->tb_freq = freq;
+    tb_env->decr_freq = freq;
     tb_env->opaque = ppcemb_timer;
 #ifdef PPC_DEBUG_TB
     if (loglevel != 0) {
@@ -904,6 +1123,9 @@
     void *opaque;
 };
 
+/* XXX: on 460, DCR addresses are 32 bits wide,
+ *      using DCRIPR to get the 22 upper bits of the DCR address
+ */
 #define DCRN_NB 1024
 struct ppc_dcr_t {
     ppc_dcrn_t dcrn[DCRN_NB];
@@ -989,7 +1211,6 @@
     return 0;
 }
 
-
 #if 0
 /*****************************************************************************/
 /* Handle system reset (for now, just stop emulation) */
@@ -1022,63 +1243,75 @@
 
 /*****************************************************************************/
 /* NVRAM helpers */
-void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
+static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
 {
-    m48t59_write(nvram, addr, value);
+    return (*nvram->read_fn)(nvram->opaque, addr);;
 }
 
-uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
+static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
 {
-    return m48t59_read(nvram, addr);
+    (*nvram->write_fn)(nvram->opaque, addr, val);
 }
 
-void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
+void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
 {
-    m48t59_write(nvram, addr, value >> 8);
-    m48t59_write(nvram, addr + 1, value & 0xFF);
+    nvram_write(nvram, addr, value);
 }
 
-uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
+uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
 {
+    return nvram_read(nvram, addr);
+}
+
+void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value)
+{
+    nvram_write(nvram, addr, value >> 8);
+    nvram_write(nvram, addr + 1, value & 0xFF);
+}
+
+uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
+{
     uint16_t tmp;
 
-    tmp = m48t59_read(nvram, addr) << 8;
-    tmp |= m48t59_read(nvram, addr + 1);
+    tmp = nvram_read(nvram, addr) << 8;
+    tmp |= nvram_read(nvram, addr + 1);
+
     return tmp;
 }
 
-void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
+void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value)
 {
-    m48t59_write(nvram, addr, value >> 24);
-    m48t59_write(nvram, addr + 1, (value >> 16) & 0xFF);
-    m48t59_write(nvram, addr + 2, (value >> 8) & 0xFF);
-    m48t59_write(nvram, addr + 3, value & 0xFF);
+    nvram_write(nvram, addr, value >> 24);
+    nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
+    nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
+    nvram_write(nvram, addr + 3, value & 0xFF);
 }
 
-uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
+uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
 {
     uint32_t tmp;
 
-    tmp = m48t59_read(nvram, addr) << 24;
-    tmp |= m48t59_read(nvram, addr + 1) << 16;
-    tmp |= m48t59_read(nvram, addr + 2) << 8;
-    tmp |= m48t59_read(nvram, addr + 3);
+    tmp = nvram_read(nvram, addr) << 24;
+    tmp |= nvram_read(nvram, addr + 1) << 16;
+    tmp |= nvram_read(nvram, addr + 2) << 8;
+    tmp |= nvram_read(nvram, addr + 3);
 
     return tmp;
 }
 
-void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
+void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
                        const unsigned char *str, uint32_t max)
 {
     int i;
 
     for (i = 0; i < max && str[i] != '\0'; i++) {
-        m48t59_write(nvram, addr + i, str[i]);
+        nvram_write(nvram, addr + i, str[i]);
     }
-    m48t59_write(nvram, addr + max - 1, '\0');
+    nvram_write(nvram, addr + i, str[i]);
+    nvram_write(nvram, addr + max - 1, '\0');
 }
 
-int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
+int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
 {
     int i;
 
@@ -1107,7 +1340,7 @@
     return tmp;
 }
 
-uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
+uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
 {
     uint32_t i;
     uint16_t crc = 0xFFFF;
@@ -1127,7 +1360,7 @@
 
 #define CMDLINE_ADDR 0x017ff000
 
-int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
+int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
                           const unsigned char *arch,
                           uint32_t RAM_size, int boot_device,
                           uint32_t kernel_image, uint32_t kernel_size,
@@ -1164,7 +1397,7 @@
     NVRAM_set_word(nvram,   0x56, height);
     NVRAM_set_word(nvram,   0x58, depth);
     crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
-    NVRAM_set_word(nvram,  0xFC, crc);
+    NVRAM_set_word(nvram,   0xFC, crc);
 
     return 0;
 }

Modified: trunk/src/host/qemu-neo1973/hw/ppc405.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc405.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -25,6 +25,8 @@
 #if !defined(PPC_405_H)
 #define PPC_405_H
 
+#include "ppc4xx.h"
+
 /* Bootinfo as set-up by u-boot */
 typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t;
 struct ppc4xx_bd_info_t {
@@ -54,18 +56,9 @@
 };
 
 /* 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);
+ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
+                                uint32_t flags);
 
-/* */
-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 */
@@ -73,14 +66,6 @@
 /* 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_phys_addr_t *ram_bases,

Modified: trunk/src/host/qemu-neo1973/hw/ppc405_boards.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405_boards.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc405_boards.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -226,8 +226,8 @@
                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,
+        pflash_register((uint32_t)(-bios_size), bios_offset,
+                        pflash_table[fl_idx], 65536, fl_sectors, 2,
                         0x0001, 0x22DA, 0x0000, 0x0000);
         fl_idx++;
     } else
@@ -236,7 +236,9 @@
 #ifdef DEBUG_BOARD_INIT
         printf("Load BIOS from file\n");
 #endif
-        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+        if (bios_name == NULL)
+            bios_name = BIOS_FILENAME;
+        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
         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);
@@ -266,7 +268,7 @@
         memset(&bd, 0, sizeof(bd));
         bd.bi_memstart = 0x00000000;
         bd.bi_memsize = ram_size;
-        bd.bi_flashstart = -(bios_size);
+        bd.bi_flashstart = -bios_size;
         bd.bi_flashsize = -bios_size;
         bd.bi_flashoffset = 0;
         bd.bi_sramstart = 0xFFF00000;
@@ -288,7 +290,7 @@
         bd.bi_plb_busfreq = 33333333;
         bd.bi_pci_busfreq = 33333333;
         bd.bi_opbfreq = 33333333;
-        bdloc = ppc405_set_bootinfo(env, &bd);
+        bdloc = ppc405_set_bootinfo(env, &bd, 0x00000001);
         env->gpr[3] = bdloc;
         kernel_base = KERNEL_LOAD_ADDR;
         /* now we can load the kernel */
@@ -539,8 +541,8 @@
                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,
+        pflash_register((uint32_t)(-bios_size), bios_offset,
+                        pflash_table[fl_idx], 65536, fl_sectors, 4,
                         0x0001, 0x22DA, 0x0000, 0x0000);
         fl_idx++;
     } else
@@ -549,7 +551,9 @@
 #ifdef DEBUG_BOARD_INIT
         printf("Load BIOS from file\n");
 #endif
-        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+        if (bios_name == NULL)
+            bios_name = BIOS_FILENAME;
+        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
         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);

Modified: trunk/src/host/qemu-neo1973/hw/ppc405_uc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405_uc.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc405_uc.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -27,7 +27,6 @@
 extern int loglevel;
 extern FILE *logfile;
 
-//#define DEBUG_MMIO
 #define DEBUG_OPBA
 #define DEBUG_SDRAM
 #define DEBUG_GPIO
@@ -36,41 +35,12 @@
 //#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)
+ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
+                                uint32_t flags)
 {
-    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;
 
@@ -103,7 +73,7 @@
     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) {
+    if (flags & 0x00000001) {
         for (i = 0; i < 6; i++)
             stb_raw(phys_ram_base + bdloc + n++, bd->bi_pci_enetaddr2[i]);
     }
@@ -121,203 +91,6 @@
 /* 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,
@@ -622,281 +395,6 @@
 }
 
 /*****************************************************************************/
-/* "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 */
 
@@ -965,7 +463,7 @@
     return bcr;
 }
 
-static inline target_phys_addr_t sdram_base (uint32_t bcr)
+static always_inline target_phys_addr_t sdram_base (uint32_t bcr)
 {
     return bcr & 0xFF800000;
 }
@@ -2691,12 +2189,17 @@
     target_ulong dbsr;
 
     printf("Reset PowerPC core\n");
+    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+    /* XXX: TOFIX */
+#if 0
     cpu_ppc_reset(env);
+#else
+    qemu_system_reset_request();
+#endif
     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)
@@ -2704,13 +2207,18 @@
     target_ulong dbsr;
 
     printf("Reset PowerPC chip\n");
+    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+    /* XXX: TOFIX */
+#if 0
     cpu_ppc_reset(env);
+#else
+    qemu_system_reset_request();
+#endif
     /* 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)
@@ -3037,7 +2545,7 @@
     int i;
 
     memset(clk_setup, 0, sizeof(clk_setup));
-    env = ppc405_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
+    env = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
                       &clk_setup[PPC405CR_TMR_CLK], sysclk);
     /* Memory mapped devices registers */
     mmio = ppc4xx_mmio_init(env, 0xEF600000);
@@ -3050,9 +2558,9 @@
     /* Universal interrupt controller */
     irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
     irqs[PPCUIC_OUTPUT_INT] =
-        ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_INT];
+        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
     irqs[PPCUIC_OUTPUT_CINT] =
-        ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_CINT];
+        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
     pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
     *picp = pic;
     /* SDRAM controller */
@@ -3387,7 +2895,7 @@
 
     memset(clk_setup, 0, sizeof(clk_setup));
     /* init CPUs */
-    env = ppc405_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
+    env = ppc4xx_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;
@@ -3403,9 +2911,9 @@
     /* Universal interrupt controller */
     irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
     irqs[PPCUIC_OUTPUT_INT] =
-        ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_INT];
+        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
     irqs[PPCUIC_OUTPUT_CINT] =
-        ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_CINT];
+        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
     pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
     *picp = pic;
     /* SDRAM controller */

Added: trunk/src/host/qemu-neo1973/hw/ppc4xx.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc4xx.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc4xx.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,49 @@
+/*
+ * QEMU PowerPC 4xx emulation 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_4XX_H)
+#define PPC_4XX_H
+
+/* PowerPC 4xx core initialization */
+CPUState *ppc4xx_init (const unsigned char *cpu_model,
+                       clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
+                       uint32_t sysclk);
+
+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 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);
+
+#endif /* !defined(PPC_4XX_H) */

Added: trunk/src/host/qemu-neo1973/hw/ppc4xx_devs.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc4xx_devs.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc4xx_devs.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,534 @@
+/*
+ * QEMU PowerPC 4xx embedded processors shared devices 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 "ppc4xx.h"
+
+extern int loglevel;
+extern FILE *logfile;
+
+//#define DEBUG_MMIO
+#define DEBUG_UIC
+
+/*****************************************************************************/
+/* Generic PowerPC 4xx processor instanciation */
+CPUState *ppc4xx_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();
+    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_ppc_reset(env);
+    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);
+    /* Register qemu callbacks */
+    qemu_register_reset(&cpu_ppc_reset, env);
+    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+
+    return env;
+}
+
+/*****************************************************************************/
+/* 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;
+}
+
+/*****************************************************************************/
+/* "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);
+}

Modified: trunk/src/host/qemu-neo1973/hw/ppc_chrp.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc_chrp.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc_chrp.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,7 +1,8 @@
 /*
- * QEMU PPC CHRP/PMAC hardware System Emulator
+ * QEMU PowerPC CHRP (currently NewWorld PowerMac) hardware System Emulator
  *
  * Copyright (c) 2004-2007 Fabrice Bellard
+ * 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
@@ -22,172 +23,8 @@
  * THE SOFTWARE.
  */
 #include "vl.h"
+#include "ppc_mac.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
-
-#define KERNEL_LOAD_ADDR 0x01000000
-#define INITRD_LOAD_ADDR 0x01800000
-
-/* MacIO devices (mapped inside the MacIO address space): CUDA, DBDMA,
-   NVRAM */
-
-static int dbdma_mem_index;
-static int cuda_mem_index;
-static int ide0_mem_index = -1;
-static int ide1_mem_index = -1;
-static int openpic_mem_index = -1;
-static int heathrow_pic_mem_index = -1;
-static int macio_nvram_mem_index = -1;
-
-/* DBDMA: currently no op - should suffice right now */
-
-static void dbdma_writeb (void *opaque,
-                          target_phys_addr_t addr, uint32_t 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)
-{
-}
-
-static void dbdma_writel (void *opaque,
-                          target_phys_addr_t addr, uint32_t value)
-{
-}
-
-static uint32_t dbdma_readb (void *opaque, target_phys_addr_t addr)
-{
-    printf("%s: 0x" PADDRX " => 0x00000000\n", __func__, addr);
-
-    return 0;
-}
-
-static uint32_t dbdma_readw (void *opaque, target_phys_addr_t addr)
-{
-    return 0;
-}
-
-static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
-{
-    return 0;
-}
-
-static CPUWriteMemoryFunc *dbdma_write[] = {
-    &dbdma_writeb,
-    &dbdma_writew,
-    &dbdma_writel,
-};
-
-static CPUReadMemoryFunc *dbdma_read[] = {
-    &dbdma_readb,
-    &dbdma_readw,
-    &dbdma_readl,
-};
-
-/* macio style NVRAM device */
-typedef struct MacIONVRAMState {
-    uint8_t data[0x2000];
-} MacIONVRAMState;
-
-static void macio_nvram_writeb (void *opaque,
-                                target_phys_addr_t addr, uint32_t value)
-{
-    MacIONVRAMState *s = opaque;
-    addr = (addr >> 4) & 0x1fff;
-    s->data[addr] = value;
-    //    printf("macio_nvram_writeb %04x = %02x\n", addr, value);
-}
-
-static uint32_t macio_nvram_readb (void *opaque, target_phys_addr_t addr)
-{
-    MacIONVRAMState *s = opaque;
-    uint32_t value;
-
-    addr = (addr >> 4) & 0x1fff;
-    value = s->data[addr];
-    //    printf("macio_nvram_readb %04x = %02x\n", addr, value);
-
-    return value;
-}
-
-static CPUWriteMemoryFunc *macio_nvram_write[] = {
-    &macio_nvram_writeb,
-    &macio_nvram_writeb,
-    &macio_nvram_writeb,
-};
-
-static CPUReadMemoryFunc *macio_nvram_read[] = {
-    &macio_nvram_readb,
-    &macio_nvram_readb,
-    &macio_nvram_readb,
-};
-
-static MacIONVRAMState *macio_nvram_init (void)
-{
-    MacIONVRAMState *s;
-    s = qemu_mallocz(sizeof(MacIONVRAMState));
-    if (!s)
-        return NULL;
-    macio_nvram_mem_index = cpu_register_io_memory(0, macio_nvram_read,
-                                                   macio_nvram_write, s);
-
-    return s;
-}
-
-static void macio_map (PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
-{
-    if (heathrow_pic_mem_index >= 0) {
-        cpu_register_physical_memory(addr + 0x00000, 0x1000,
-                                     heathrow_pic_mem_index);
-    }
-    cpu_register_physical_memory(addr + 0x08000, 0x1000, dbdma_mem_index);
-    cpu_register_physical_memory(addr + 0x16000, 0x2000, cuda_mem_index);
-    if (ide0_mem_index >= 0)
-        cpu_register_physical_memory(addr + 0x1f000, 0x1000, ide0_mem_index);
-    if (ide1_mem_index >= 0)
-        cpu_register_physical_memory(addr + 0x20000, 0x1000, ide1_mem_index);
-    if (openpic_mem_index >= 0) {
-        cpu_register_physical_memory(addr + 0x40000, 0x40000,
-                                     openpic_mem_index);
-    }
-    if (macio_nvram_mem_index >= 0)
-        cpu_register_physical_memory(addr + 0x60000, 0x20000,
-                                     macio_nvram_mem_index);
-}
-
-static void macio_init (PCIBus *bus, int device_id)
-{
-    PCIDevice *d;
-
-    d = pci_register_device(bus, "macio", sizeof(PCIDevice),
-                            -1, NULL, NULL);
-    /* Note: this code is strongly inspirated from the corresponding code
-       in PearPC */
-    d->config[0x00] = 0x6b; // vendor_id
-    d->config[0x01] = 0x10;
-    d->config[0x02] = device_id;
-    d->config[0x03] = device_id >> 8;
-
-    d->config[0x0a] = 0x00; // class_sub = pci2pci
-    d->config[0x0b] = 0xff; // class_base = bridge
-    d->config[0x0e] = 0x00; // header_type
-
-    d->config[0x3d] = 0x01; // interrupt on pin 1
-
-    dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL);
-
-    pci_register_io_region(d, 0, 0x80000,
-                           PCI_ADDRESS_SPACE_MEM, macio_map);
-}
-
 /* UniN device */
 static void unin_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
 {
@@ -210,159 +47,83 @@
     &unin_readl,
 };
 
-/* temporary frame buffer OSI calls for the video.x driver. The right
-   solution is to modify the driver to use VGA PCI I/Os */
-/* XXX: to be removed. This is no way related to emulation */
-static int vga_osi_call (CPUState *env)
+/* PowerPC Mac99 hardware initialisation */
+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)
 {
-    static int vga_vbl_enabled;
-    int linesize;
-
-    //    printf("osi_call R5=%d\n", env->gpr[5]);
-
-    /* same handler as PearPC, coming from the original MOL video
-       driver. */
-    switch(env->gpr[5]) {
-    case 4:
-        break;
-    case 28: /* set_vmode */
-        if (env->gpr[6] != 1 || env->gpr[7] != 0)
-            env->gpr[3] = 1;
-        else
-            env->gpr[3] = 0;
-        break;
-    case 29: /* get_vmode_info */
-        if (env->gpr[6] != 0) {
-            if (env->gpr[6] != 1 || env->gpr[7] != 0) {
-                env->gpr[3] = 1;
-                break;
-            }
-        }
-        env->gpr[3] = 0;
-        env->gpr[4] = (1 << 16) | 1; /* num_vmodes, cur_vmode */
-        env->gpr[5] = (1 << 16) | 0; /* num_depths, cur_depth_mode */
-        env->gpr[6] = (graphic_width << 16) | graphic_height; /* w, h */
-        env->gpr[7] = 85 << 16; /* refresh rate */
-        env->gpr[8] = (graphic_depth + 7) & ~7; /* depth (round to byte) */
-        linesize = ((graphic_depth + 7) >> 3) * graphic_width;
-        linesize = (linesize + 3) & ~3;
-        env->gpr[9] = (linesize << 16) | 0; /* row_bytes, offset */
-        break;
-    case 31: /* set_video power */
-        env->gpr[3] = 0;
-        break;
-    case 39: /* video_ctrl */
-        if (env->gpr[6] == 0 || env->gpr[6] == 1)
-            vga_vbl_enabled = env->gpr[6];
-        env->gpr[3] = 0;
-        break;
-    case 47:
-        break;
-    case 59: /* set_color */
-        /* R6 = index, R7 = RGB */
-        env->gpr[3] = 0;
-        break;
-    case 64: /* get color */
-        /* R6 = index */
-        env->gpr[3] = 0;
-        break;
-    case 116: /* set hwcursor */
-        /* R6 = x, R7 = y, R8 = visible, R9 = data */
-        break;
-    default:
-        fprintf(stderr, "unsupported OSI call R5=" REGX "\n", env->gpr[5]);
-        break;
-    }
-
-    return 1; /* osi_call handled */
-}
-
-static uint8_t nvram_chksum (const uint8_t *buf, int n)
-{
-    int sum, i;
-    sum = 0;
-    for(i = 0; i < n; i++)
-        sum += buf[i];
-    return (sum & 0xff) + (sum >> 8);
-}
-
-/* set a free Mac OS NVRAM partition */
-void pmac_format_nvram_partition (uint8_t *buf, int len)
-{
-    char partition_name[12] = "wwwwwwwwwwww";
-
-    buf[0] = 0x7f; /* free partition magic */
-    buf[1] = 0; /* checksum */
-    buf[2] = len >> 8;
-    buf[3] = len;
-    memcpy(buf + 4, partition_name, 12);
-    buf[1] = nvram_chksum(buf, 16);
-}
-
-/* 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,
-                           const char *cpu_model,
-                           int is_heathrow)
-{
     CPUState *env, *envs[MAX_CPUS];
     char buf[1024];
     qemu_irq *pic, **openpic_irqs;
-    m48t59_t *nvram;
     int unin_memory;
     int linux_boot, i;
     unsigned long bios_offset, vga_bios_offset;
     uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
     ppc_def_t *def;
     PCIBus *pci_bus;
-    const char *arch_name;
+    nvram_t nvram;
+#if 0
+    MacIONVRAMState *nvr;
+    int nvram_mem_index;
+#endif
+    m48t59_t *m48t59;
     int vga_bios_size, bios_size;
     qemu_irq *dummy_irq;
+    int pic_mem_index, dbdma_mem_index, cuda_mem_index;
+    int ide_mem_index[2];
 
     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);
-
-    /* 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.
-     */
+        cpu_model = "default";
     ppc_find_by_name(cpu_model, &def);
     if (def == NULL) {
         cpu_abort(env, "Unable to find PowerPC CPU definition\n");
     }
     for (i = 0; i < smp_cpus; i++) {
         cpu_ppc_register(env, def);
+        cpu_ppc_reset(env);
         /* Set time-base frequency to 100 Mhz */
         cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+#if 0
         env->osi_call = vga_osi_call;
+#endif
+        qemu_register_reset(&cpu_ppc_reset, env);
+        register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
         envs[i] = env;
     }
+    if (env->nip < 0xFFF80000) {
+        /* Special test for PowerPC 601:
+         * the boot vector is at 0xFFF00100, then we need a 1MB BIOS.
+         * But the NVRAM is located at 0xFFF04000...
+         */
+        cpu_abort(env, "Mac99 hardware can not handle 1 MB BIOS\n");
+    }
 
     /* allocate RAM */
     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
 
     /* allocate and load BIOS */
     bios_offset = ram_size + vga_ram_size;
-    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
     bios_size = load_image(buf, phys_ram_base + bios_offset);
     if (bios_size < 0 || bios_size > BIOS_SIZE) {
         cpu_abort(env, "qemu: could not load PowerPC bios '%s'\n", buf);
         exit(1);
     }
     bios_size = (bios_size + 0xfff) & ~0xfff;
+    if (bios_size > 0x00080000) {
+        /* As the NVRAM is located at 0xFFF04000, we cannot use 1 MB BIOSes */
+        cpu_abort(env, "Mac99 hardware can not handle 1 MB BIOS\n");
+    }
     cpu_register_physical_memory((uint32_t)(-bios_size),
                                  bios_size, bios_offset | IO_MEM_ROM);
 
@@ -418,150 +179,113 @@
         initrd_size = 0;
     }
 
-    if (is_heathrow) {
-        isa_mem_base = 0x80000000;
+    isa_mem_base = 0x80000000;
 
-        /* Register 2 MB of ISA IO space */
-        isa_mmio_init(0xfe000000, 0x00200000);
+    /* Register 8 MB of ISA IO space */
+    isa_mmio_init(0xf2000000, 0x00800000);
 
-        /* init basic PC hardware */
-        if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
-            cpu_abort(env, "Only 6xx bus is supported on heathrow machine\n");
+    /* UniN init */
+    unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
+    cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
+
+    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;
+#if defined(TARGET_PPC64)
+        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;
+#endif /* defined(TARGET_PPC64) */
+        default:
+            cpu_abort(env, "Bus model not supported on mac99 machine\n");
             exit(1);
         }
-        pic = heathrow_pic_init(&heathrow_pic_mem_index);
-        pci_bus = pci_grackle_init(0xfec00000, pic);
-        pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
-                     ram_size, vga_ram_size,
-                     vga_bios_offset, vga_bios_size);
+    }
+    pic = openpic_init(NULL, &pic_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,
+                 ram_size, vga_ram_size,
+                 vga_bios_offset, vga_bios_size);
+    
+    /* XXX: suppress that */
+    dummy_irq = i8259_init(NULL);
 
-        /* XXX: suppress that */
-        dummy_irq = i8259_init(NULL);
-
-        /* XXX: use Mac Serial port */
-        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], -1);
-        }
-
-        pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
-
-        /* cuda also initialize ADB */
-        cuda_mem_index = cuda_init(pic[0x12]);
-
-        adb_kbd_init(&adb_bus);
-        adb_mouse_init(&adb_bus);
-
-        {
-            MacIONVRAMState *nvr;
-            nvr = macio_nvram_init();
-            pmac_format_nvram_partition(nvr->data, 0x2000);
-        }
-
-        macio_init(pci_bus, 0x0017);
-
-        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);
-
-        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, "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,
-                     ram_size, vga_ram_size,
-                     vga_bios_offset, vga_bios_size);
-
-        /* XXX: suppress that */
-        dummy_irq = i8259_init(NULL);
-
-        /* XXX: use Mac Serial port */
-        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], -1);
-        }
+    /* XXX: use Mac Serial port */
+    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], -1);
+    }
 #if 1
-        ide0_mem_index = pmac_ide_init(&bs_table[0], pic[0x13]);
-        ide1_mem_index = pmac_ide_init(&bs_table[2], pic[0x14]);
+    ide_mem_index[0] = pmac_ide_init(&bs_table[0], pic[0x13]);
+    ide_mem_index[1] = pmac_ide_init(&bs_table[2], pic[0x14]);
 #else
-        pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
+    pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
 #endif
-        /* cuda also initialize ADB */
-        cuda_mem_index = cuda_init(pic[0x19]);
+    /* cuda also initialize ADB */
+    cuda_init(&cuda_mem_index, pic[0x19]);
+    
+    adb_kbd_init(&adb_bus);
+    adb_mouse_init(&adb_bus);
 
-        adb_kbd_init(&adb_bus);
-        adb_mouse_init(&adb_bus);
+    dbdma_init(&dbdma_mem_index);
 
-        macio_init(pci_bus, 0x0022);
+    macio_init(pci_bus, 0x0022, 0, pic_mem_index, dbdma_mem_index,
+               cuda_mem_index, -1, 2, ide_mem_index);
 
-        nvram = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
-
-        arch_name = "MAC99";
-    }
-
     if (usb_enabled) {
         usb_ohci_init_pci(pci_bus, 3, -1);
     }
 
     if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
         graphic_depth = 15;
-
-    PPC_NVRAM_set_params(nvram, NVRAM_SIZE, arch_name, ram_size, boot_device,
+#if 0 /* XXX: this is ugly but needed for now, or OHW won't boot */
+    /* The NewWorld NVRAM is not located in the MacIO device */
+    nvr = macio_nvram_init(&nvram_mem_index);
+    pmac_format_nvram_partition(nvr, 0x2000);
+    cpu_register_physical_memory(0xFFF04000, 0x20000, nvram_mem_index);
+    nvram.opaque = nvr;
+    nvram.read_fn = &macio_nvram_read;
+    nvram.write_fn = &macio_nvram_write;
+#else
+    m48t59 = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
+    nvram.opaque = m48t59;
+    nvram.read_fn = &m48t59_read;
+    nvram.write_fn = &m48t59_write;
+#endif
+    PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "MAC99", ram_size, boot_device,
                          kernel_base, kernel_size,
                          kernel_cmdline,
                          initrd_base, initrd_size,
@@ -572,44 +296,10 @@
 
     /* Special port to get debug messages from Open-Firmware */
     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,
-                             const char *cpu_model)
-{
-    ppc_chrp_init(ram_size, vga_ram_size, boot_device,
-                  ds, fd_filename, snapshot,
-                  kernel_filename, kernel_cmdline,
-                  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,
-                               const char *cpu_model)
-{
-    ppc_chrp_init(ram_size, vga_ram_size, boot_device,
-                  ds, fd_filename, snapshot,
-                  kernel_filename, kernel_cmdline,
-                  initrd_filename, cpu_model, 1);
-}
-
 QEMUMachine core99_machine = {
     "mac99",
     "Mac99 based PowerMAC",
     ppc_core99_init,
 };
-
-QEMUMachine heathrow_machine = {
-    "g3bw",
-    "Heathrow based PowerMAC",
-    ppc_heathrow_init,
-};

Added: trunk/src/host/qemu-neo1973/hw/ppc_mac.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc_mac.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc_mac.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,70 @@
+/*
+ * QEMU PowerMac emulation shared definitions and prototypes
+ *
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * 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_MAC_H__)
+#define __PPC_MAC_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
+
+#define KERNEL_LOAD_ADDR 0x01000000
+#define INITRD_LOAD_ADDR 0x01800000
+
+/* DBDMA */
+void dbdma_init (int *dbdma_mem_index);
+
+/* Cuda */
+void cuda_init (int *cuda_mem_index, qemu_irq irq);
+
+/* MacIO */
+void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
+                 int dbdma_mem_index, int cuda_mem_index, int nvram_mem_index,
+                 int nb_ide, int *ide_mem_index);
+
+/* NewWorld PowerMac IDE */
+int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq);
+
+/* Heathrow PIC */
+qemu_irq *heathrow_pic_init(int *pmem_index,
+                            int nb_cpus, qemu_irq **irqs);
+
+/* Grackle PCI */
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic);
+
+/* UniNorth PCI */
+PCIBus *pci_pmac_init(qemu_irq *pic);
+
+/* Mac NVRAM */
+typedef struct MacIONVRAMState MacIONVRAMState;
+
+MacIONVRAMState *macio_nvram_init (int *mem_index);
+void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len);
+uint32_t macio_nvram_read (void *opaque, uint32_t addr);
+void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val);
+
+#endif /* !defined(__PPC_MAC_H__) */

Added: trunk/src/host/qemu-neo1973/hw/ppc_oldworld.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc_oldworld.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc_oldworld.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,309 @@
+/*
+ * QEMU OldWorld PowerMac (currently ~G3 B&W) hardware System Emulator
+ *
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * 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 "ppc_mac.h"
+
+/* temporary frame buffer OSI calls for the video.x driver. The right
+   solution is to modify the driver to use VGA PCI I/Os */
+/* XXX: to be removed. This is no way related to emulation */
+static int vga_osi_call (CPUState *env)
+{
+    static int vga_vbl_enabled;
+    int linesize;
+
+    //    printf("osi_call R5=%d\n", env->gpr[5]);
+
+    /* same handler as PearPC, coming from the original MOL video
+       driver. */
+    switch(env->gpr[5]) {
+    case 4:
+        break;
+    case 28: /* set_vmode */
+        if (env->gpr[6] != 1 || env->gpr[7] != 0)
+            env->gpr[3] = 1;
+        else
+            env->gpr[3] = 0;
+        break;
+    case 29: /* get_vmode_info */
+        if (env->gpr[6] != 0) {
+            if (env->gpr[6] != 1 || env->gpr[7] != 0) {
+                env->gpr[3] = 1;
+                break;
+            }
+        }
+        env->gpr[3] = 0;
+        env->gpr[4] = (1 << 16) | 1; /* num_vmodes, cur_vmode */
+        env->gpr[5] = (1 << 16) | 0; /* num_depths, cur_depth_mode */
+        env->gpr[6] = (graphic_width << 16) | graphic_height; /* w, h */
+        env->gpr[7] = 85 << 16; /* refresh rate */
+        env->gpr[8] = (graphic_depth + 7) & ~7; /* depth (round to byte) */
+        linesize = ((graphic_depth + 7) >> 3) * graphic_width;
+        linesize = (linesize + 3) & ~3;
+        env->gpr[9] = (linesize << 16) | 0; /* row_bytes, offset */
+        break;
+    case 31: /* set_video power */
+        env->gpr[3] = 0;
+        break;
+    case 39: /* video_ctrl */
+        if (env->gpr[6] == 0 || env->gpr[6] == 1)
+            vga_vbl_enabled = env->gpr[6];
+        env->gpr[3] = 0;
+        break;
+    case 47:
+        break;
+    case 59: /* set_color */
+        /* R6 = index, R7 = RGB */
+        env->gpr[3] = 0;
+        break;
+    case 64: /* get color */
+        /* R6 = index */
+        env->gpr[3] = 0;
+        break;
+    case 116: /* set hwcursor */
+        /* R6 = x, R7 = y, R8 = visible, R9 = data */
+        break;
+    default:
+        fprintf(stderr, "unsupported OSI call R5=" REGX "\n", env->gpr[5]);
+        break;
+    }
+
+    return 1; /* osi_call handled */
+}
+
+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)
+{
+    CPUState *env, *envs[MAX_CPUS];
+    char buf[1024];
+    qemu_irq *pic, **heathrow_irqs;
+    nvram_t nvram;
+    m48t59_t *m48t59;
+    int linux_boot, i;
+    unsigned long bios_offset, vga_bios_offset;
+    uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
+    ppc_def_t *def;
+    PCIBus *pci_bus;
+    MacIONVRAMState *nvr;
+    int vga_bios_size, bios_size;
+    qemu_irq *dummy_irq;
+    int pic_mem_index, nvram_mem_index, dbdma_mem_index, cuda_mem_index;
+
+    linux_boot = (kernel_filename != NULL);
+
+    /* init CPUs */
+    env = cpu_init();
+    if (cpu_model == NULL)
+        cpu_model = "default";
+    ppc_find_by_name(cpu_model, &def);
+    if (def == NULL) {
+        cpu_abort(env, "Unable to find PowerPC CPU definition\n");
+    }
+    for (i = 0; i < smp_cpus; i++) {
+        cpu_ppc_register(env, def);
+        cpu_ppc_reset(env);
+        /* Set time-base frequency to 100 Mhz */
+        cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+        env->osi_call = vga_osi_call;
+        qemu_register_reset(&cpu_ppc_reset, env);
+        register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+        envs[i] = env;
+    }
+    if (env->nip < 0xFFF80000) {
+        /* Special test for PowerPC 601:
+         * the boot vector is at 0xFFF00100, then we need a 1MB BIOS.
+         * But the NVRAM is located at 0xFFF04000...
+         */
+        cpu_abort(env, "G3BW Mac hardware can not handle 1 MB BIOS\n");
+    }
+
+    /* allocate RAM */
+    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
+
+    /* allocate and load BIOS */
+    bios_offset = ram_size + vga_ram_size;
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
+    bios_size = load_image(buf, phys_ram_base + bios_offset);
+    if (bios_size < 0 || bios_size > BIOS_SIZE) {
+        cpu_abort(env, "qemu: could not load PowerPC bios '%s'\n", buf);
+        exit(1);
+    }
+    bios_size = (bios_size + 0xfff) & ~0xfff;
+    if (bios_size > 0x00080000) {
+        /* As the NVRAM is located at 0xFFF04000, we cannot use 1 MB BIOSes */
+        cpu_abort(env, "G3BW Mac hardware can not handle 1 MB BIOS\n");
+    }
+    cpu_register_physical_memory((uint32_t)(-bios_size),
+                                 bios_size, bios_offset | IO_MEM_ROM);
+
+    /* allocate and load VGA BIOS */
+    vga_bios_offset = bios_offset + bios_size;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+    vga_bios_size = load_image(buf, phys_ram_base + vga_bios_offset + 8);
+    if (vga_bios_size < 0) {
+        /* if no bios is present, we can still work */
+        fprintf(stderr, "qemu: warning: could not load VGA bios '%s'\n", buf);
+        vga_bios_size = 0;
+    } else {
+        /* set a specific header (XXX: find real Apple format for NDRV
+           drivers) */
+        phys_ram_base[vga_bios_offset] = 'N';
+        phys_ram_base[vga_bios_offset + 1] = 'D';
+        phys_ram_base[vga_bios_offset + 2] = 'R';
+        phys_ram_base[vga_bios_offset + 3] = 'V';
+        cpu_to_be32w((uint32_t *)(phys_ram_base + vga_bios_offset + 4),
+                     vga_bios_size);
+        vga_bios_size += 8;
+    }
+    vga_bios_size = (vga_bios_size + 0xfff) & ~0xfff;
+
+    if (linux_boot) {
+        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) {
+            cpu_abort(env, "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) {
+                cpu_abort(env, "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;
+    }
+
+    isa_mem_base = 0x80000000;
+    
+    /* Register 2 MB of ISA IO space */
+    isa_mmio_init(0xfe000000, 0x00200000);
+
+    /* XXX: we register only 1 output pin for heathrow PIC */
+    heathrow_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
+    heathrow_irqs[0] =
+        qemu_mallocz(smp_cpus * sizeof(qemu_irq) * 1);
+    /* Connect the heathrow PIC outputs to the 6xx bus */
+    for (i = 0; i < smp_cpus; i++) {
+        switch (PPC_INPUT(env)) {
+        case PPC_FLAGS_INPUT_6xx:
+            heathrow_irqs[i] = heathrow_irqs[0] + (i * 1);
+            heathrow_irqs[i][0] =
+                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
+            break;
+        default:
+            cpu_abort(env, "Bus model not supported on OldWorld Mac machine\n");
+            exit(1);
+        }
+    }
+
+    /* 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(&pic_mem_index, 1, heathrow_irqs);
+    pci_bus = pci_grackle_init(0xfec00000, pic);
+    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 */
+    dummy_irq = i8259_init(NULL);
+
+    /* XXX: use Mac Serial port */
+    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], -1);
+    }
+    
+    pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
+
+    /* cuda also initialize ADB */
+    cuda_init(&cuda_mem_index, pic[0x12]);
+
+    adb_kbd_init(&adb_bus);
+    adb_mouse_init(&adb_bus);
+    
+    nvr = macio_nvram_init(&nvram_mem_index);
+    pmac_format_nvram_partition(nvr, 0x2000);
+
+    dbdma_init(&dbdma_mem_index);
+    
+    macio_init(pci_bus, 0x0017, 1, pic_mem_index, dbdma_mem_index,
+               cuda_mem_index, nvram_mem_index, 0, NULL);
+
+    if (usb_enabled) {
+        usb_ohci_init_pci(pci_bus, 3, -1);
+    }
+
+    if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
+        graphic_depth = 15;
+
+    m48t59 = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
+    nvram.opaque = m48t59;
+    nvram.read_fn = &m48t59_read;
+    nvram.write_fn = &m48t59_write;
+    PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "HEATHROW", ram_size, boot_device,
+                         kernel_base, kernel_size,
+                         kernel_cmdline,
+                         initrd_base, initrd_size,
+                         /* XXX: need an option to load a NVRAM image */
+                         0,
+                         graphic_width, graphic_height, graphic_depth);
+    /* No PCI init: the BIOS will do it */
+
+    /* Special port to get debug messages from Open-Firmware */
+    register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
+}
+
+QEMUMachine heathrow_machine = {
+    "g3bw",
+    "Heathrow based PowerMAC",
+    ppc_heathrow_init,
+};

Modified: trunk/src/host/qemu-neo1973/hw/ppc_prep.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc_prep.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/ppc_prep.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -26,6 +26,9 @@
 //#define HARD_DEBUG_PPC_IO
 //#define DEBUG_PPC_IO
 
+/* SMP is not enabled, for now */
+#define MAX_CPUS 1
+
 #define BIOS_FILENAME "ppc_rom.bin"
 #define KERNEL_LOAD_ADDR 0x01000000
 #define INITRD_LOAD_ADDR 0x01800000
@@ -104,7 +107,7 @@
     //    printf("%s: 0x%08x => 0x%08x\n", __func__, addr, value);
 }
 
-static inline uint32_t _PPC_intack_read (target_phys_addr_t addr)
+static always_inline uint32_t _PPC_intack_read (target_phys_addr_t addr)
 {
     uint32_t retval = 0;
 
@@ -249,6 +252,7 @@
 
 /* Fake super-io ports for PREP platform (Intel 82378ZB) */
 typedef struct sysctrl_t {
+    qemu_irq reset_irq;
     m48t59_t *nvram;
     uint8_t state;
     uint8_t syscontrol;
@@ -290,7 +294,9 @@
         /* Special port 92 */
         /* Check soft reset asked */
         if (val & 0x01) {
-            //            cpu_interrupt(first_cpu, PPC_INTERRUPT_RESET);
+            qemu_irq_raise(sysctrl->reset_irq);
+        } else {
+            qemu_irq_lower(sysctrl->reset_irq);
         }
         /* Check LE mode */
         if (val & 0x02) {
@@ -409,8 +415,9 @@
     return retval;
 }
 
-static inline target_phys_addr_t prep_IO_address (sysctrl_t *sysctrl,
-                                                  target_phys_addr_t addr)
+static always_inline target_phys_addr_t prep_IO_address (sysctrl_t *sysctrl,
+                                                         target_phys_addr_t
+                                                         addr)
 {
     if (sysctrl->contiguous_map == 0) {
         /* 64 KB contiguous space for IOs */
@@ -521,9 +528,10 @@
                            const char *initrd_filename,
                            const char *cpu_model)
 {
-    CPUState *env;
+    CPUState *env, *envs[MAX_CPUS];
     char buf[1024];
-    m48t59_t *nvram;
+    nvram_t nvram;
+    m48t59_t *m48t59;
     int PPC_io_memory;
     int linux_boot, i, nb_nics1, bios_size;
     unsigned long bios_offset;
@@ -539,33 +547,39 @@
     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);
-
-    /* Default CPU is a 604 */
     if (cpu_model == NULL)
-        cpu_model = "604";
+        cpu_model = "default";
     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);
-    /* Set time-base frequency to 100 Mhz */
-    cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+    for (i = 0; i < smp_cpus; i++) {
+        cpu_ppc_register(env, def);
+        cpu_ppc_reset(env);
+        /* Set time-base frequency to 100 Mhz */
+        cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+        qemu_register_reset(&cpu_ppc_reset, env);
+        register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+        envs[i] = env;
+    }
 
     /* allocate RAM */
     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
 
     /* allocate and load BIOS */
     bios_offset = ram_size + vga_ram_size;
-    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
     bios_size = load_image(buf, phys_ram_base + bios_offset);
     if (bios_size < 0 || bios_size > BIOS_SIZE) {
         cpu_abort(env, "qemu: could not load PPC PREP bios '%s'\n", buf);
         exit(1);
     }
+    if (env->nip < 0xFFF80000 && bios_size < 0x00100000) {
+        cpu_abort(env, "PowerPC 601 / 620 / 970 need a 1MB BIOS\n");
+    }
     bios_size = (bios_size + 0xfff) & ~0xfff;
     cpu_register_physical_memory((uint32_t)(-bios_size),
                                  bios_size, bios_offset | IO_MEM_ROM);
@@ -626,16 +640,11 @@
     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) {
+        if (nd_table[i].model == NULL
+            || strcmp(nd_table[i].model, "ne2k_isa") == 0) {
             isa_ne2000_init(ne2000_io[i], i8259[ne2000_irq[i]], &nd_table[i]);
-        } else if (strcmp(nd_table[0].model, "?") == 0) {
-            fprintf(stderr, "qemu: Supported NICs: ne2k_isa\n");
-            exit (1);
         } else {
-            /* Why ? */
-            cpu_abort(env, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
-            exit (1);
+            pci_nic_init(pci_bus, &nd_table[i], -1);
         }
     }
 
@@ -654,6 +663,7 @@
     register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
     register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
     /* Register fake IO ports for PREP */
+    sysctrl->reset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
     register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
     register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl);
     /* System control ports */
@@ -676,13 +686,16 @@
         usb_ohci_init_pci(pci_bus, 3, -1);
     }
 
-    nvram = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
-    if (nvram == NULL)
+    m48t59 = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
+    if (m48t59 == NULL)
         return;
-    sysctrl->nvram = nvram;
+    sysctrl->nvram = m48t59;
 
     /* Initialise NVRAM */
-    PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
+    nvram.opaque = m48t59;
+    nvram.read_fn = &m48t59_read;
+    nvram.write_fn = &m48t59_write;
+    PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
                          kernel_base, kernel_size,
                          kernel_cmdline,
                          initrd_base, initrd_size,

Modified: trunk/src/host/qemu-neo1973/hw/prep_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/prep_pci.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/prep_pci.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -117,7 +117,6 @@
     &PPC_PCIIO_readl,
 };
 
-/* Don't know if this matches real hardware, but it agrees with OHW.  */
 static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
 {
     return (irq_num + (pci_dev->devfn >> 3)) & 1;
@@ -125,7 +124,7 @@
 
 static void prep_set_irq(qemu_irq *pic, int irq_num, int level)
 {
-    qemu_set_irq(pic[irq_num ? 11 : 9], level);
+    qemu_set_irq(pic[(irq_num & 1) ? 11 : 9] , level);
 }
 
 PCIBus *pci_prep_init(qemu_irq *pic)
@@ -135,7 +134,7 @@
     int PPC_io_memory;
 
     s = qemu_mallocz(sizeof(PREPPCIState));
-    s->bus = pci_register_bus(prep_set_irq, prep_map_irq, pic, 0, 2);
+    s->bus = pci_register_bus(prep_set_irq, prep_map_irq, pic, 0, 4);
 
     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/pxa.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/pxa.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -4,7 +4,7 @@
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licenced under the GPL.
+ * This code is licenced under the GNU GPL v2.
  */
 #ifndef PXA_H
 # define PXA_H			"pxa.h"

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -24,6 +24,7 @@
     uint32_t rising[PXA2XX_GPIO_BANKS];
     uint32_t falling[PXA2XX_GPIO_BANKS];
     uint32_t status[PXA2XX_GPIO_BANKS];
+    uint32_t gpsr[PXA2XX_GPIO_BANKS];
     uint32_t gafr[PXA2XX_GPIO_BANKS * 2];
 
     uint32_t prev_level[PXA2XX_GPIO_BANKS];
@@ -152,6 +153,11 @@
     case GPDR:		/* GPIO Pin-Direction registers */
         return s->dir[bank];
 
+    case GPSR:		/* GPIO Pin-Output Set registers */
+        printf("%s: Read from a write-only register " REG_FMT "\n",
+                        __FUNCTION__, offset);
+        return s->gpsr[bank];	/* Return last written value.  */
+
     case GRER:		/* GPIO Rising-Edge Detect Enable registers */
         return s->rising[bank];
 
@@ -201,6 +207,7 @@
     case GPSR:		/* GPIO Pin-Output Set registers */
         s->olevel[bank] |= value;
         pxa2xx_gpio_handler_update(s);
+        s->gpsr[bank] = value;
         break;
 
     case GPCR:		/* GPIO Pin-Output Clear registers */

Added: trunk/src/host/qemu-neo1973/hw/r2d.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/r2d.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/r2d.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,63 @@
+/*
+ * Renesas SH7751R R2D-PLUS emulation
+ *
+ * Copyright (c) 2007 Magnus Damm
+ *
+ * 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 SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
+#define SDRAM_SIZE 0x04000000
+
+void r2d_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;
+    struct SH7750State *s;
+
+    env = cpu_init();
+
+    /* Allocate memory space */
+    cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, 0);
+    /* Register peripherals */
+    s = sh7750_init(env);
+    /* Todo: register on board registers */
+    {
+      int kernel_size;
+
+      kernel_size = load_image(kernel_filename, phys_ram_base);
+
+      if (kernel_size < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
+        exit(1);
+      }
+
+      env->pc = SDRAM_BASE | 0xa0000000; /* Start from P2 area */
+    }
+}
+
+QEMUMachine r2d_machine = {
+    "r2d",
+    "r2d-plus board",
+    r2d_init
+};

Modified: trunk/src/host/qemu-neo1973/hw/sh7750.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh7750.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh7750.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,6 +1,7 @@
 /*
  * SH7750 device
  *
+ * Copyright (c) 2007 Magnus Damm
  * Copyright (c) 2005 Samuel Tardieu
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -26,14 +27,8 @@
 #include "vl.h"
 #include "sh7750_regs.h"
 #include "sh7750_regnames.h"
+#include "sh_intc.h"
 
-typedef struct {
-    uint8_t data[16];
-    uint8_t length;		/* Number of characters in the FIFO */
-    uint8_t write_idx;		/* Index of first character to write */
-    uint8_t read_idx;		/* Index of first character to read */
-} fifo;
-
 #define NB_DEVICES 4
 
 typedef struct SH7750State {
@@ -43,34 +38,6 @@
     uint32_t periph_freq;
     /* SDRAM controller */
     uint16_t rfcr;
-    /* First serial port */
-    CharDriverState *serial1;
-    uint8_t scscr1;
-    uint8_t scsmr1;
-    uint8_t scbrr1;
-    uint8_t scssr1;
-    uint8_t scssr1_read;
-    uint8_t sctsr1;
-    uint8_t sctsr1_loaded;
-    uint8_t sctdr1;
-    uint8_t scrdr1;
-    /* Second serial port */
-    CharDriverState *serial2;
-    uint16_t sclsr2;
-    uint16_t scscr2;
-    uint16_t scfcr2;
-    uint16_t scfsr2;
-    uint16_t scsmr2;
-    uint8_t scbrr2;
-    fifo serial2_receive_fifo;
-    fifo serial2_transmit_fifo;
-    /* Timers */
-    uint8_t tstr;
-    /* Timer 0 */
-    QEMUTimer *timer0;
-    uint16_t tcr0;
-    uint32_t tcor0;
-    uint32_t tcnt0;
     /* IO ports */
     uint16_t gpioic;
     uint32_t pctra;
@@ -86,345 +53,16 @@
     uint16_t periph_pdtrb;	/* Imposed by the peripherals */
     uint16_t periph_portdirb;	/* Direction seen from the peripherals */
     sh7750_io_device *devices[NB_DEVICES];	/* External peripherals */
+
+    uint16_t icr;
     /* Cache */
     uint32_t ccr;
+
+    struct intc_desc intc;
 } SH7750State;
 
-/**********************************************************************
- Timers
-**********************************************************************/
 
-/* XXXXX At this time, timer0 works in underflow only mode, that is
-   the value of tcnt0 is read at alarm computation time and cannot
-   be read back by the guest OS */
-
-static void start_timer0(SH7750State * s)
-{
-    uint64_t now, next, prescaler;
-
-    if ((s->tcr0 & 6) == 6) {
-	fprintf(stderr, "rtc clock for timer 0 not supported\n");
-	assert(0);
-    }
-
-    if ((s->tcr0 & 7) == 5) {
-	fprintf(stderr, "timer 0 configuration not supported\n");
-	assert(0);
-    }
-
-    if ((s->tcr0 & 4) == 4)
-	prescaler = 1024;
-    else
-	prescaler = 4 << (s->tcr0 & 3);
-
-    now = qemu_get_clock(vm_clock);
-    /* XXXXX */
-    next =
-	now + muldiv64(prescaler * s->tcnt0, ticks_per_sec,
-		       s->periph_freq);
-    if (next == now)
-	next = now + 1;
-    fprintf(stderr, "now=%016" PRIx64 ", next=%016" PRIx64 "\n", now, next);
-    fprintf(stderr, "timer will underflow in %f seconds\n",
-	    (float) (next - now) / (float) ticks_per_sec);
-
-    qemu_mod_timer(s->timer0, next);
-}
-
-static void timer_start_changed(SH7750State * s)
-{
-    if (s->tstr & SH7750_TSTR_STR0) {
-	start_timer0(s);
-    } else {
-	fprintf(stderr, "timer 0 is stopped\n");
-	qemu_del_timer(s->timer0);
-    }
-}
-
-static void timer0_cb(void *opaque)
-{
-    SH7750State *s = opaque;
-
-    s->tcnt0 = (uint32_t) 0;	/* XXXXX */
-    if (--s->tcnt0 == (uint32_t) - 1) {
-	fprintf(stderr, "timer 0 underflow\n");
-	s->tcnt0 = s->tcor0;
-	s->tcr0 |= SH7750_TCR_UNF;
-	if (s->tcr0 & SH7750_TCR_UNIE) {
-	    fprintf(stderr,
-		    "interrupt generation for timer 0 not supported\n");
-	    assert(0);
-	}
-    }
-    start_timer0(s);
-}
-
-static void init_timers(SH7750State * s)
-{
-    s->tcor0 = 0xffffffff;
-    s->tcnt0 = 0xffffffff;
-    s->timer0 = qemu_new_timer(vm_clock, &timer0_cb, s);
-}
-
 /**********************************************************************
- First serial port
-**********************************************************************/
-
-static int serial1_can_receive(void *opaque)
-{
-    SH7750State *s = opaque;
-
-    return s->scscr1 & SH7750_SCSCR_RE;
-}
-
-static void serial1_receive_char(SH7750State * s, uint8_t c)
-{
-    if (s->scssr1 & SH7750_SCSSR1_RDRF) {
-	s->scssr1 |= SH7750_SCSSR1_ORER;
-	return;
-    }
-
-    s->scrdr1 = c;
-    s->scssr1 |= SH7750_SCSSR1_RDRF;
-}
-
-static void serial1_receive(void *opaque, const uint8_t * buf, int size)
-{
-    SH7750State *s = opaque;
-    int i;
-
-    for (i = 0; i < size; i++) {
-	serial1_receive_char(s, buf[i]);
-    }
-}
-
-static void serial1_event(void *opaque, int event)
-{
-    assert(0);
-}
-
-static void serial1_maybe_send(SH7750State * s)
-{
-    uint8_t c;
-
-    if (s->scssr1 & SH7750_SCSSR1_TDRE)
-	return;
-    c = s->sctdr1;
-    s->scssr1 |= SH7750_SCSSR1_TDRE | SH7750_SCSSR1_TEND;
-    if (s->scscr1 & SH7750_SCSCR_TIE) {
-	fprintf(stderr, "interrupts for serial port 1 not implemented\n");
-	assert(0);
-    }
-    /* XXXXX Check for errors in write */
-    qemu_chr_write(s->serial1, &c, 1);
-}
-
-static void serial1_change_scssr1(SH7750State * s, uint8_t mem_value)
-{
-    uint8_t new_flags;
-
-    /* If transmit disable, TDRE and TEND stays up */
-    if ((s->scscr1 & SH7750_SCSCR_TE) == 0) {
-	mem_value |= SH7750_SCSSR1_TDRE | SH7750_SCSSR1_TEND;
-    }
-
-    /* Only clear bits which have been read before and do not set any bit
-       in the flags */
-    new_flags = s->scssr1 & ~s->scssr1_read;	/* Preserve unread flags */
-    new_flags &= mem_value | ~s->scssr1_read;	/* Clear read flags */
-
-    s->scssr1 = (new_flags & 0xf8) | (mem_value & 1);
-    s->scssr1_read &= mem_value;
-
-    /* If TDRE has been cleared, TEND will also be cleared */
-    if ((s->scssr1 & SH7750_SCSSR1_TDRE) == 0) {
-	s->scssr1 &= ~SH7750_SCSSR1_TEND;
-    }
-
-    /* Check for transmission to start */
-    serial1_maybe_send(s);
-}
-
-static void serial1_update_parameters(SH7750State * s)
-{
-    QEMUSerialSetParams ssp;
-
-    if (s->scsmr1 & SH7750_SCSMR_CHR_7)
-	ssp.data_bits = 7;
-    else
-	ssp.data_bits = 8;
-    if (s->scsmr1 & SH7750_SCSMR_PE) {
-	if (s->scsmr1 & SH7750_SCSMR_PM_ODD)
-	    ssp.parity = 'O';
-	else
-	    ssp.parity = 'E';
-    } else
-	ssp.parity = 'N';
-    if (s->scsmr1 & SH7750_SCSMR_STOP_2)
-	ssp.stop_bits = 2;
-    else
-	ssp.stop_bits = 1;
-    fprintf(stderr, "SCSMR1=%04x SCBRR1=%02x\n", s->scsmr1, s->scbrr1);
-    ssp.speed = s->periph_freq /
-	(32 * s->scbrr1 * (1 << (2 * (s->scsmr1 & 3)))) - 1;
-    fprintf(stderr, "data bits=%d, stop bits=%d, parity=%c, speed=%d\n",
-	    ssp.data_bits, ssp.stop_bits, ssp.parity, ssp.speed);
-    qemu_chr_ioctl(s->serial1, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
-}
-
-static void scscr1_changed(SH7750State * s)
-{
-    if (s->scscr1 & (SH7750_SCSCR_TE | SH7750_SCSCR_RE)) {
-	if (!s->serial1) {
-	    fprintf(stderr, "serial port 1 not bound to anything\n");
-	    assert(0);
-	}
-	serial1_update_parameters(s);
-    }
-    if ((s->scscr1 & SH7750_SCSCR_RE) == 0) {
-	s->scssr1 |= SH7750_SCSSR1_TDRE;
-    }
-}
-
-static void init_serial1(SH7750State * s, int serial_nb)
-{
-    CharDriverState *chr;
-
-    s->scssr1 = 0x84;
-    chr = serial_hds[serial_nb];
-    if (!chr) {
-	fprintf(stderr,
-		"no serial port associated to SH7750 first serial port\n");
-	return;
-    }
-
-    s->serial1 = chr;
-    qemu_chr_add_handlers(chr, serial1_can_receive,
-			  serial1_receive, serial1_event, s);
-}
-
-/**********************************************************************
- Second serial port
-**********************************************************************/
-
-static int serial2_can_receive(void *opaque)
-{
-    SH7750State *s = opaque;
-    static uint8_t max_fifo_size[] = { 15, 1, 4, 6, 8, 10, 12, 14 };
-
-    return s->serial2_receive_fifo.length <
-	max_fifo_size[(s->scfcr2 >> 9) & 7];
-}
-
-static void serial2_adjust_receive_flags(SH7750State * s)
-{
-    static uint8_t max_fifo_size[] = { 1, 4, 8, 14 };
-
-    /* XXXXX Add interrupt generation */
-    if (s->serial2_receive_fifo.length >=
-	max_fifo_size[(s->scfcr2 >> 7) & 3]) {
-	s->scfsr2 |= SH7750_SCFSR2_RDF;
-	s->scfsr2 &= ~SH7750_SCFSR2_DR;
-    } else {
-	s->scfsr2 &= ~SH7750_SCFSR2_RDF;
-	if (s->serial2_receive_fifo.length > 0)
-	    s->scfsr2 |= SH7750_SCFSR2_DR;
-	else
-	    s->scfsr2 &= ~SH7750_SCFSR2_DR;
-    }
-}
-
-static void serial2_append_char(SH7750State * s, uint8_t c)
-{
-    if (s->serial2_receive_fifo.length == 16) {
-	/* Overflow */
-	s->sclsr2 |= SH7750_SCLSR2_ORER;
-	return;
-    }
-
-    s->serial2_receive_fifo.data[s->serial2_receive_fifo.write_idx++] = c;
-    s->serial2_receive_fifo.length++;
-    serial2_adjust_receive_flags(s);
-}
-
-static void serial2_receive(void *opaque, const uint8_t * buf, int size)
-{
-    SH7750State *s = opaque;
-    int i;
-
-    for (i = 0; i < size; i++)
-	serial2_append_char(s, buf[i]);
-}
-
-static void serial2_event(void *opaque, int event)
-{
-    /* XXXXX */
-    assert(0);
-}
-
-static void serial2_update_parameters(SH7750State * s)
-{
-    QEMUSerialSetParams ssp;
-
-    if (s->scsmr2 & SH7750_SCSMR_CHR_7)
-	ssp.data_bits = 7;
-    else
-	ssp.data_bits = 8;
-    if (s->scsmr2 & SH7750_SCSMR_PE) {
-	if (s->scsmr2 & SH7750_SCSMR_PM_ODD)
-	    ssp.parity = 'O';
-	else
-	    ssp.parity = 'E';
-    } else
-	ssp.parity = 'N';
-    if (s->scsmr2 & SH7750_SCSMR_STOP_2)
-	ssp.stop_bits = 2;
-    else
-	ssp.stop_bits = 1;
-    fprintf(stderr, "SCSMR2=%04x SCBRR2=%02x\n", s->scsmr2, s->scbrr2);
-    ssp.speed = s->periph_freq /
-	(32 * s->scbrr2 * (1 << (2 * (s->scsmr2 & 3)))) - 1;
-    fprintf(stderr, "data bits=%d, stop bits=%d, parity=%c, speed=%d\n",
-	    ssp.data_bits, ssp.stop_bits, ssp.parity, ssp.speed);
-    qemu_chr_ioctl(s->serial2, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
-}
-
-static void scscr2_changed(SH7750State * s)
-{
-    if (s->scscr2 & (SH7750_SCSCR_TE | SH7750_SCSCR_RE)) {
-	if (!s->serial2) {
-	    fprintf(stderr, "serial port 2 not bound to anything\n");
-	    assert(0);
-	}
-	serial2_update_parameters(s);
-    }
-}
-
-static void init_serial2(SH7750State * s, int serial_nb)
-{
-    CharDriverState *chr;
-
-    s->scfsr2 = 0x0060;
-
-    chr = serial_hds[serial_nb];
-    if (!chr) {
-	fprintf(stderr,
-		"no serial port associated to SH7750 second serial port\n");
-	return;
-    }
-
-    s->serial2 = chr;
-    qemu_chr_add_handlers(chr, serial2_can_receive,
-			  serial2_receive, serial1_event, s);
-}
-
-static void init_serial_ports(SH7750State * s)
-{
-    init_serial1(s, 0);
-    init_serial2(s, 1);
-}
-
-/**********************************************************************
  I/O ports
 **********************************************************************/
 
@@ -554,17 +192,7 @@
 
 static uint32_t sh7750_mem_readb(void *opaque, target_phys_addr_t addr)
 {
-    SH7750State *s = opaque;
-    uint8_t r;
-
     switch (addr) {
-    case SH7750_SCSSR1_A7:
-	r = s->scssr1;
-	s->scssr1_read |= r;
-	return s->scssr1;
-    case SH7750_SCRDR1_A7:
-	s->scssr1 &= ~SH7750_SCSSR1_RDRF;
-	return s->scrdr1;
     default:
 	error_access("byte read", addr);
 	assert(0);
@@ -574,26 +202,20 @@
 static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr)
 {
     SH7750State *s = opaque;
-    uint16_t r;
 
     switch (addr) {
+    case SH7750_FRQCR_A7:
+	return 0;
     case SH7750_RFCR_A7:
 	fprintf(stderr,
 		"Read access to refresh count register, incrementing\n");
 	return s->rfcr++;
-    case SH7750_TCR0_A7:
-	return s->tcr0;
-    case SH7750_SCLSR2_A7:
-	/* Read and clear overflow bit */
-	r = s->sclsr2;
-	s->sclsr2 = 0;
-	return r;
-    case SH7750_SCSFR2_A7:
-	return s->scfsr2;
     case SH7750_PDTRA_A7:
 	return porta_lines(s);
     case SH7750_PDTRB_A7:
 	return portb_lines(s);
+    case 0x1fd00000:
+        return s->icr;
     default:
 	error_access("word read", addr);
 	assert(0);
@@ -638,38 +260,12 @@
 static void sh7750_mem_writeb(void *opaque, target_phys_addr_t addr,
 			      uint32_t mem_value)
 {
-    SH7750State *s = opaque;
-
     switch (addr) {
 	/* PRECHARGE ? XXXXX */
     case SH7750_PRECHARGE0_A7:
     case SH7750_PRECHARGE1_A7:
 	ignore_access("byte write", addr);
 	return;
-    case SH7750_SCBRR2_A7:
-	s->scbrr2 = mem_value;
-	return;
-    case SH7750_TSTR_A7:
-	s->tstr = mem_value;
-	timer_start_changed(s);
-	return;
-    case SH7750_SCSCR1_A7:
-	s->scscr1 = mem_value;
-	scscr1_changed(s);
-	return;
-    case SH7750_SCSMR1_A7:
-	s->scsmr1 = mem_value;
-	return;
-    case SH7750_SCBRR1_A7:
-	s->scbrr1 = mem_value;
-	return;
-    case SH7750_SCTDR1_A7:
-	s->scssr1 &= ~SH7750_SCSSR1_TEND;
-	s->sctdr1 = mem_value;
-	return;
-    case SH7750_SCSSR1_A7:
-	serial1_change_scssr1(s, mem_value);
-	return;
     default:
 	error_access("byte write", addr);
 	assert(0);
@@ -684,8 +280,6 @@
 
     switch (addr) {
 	/* SDRAM controller */
-    case SH7750_SCBRR1_A7:
-    case SH7750_SCBRR2_A7:
     case SH7750_BCR2_A7:
     case SH7750_BCR3_A7:
     case SH7750_RTCOR_A7:
@@ -708,22 +302,6 @@
 	fprintf(stderr, "Write access to refresh count register\n");
 	s->rfcr = mem_value;
 	return;
-    case SH7750_SCLSR2_A7:
-	s->sclsr2 = mem_value;
-	return;
-    case SH7750_SCSCR2_A7:
-	s->scscr2 = mem_value;
-	scscr2_changed(s);
-	return;
-    case SH7750_SCFCR2_A7:
-	s->scfcr2 = mem_value;
-	return;
-    case SH7750_SCSMR2_A7:
-	s->scsmr2 = mem_value;
-	return;
-    case SH7750_TCR0_A7:
-	s->tcr0 = mem_value;
-	return;
     case SH7750_GPIOIC_A7:
 	s->gpioic = mem_value;
 	if (mem_value != 0) {
@@ -731,6 +309,9 @@
 	    assert(0);
 	}
 	return;
+    case 0x1fd00000:
+        s->icr = mem_value;
+	return;
     default:
 	error_access("word write", addr);
 	assert(0);
@@ -768,9 +349,6 @@
 	s->portpullupb = portpullup(mem_value);
 	portb_changed(s, temp);
 	return;
-    case SH7750_TCNT0_A7:
-	s->tcnt0 = mem_value & 0xf;
-	return;
     case SH7750_MMUCR_A7:
 	s->cpu->mmucr = mem_value;
 	return;
@@ -816,10 +394,144 @@
     sh7750_mem_writel
 };
 
+/* sh775x interrupt controller tables for sh_intc.c
+ * stolen from linux/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+ */
+
+enum {
+	UNUSED = 0,
+
+	/* interrupt sources */
+	IRL0, IRL1, IRL2, IRL3, /* only IRLM mode supported */
+	HUDI, GPIOI,
+	DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
+	DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
+	DMAC_DMAE,
+	PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+	PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
+	TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
+	RTC_ATI, RTC_PRI, RTC_CUI,
+	SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
+	SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
+	WDT,
+	REF_RCMI, REF_ROVI,
+
+	/* interrupt groups */
+	DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
+
+	NR_SOURCES,
+};
+
+static struct intc_vect vectors[] = {
+	INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
+	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
+	INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
+	INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
+	INTC_VECT(RTC_CUI, 0x4c0),
+	INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
+	INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
+	INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
+	INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
+	INTC_VECT(WDT, 0x560),
+	INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
+};
+
+static struct intc_group groups[] = {
+	INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
+	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
+	INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
+	INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
+	INTC_GROUP(REF, REF_RCMI, REF_ROVI),
+};
+
+static struct intc_prio_reg prio_registers[] = {
+	{ 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
+	{ 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
+	{ 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
+	{ 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
+	{ 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0,
+						 TMU4, TMU3,
+						 PCIC1, PCIC0_PCISERR } },
+};
+
+/* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
+
+static struct intc_vect vectors_dma4[] = {
+	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
+	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
+	INTC_VECT(DMAC_DMAE, 0x6c0),
+};
+
+static struct intc_group groups_dma4[] = {
+	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
+		   DMAC_DMTE3, DMAC_DMAE),
+};
+
+/* SH7750R and SH7751R both have 8-channel DMA controllers */
+
+static struct intc_vect vectors_dma8[] = {
+	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
+	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
+	INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
+	INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
+	INTC_VECT(DMAC_DMAE, 0x6c0),
+};
+
+static struct intc_group groups_dma8[] = {
+	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
+		   DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
+		   DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
+};
+
+/* SH7750R, SH7751 and SH7751R all have two extra timer channels */
+
+static struct intc_vect vectors_tmu34[] = {
+	INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80),
+};
+
+static struct intc_mask_reg mask_registers[] = {
+	{ 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */
+	  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, TMU4, TMU3,
+	    PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+	    PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2,
+	    PCIC1_PCIDMA3, PCIC0_PCISERR } },
+};
+
+/* SH7750S, SH7750R, SH7751 and SH7751R all have IRLM priority registers */
+
+static struct intc_vect vectors_irlm[] = {
+	INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
+	INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
+};
+
+/* SH7751 and SH7751R both have PCI */
+
+static struct intc_vect vectors_pci[] = {
+	INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0),
+	INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0),
+	INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60),
+	INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20),
+};
+
+static struct intc_group groups_pci[] = {
+	INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+		   PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
+};
+
+#define SH_CPU_SH7750  (1 << 0)
+#define SH_CPU_SH7750S (1 << 1)
+#define SH_CPU_SH7750R (1 << 2)
+#define SH_CPU_SH7751  (1 << 3)
+#define SH_CPU_SH7751R (1 << 4)
+#define SH_CPU_SH7750_ALL (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7750R)
+#define SH_CPU_SH7751_ALL (SH_CPU_SH7751 | SH_CPU_SH7751R)
+
 SH7750State *sh7750_init(CPUSH4State * cpu)
 {
     SH7750State *s;
     int sh7750_io_memory;
+    int cpu_model = SH_CPU_SH7751R; /* for now */
 
     s = qemu_mallocz(sizeof(SH7750State));
     s->cpu = cpu;
@@ -828,7 +540,54 @@
 					      sh7750_mem_read,
 					      sh7750_mem_write, s);
     cpu_register_physical_memory(0x1c000000, 0x04000000, sh7750_io_memory);
-    init_timers(s);
-    init_serial_ports(s);
+
+    sh_intc_init(&s->intc, NR_SOURCES,
+		 _INTC_ARRAY(mask_registers),
+		 _INTC_ARRAY(prio_registers));
+
+    sh_intc_register_sources(&s->intc, 
+			     _INTC_ARRAY(vectors),
+			     _INTC_ARRAY(groups));
+
+    sh_serial_init(0x1fe00000, 0, s->periph_freq, serial_hds[0]);
+    sh_serial_init(0x1fe80000, SH_SERIAL_FEAT_SCIF,
+		   s->periph_freq, serial_hds[1]);
+
+    tmu012_init(0x1fd80000,
+		TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
+		s->periph_freq);
+
+
+    if (cpu_model & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
+        sh_intc_register_sources(&s->intc, 
+				 _INTC_ARRAY(vectors_dma4),
+				 _INTC_ARRAY(groups_dma4));
+    }
+
+    if (cpu_model & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
+        sh_intc_register_sources(&s->intc, 
+				 _INTC_ARRAY(vectors_dma8),
+				 _INTC_ARRAY(groups_dma8));
+    }
+
+    if (cpu_model & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) {
+        sh_intc_register_sources(&s->intc, 
+				 _INTC_ARRAY(vectors_tmu34),
+				 _INTC_ARRAY(NULL));
+        tmu012_init(0x1e100000, 0, s->periph_freq);
+    }
+
+    if (cpu_model & (SH_CPU_SH7751_ALL)) {
+        sh_intc_register_sources(&s->intc, 
+				 _INTC_ARRAY(vectors_pci),
+				 _INTC_ARRAY(groups_pci));
+    }
+
+    if (cpu_model & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) {
+        sh_intc_register_sources(&s->intc, 
+				 _INTC_ARRAY(vectors_irlm),
+				 _INTC_ARRAY(NULL));
+    }
+
     return s;
 }

Modified: trunk/src/host/qemu-neo1973/hw/sh7750_regnames.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh7750_regnames.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh7750_regnames.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -42,18 +42,6 @@
 	REGNAME(SH7750_RMONAR_A7)
 	REGNAME(SH7750_RCR1_A7)
 	REGNAME(SH7750_RCR2_A7)
-	REGNAME(SH7750_TOCR_A7)
-	REGNAME(SH7750_TSTR_A7)
-	REGNAME(SH7750_TCOR0_A7)
-	REGNAME(SH7750_TCOR1_A7)
-	REGNAME(SH7750_TCOR2_A7)
-	REGNAME(SH7750_TCNT0_A7)
-	REGNAME(SH7750_TCNT1_A7)
-	REGNAME(SH7750_TCNT2_A7)
-	REGNAME(SH7750_TCR0_A7)
-	REGNAME(SH7750_TCR1_A7)
-	REGNAME(SH7750_TCR2_A7)
-	REGNAME(SH7750_TCPR2_A7)
 	REGNAME(SH7750_BCR1_A7)
 	REGNAME(SH7750_BCR2_A7)
 	REGNAME(SH7750_WCR1_A7)
@@ -82,33 +70,12 @@
 	REGNAME(SH7750_CHCR2_A7)
 	REGNAME(SH7750_CHCR3_A7)
 	REGNAME(SH7750_DMAOR_A7)
-	REGNAME(SH7750_SCRDR1_A7)
-	REGNAME(SH7750_SCRDR2_A7)
-	REGNAME(SH7750_SCTDR1_A7)
-	REGNAME(SH7750_SCTDR2_A7)
-	REGNAME(SH7750_SCSMR1_A7)
-	REGNAME(SH7750_SCSMR2_A7)
-	REGNAME(SH7750_SCSCR1_A7)
-	REGNAME(SH7750_SCSCR2_A7)
-	REGNAME(SH7750_SCSSR1_A7)
-	REGNAME(SH7750_SCSFR2_A7)
-	REGNAME(SH7750_SCSPTR1_A7)
-	REGNAME(SH7750_SCSPTR2_A7)
-	REGNAME(SH7750_SCBRR1_A7)
-	REGNAME(SH7750_SCBRR2_A7)
-	REGNAME(SH7750_SCFCR2_A7)
-	REGNAME(SH7750_SCFDR2_A7)
-	REGNAME(SH7750_SCLSR2_A7)
-	REGNAME(SH7750_SCSCMR1_A7)
 	REGNAME(SH7750_PCTRA_A7)
 	REGNAME(SH7750_PDTRA_A7)
 	REGNAME(SH7750_PCTRB_A7)
 	REGNAME(SH7750_PDTRB_A7)
 	REGNAME(SH7750_GPIOIC_A7)
 	REGNAME(SH7750_ICR_A7)
-	REGNAME(SH7750_IPRA_A7)
-	REGNAME(SH7750_IPRB_A7)
-	REGNAME(SH7750_IPRC_A7)
 	REGNAME(SH7750_BCR3_A7)
 	REGNAME(SH7750_BCR4_A7)
 	REGNAME(SH7750_PRECHARGE0_A7)

Modified: trunk/src/host/qemu-neo1973/hw/sh7750_regs.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh7750_regs.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh7750_regs.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -524,95 +524,7 @@
 					   year counters are stopped
 					   1 - sec, min, hr, day-of-week, month,
 					   year counters operate normally */
-
-
 /*
- * Timer Unit (TMU)
- */
-/* Timer Output Control Register (byte) - TOCR */
-#define SH7750_TOCR_REGOFS    0xD80000	/* offset */
-#define SH7750_TOCR           SH7750_P4_REG32(SH7750_TOCR_REGOFS)
-#define SH7750_TOCR_A7        SH7750_A7_REG32(SH7750_TOCR_REGOFS)
-#define SH7750_TOCR_TCOE      0x01	/* Timer Clock Pin Control:
-					   0 - TCLK is used as external clock
-					   input or input capture control
-					   1 - TCLK is used as on-chip RTC
-					   output clock pin */
-
-/* Timer Start Register (byte) - TSTR */
-#define SH7750_TSTR_REGOFS    0xD80004	/* offset */
-#define SH7750_TSTR           SH7750_P4_REG32(SH7750_TSTR_REGOFS)
-#define SH7750_TSTR_A7        SH7750_A7_REG32(SH7750_TSTR_REGOFS)
-#define SH7750_TSTR_STR2      0x04	/* TCNT2 performs count operations */
-#define SH7750_TSTR_STR1      0x02	/* TCNT1 performs count operations */
-#define SH7750_TSTR_STR0      0x01	/* TCNT0 performs count operations */
-#define SH7750_TSTR_STR(n)    (1 << (n))
-
-/* Timer Constant Register - TCOR0, TCOR1, TCOR2 */
-#define SH7750_TCOR_REGOFS(n) (0xD80008 + ((n)*12))	/* offset */
-#define SH7750_TCOR(n)        SH7750_P4_REG32(SH7750_TCOR_REGOFS(n))
-#define SH7750_TCOR_A7(n)     SH7750_A7_REG32(SH7750_TCOR_REGOFS(n))
-#define SH7750_TCOR0          SH7750_TCOR(0)
-#define SH7750_TCOR1          SH7750_TCOR(1)
-#define SH7750_TCOR2          SH7750_TCOR(2)
-#define SH7750_TCOR0_A7       SH7750_TCOR_A7(0)
-#define SH7750_TCOR1_A7       SH7750_TCOR_A7(1)
-#define SH7750_TCOR2_A7       SH7750_TCOR_A7(2)
-
-/* Timer Counter Register - TCNT0, TCNT1, TCNT2 */
-#define SH7750_TCNT_REGOFS(n) (0xD8000C + ((n)*12))	/* offset */
-#define SH7750_TCNT(n)        SH7750_P4_REG32(SH7750_TCNT_REGOFS(n))
-#define SH7750_TCNT_A7(n)     SH7750_A7_REG32(SH7750_TCNT_REGOFS(n))
-#define SH7750_TCNT0          SH7750_TCNT(0)
-#define SH7750_TCNT1          SH7750_TCNT(1)
-#define SH7750_TCNT2          SH7750_TCNT(2)
-#define SH7750_TCNT0_A7       SH7750_TCNT_A7(0)
-#define SH7750_TCNT1_A7       SH7750_TCNT_A7(1)
-#define SH7750_TCNT2_A7       SH7750_TCNT_A7(2)
-
-/* Timer Control Register (half) - TCR0, TCR1, TCR2 */
-#define SH7750_TCR_REGOFS(n)  (0xD80010 + ((n)*12))	/* offset */
-#define SH7750_TCR(n)         SH7750_P4_REG32(SH7750_TCR_REGOFS(n))
-#define SH7750_TCR_A7(n)      SH7750_A7_REG32(SH7750_TCR_REGOFS(n))
-#define SH7750_TCR0           SH7750_TCR(0)
-#define SH7750_TCR1           SH7750_TCR(1)
-#define SH7750_TCR2           SH7750_TCR(2)
-#define SH7750_TCR0_A7        SH7750_TCR_A7(0)
-#define SH7750_TCR1_A7        SH7750_TCR_A7(1)
-#define SH7750_TCR2_A7        SH7750_TCR_A7(2)
-
-#define SH7750_TCR2_ICPF       0x200	/* Input Capture Interrupt Flag
-					   (1 - input capture has occured) */
-#define SH7750_TCR_UNF         0x100	/* Underflow flag */
-#define SH7750_TCR2_ICPE       0x0C0	/* Input Capture Control: */
-#define SH7750_TCR2_ICPE_DIS   0x000	/*   Input Capture function is not used */
-#define SH7750_TCR2_ICPE_NOINT 0x080	/*   Input Capture function is used, but
-					   input capture interrupt is not
-					   enabled */
-#define SH7750_TCR2_ICPE_INT   0x0C0	/*   Input Capture function is used,
-					   input capture interrupt enabled */
-#define SH7750_TCR_UNIE        0x020	/* Underflow Interrupt Control
-					   (1 - underflow interrupt enabled) */
-#define SH7750_TCR_CKEG        0x018	/* Clock Edge selection: */
-#define SH7750_TCR_CKEG_RAISE  0x000	/*   Count/capture on rising edge */
-#define SH7750_TCR_CKEG_FALL   0x008	/*   Count/capture on falling edge */
-#define SH7750_TCR_CKEG_BOTH   0x018	/*   Count/capture on both rising and
-					   falling edges */
-#define SH7750_TCR_TPSC         0x007	/* Timer prescaler */
-#define SH7750_TCR_TPSC_DIV4    0x000	/*   Counts on peripheral clock/4 */
-#define SH7750_TCR_TPSC_DIV16   0x001	/*   Counts on peripheral clock/16 */
-#define SH7750_TCR_TPSC_DIV64   0x002	/*   Counts on peripheral clock/64 */
-#define SH7750_TCR_TPSC_DIV256  0x003	/*   Counts on peripheral clock/256 */
-#define SH7750_TCR_TPSC_DIV1024 0x004	/*   Counts on peripheral clock/1024 */
-#define SH7750_TCR_TPSC_RTC     0x006	/*   Counts on on-chip RTC output clk */
-#define SH7750_TCR_TPSC_EXT     0x007	/*   Counts on external clock */
-
-/* Input Capture Register (read-only) - TCPR2 */
-#define SH7750_TCPR2_REGOFS   0xD8002C	/* offset */
-#define SH7750_TCPR2          SH7750_P4_REG32(SH7750_TCPR2_REGOFS)
-#define SH7750_TCPR2_A7       SH7750_A7_REG32(SH7750_TCPR2_REGOFS)
-
-/*
  * Bus State Controller - BSC
  */
 /* Bus Control Register 1 - BCR1 */
@@ -1257,231 +1169,6 @@
 #define SH7750_DMAOR_DME      0x00000001	/* DMAC Master Enable */
 
 /*
- * Serial Communication Interface - SCI
- * Serial Communication Interface with FIFO - SCIF
- */
-/* SCI Receive Data Register (byte, read-only) - SCRDR1, SCFRDR2 */
-#define SH7750_SCRDR_REGOFS(n) ((n) == 1 ? 0xE00014 : 0xE80014)	/* offset */
-#define SH7750_SCRDR(n)       SH7750_P4_REG32(SH7750_SCRDR_REGOFS(n))
-#define SH7750_SCRDR1         SH7750_SCRDR(1)
-#define SH7750_SCRDR2         SH7750_SCRDR(2)
-#define SH7750_SCRDR_A7(n)    SH7750_A7_REG32(SH7750_SCRDR_REGOFS(n))
-#define SH7750_SCRDR1_A7      SH7750_SCRDR_A7(1)
-#define SH7750_SCRDR2_A7      SH7750_SCRDR_A7(2)
-
-/* SCI Transmit Data Register (byte) - SCTDR1, SCFTDR2 */
-#define SH7750_SCTDR_REGOFS(n) ((n) == 1 ? 0xE0000C : 0xE8000C)	/* offset */
-#define SH7750_SCTDR(n)       SH7750_P4_REG32(SH7750_SCTDR_REGOFS(n))
-#define SH7750_SCTDR1         SH7750_SCTDR(1)
-#define SH7750_SCTDR2         SH7750_SCTDR(2)
-#define SH7750_SCTDR_A7(n)    SH7750_A7_REG32(SH7750_SCTDR_REGOFS(n))
-#define SH7750_SCTDR1_A7      SH7750_SCTDR_A7(1)
-#define SH7750_SCTDR2_A7      SH7750_SCTDR_A7(2)
-
-/* SCI Serial Mode Register - SCSMR1(byte), SCSMR2(half) */
-#define SH7750_SCSMR_REGOFS(n) ((n) == 1 ? 0xE00000 : 0xE80000)	/* offset */
-#define SH7750_SCSMR(n)       SH7750_P4_REG32(SH7750_SCSMR_REGOFS(n))
-#define SH7750_SCSMR1         SH7750_SCSMR(1)
-#define SH7750_SCSMR2         SH7750_SCSMR(2)
-#define SH7750_SCSMR_A7(n)    SH7750_A7_REG32(SH7750_SCSMR_REGOFS(n))
-#define SH7750_SCSMR1_A7      SH7750_SCSMR_A7(1)
-#define SH7750_SCSMR2_A7      SH7750_SCSMR_A7(2)
-
-#define SH7750_SCSMR1_CA       0x80	/* Communication Mode (C/A\): */
-#define SH7750_SCSMR1_CA_ASYNC 0x00	/*     Asynchronous Mode */
-#define SH7750_SCSMR1_CA_SYNC  0x80	/*     Synchronous Mode */
-#define SH7750_SCSMR_CHR       0x40	/* Character Length: */
-#define SH7750_SCSMR_CHR_8     0x00	/*     8-bit data */
-#define SH7750_SCSMR_CHR_7     0x40	/*     7-bit data */
-#define SH7750_SCSMR_PE        0x20	/* Parity Enable */
-#define SH7750_SCSMR_PM        0x10	/* Parity Mode: */
-#define SH7750_SCSMR_PM_EVEN   0x00	/*     Even Parity */
-#define SH7750_SCSMR_PM_ODD    0x10	/*     Odd Parity */
-#define SH7750_SCSMR_STOP      0x08	/* Stop Bit Length: */
-#define SH7750_SCSMR_STOP_1    0x00	/*     1 stop bit */
-#define SH7750_SCSMR_STOP_2    0x08	/*     2 stop bit */
-#define SH7750_SCSMR1_MP       0x04	/* Multiprocessor Mode */
-#define SH7750_SCSMR_CKS       0x03	/* Clock Select */
-#define SH7750_SCSMR_CKS_S     0
-#define SH7750_SCSMR_CKS_DIV1  0x00	/*     Periph clock */
-#define SH7750_SCSMR_CKS_DIV4  0x01	/*     Periph clock / 4 */
-#define SH7750_SCSMR_CKS_DIV16 0x02	/*     Periph clock / 16 */
-#define SH7750_SCSMR_CKS_DIV64 0x03	/*     Periph clock / 64 */
-
-/* SCI Serial Control Register - SCSCR1(byte), SCSCR2(half) */
-#define SH7750_SCSCR_REGOFS(n) ((n) == 1 ? 0xE00008 : 0xE80008)	/* offset */
-#define SH7750_SCSCR(n)       SH7750_P4_REG32(SH7750_SCSCR_REGOFS(n))
-#define SH7750_SCSCR1         SH7750_SCSCR(1)
-#define SH7750_SCSCR2         SH7750_SCSCR(2)
-#define SH7750_SCSCR_A7(n)    SH7750_A7_REG32(SH7750_SCSCR_REGOFS(n))
-#define SH7750_SCSCR1_A7      SH7750_SCSCR_A7(1)
-#define SH7750_SCSCR2_A7      SH7750_SCSCR_A7(2)
-
-#define SH7750_SCSCR_TIE      0x80	/* Transmit Interrupt Enable */
-#define SH7750_SCSCR_RIE      0x40	/* Receive Interrupt Enable */
-#define SH7750_SCSCR_TE       0x20	/* Transmit Enable */
-#define SH7750_SCSCR_RE       0x10	/* Receive Enable */
-#define SH7750_SCSCR1_MPIE    0x08	/* Multiprocessor Interrupt Enable */
-#define SH7750_SCSCR2_REIE    0x08	/* Receive Error Interrupt Enable */
-#define SH7750_SCSCR1_TEIE    0x04	/* Transmit End Interrupt Enable */
-#define SH7750_SCSCR1_CKE     0x03	/* Clock Enable: */
-#define SH7750_SCSCR_CKE_INTCLK            0x00	/* Use Internal Clock */
-#define SH7750_SCSCR_CKE_EXTCLK            0x02	/* Use External Clock from SCK */
-#define SH7750_SCSCR1_CKE_ASYNC_SCK_CLKOUT 0x01	/* Use SCK as a clock output
-						   in asynchronous mode */
-
-/* SCI Serial Status Register - SCSSR1(byte), SCSFR2(half) */
-#define SH7750_SCSSR_REGOFS(n) ((n) == 1 ? 0xE00010 : 0xE80010)	/* offset */
-#define SH7750_SCSSR(n)       SH7750_P4_REG32(SH7750_SCSSR_REGOFS(n))
-#define SH7750_SCSSR1         SH7750_SCSSR(1)
-#define SH7750_SCSFR2         SH7750_SCSSR(2)
-#define SH7750_SCSSR_A7(n)    SH7750_A7_REG32(SH7750_SCSSR_REGOFS(n))
-#define SH7750_SCSSR1_A7      SH7750_SCSSR_A7(1)
-#define SH7750_SCSFR2_A7      SH7750_SCSSR_A7(2)
-
-#define SH7750_SCSSR1_TDRE    0x80	/* Transmit Data Register Empty */
-#define SH7750_SCSSR1_RDRF    0x40	/* Receive Data Register Full */
-#define SH7750_SCSSR1_ORER    0x20	/* Overrun Error */
-#define SH7750_SCSSR1_FER     0x10	/* Framing Error */
-#define SH7750_SCSSR1_PER     0x08	/* Parity Error */
-#define SH7750_SCSSR1_TEND    0x04	/* Transmit End */
-#define SH7750_SCSSR1_MPB     0x02	/* Multiprocessor Bit */
-#define SH7750_SCSSR1_MPBT    0x01	/* Multiprocessor Bit Transfer */
-
-#define SH7750_SCFSR2_PERN    0xF000	/* Number of Parity Errors */
-#define SH7750_SCFSR2_PERN_S  12
-#define SH7750_SCFSR2_FERN    0x0F00	/* Number of Framing Errors */
-#define SH7750_SCFSR2_FERN_S  8
-#define SH7750_SCFSR2_ER      0x0080	/* Receive Error */
-#define SH7750_SCFSR2_TEND    0x0040	/* Transmit End */
-#define SH7750_SCFSR2_TDFE    0x0020	/* Transmit FIFO Data Empty */
-#define SH7750_SCFSR2_BRK     0x0010	/* Break Detect */
-#define SH7750_SCFSR2_FER     0x0008	/* Framing Error */
-#define SH7750_SCFSR2_PER     0x0004	/* Parity Error */
-#define SH7750_SCFSR2_RDF     0x0002	/* Receive FIFO Data Full */
-#define SH7750_SCFSR2_DR      0x0001	/* Receive Data Ready */
-
-/* SCI Serial Port Register - SCSPTR1(byte) */
-#define SH7750_SCSPTR1_REGOFS 0xE0001C	/* offset */
-#define SH7750_SCSPTR1        SH7750_P4_REG32(SH7750_SCSPTR1_REGOFS)
-#define SH7750_SCSPTR1_A7     SH7750_A7_REG32(SH7750_SCSPTR1_REGOFS)
-
-#define SH7750_SCSPTR1_EIO    0x80	/* Error Interrupt Only */
-#define SH7750_SCSPTR1_SPB1IO 0x08	/* 1: Output SPB1DT bit to SCK pin */
-#define SH7750_SCSPTR1_SPB1DT 0x04	/* Serial Port Clock Port Data */
-#define SH7750_SCSPTR1_SPB0IO 0x02	/* 1: Output SPB0DT bit to TxD pin */
-#define SH7750_SCSPTR1_SPB0DT 0x01	/* Serial Port Break Data */
-
-/* SCIF Serial Port Register - SCSPTR2(half) */
-#define SH7750_SCSPTR2_REGOFS 0xE80020	/* offset */
-#define SH7750_SCSPTR2        SH7750_P4_REG32(SH7750_SCSPTR2_REGOFS)
-#define SH7750_SCSPTR2_A7     SH7750_A7_REG32(SH7750_SCSPTR2_REGOFS)
-
-#define SH7750_SCSPTR2_RTSIO  0x80	/* 1: Output RTSDT bit to RTS2\ pin */
-#define SH7750_SCSPTR2_RTSDT  0x40	/* RTS Port Data */
-#define SH7750_SCSPTR2_CTSIO  0x20	/* 1: Output CTSDT bit to CTS2\ pin */
-#define SH7750_SCSPTR2_CTSDT  0x10	/* CTS Port Data */
-#define SH7750_SCSPTR2_SPB2IO 0x02	/* 1: Output SPBDT bit to TxD2 pin */
-#define SH7750_SCSPTR2_SPB2DT 0x01	/* Serial Port Break Data */
-
-/* SCI Bit Rate Register - SCBRR1(byte), SCBRR2(byte) */
-#define SH7750_SCBRR_REGOFS(n) ((n) == 1 ? 0xE00004 : 0xE80004)	/* offset */
-#define SH7750_SCBRR(n)       SH7750_P4_REG32(SH7750_SCBRR_REGOFS(n))
-#define SH7750_SCBRR1         SH7750_SCBRR_P4(1)
-#define SH7750_SCBRR2         SH7750_SCBRR_P4(2)
-#define SH7750_SCBRR_A7(n)    SH7750_A7_REG32(SH7750_SCBRR_REGOFS(n))
-#define SH7750_SCBRR1_A7      SH7750_SCBRR_A7(1)
-#define SH7750_SCBRR2_A7      SH7750_SCBRR_A7(2)
-
-/* SCIF FIFO Control Register - SCFCR2(half) */
-#define SH7750_SCFCR2_REGOFS  0xE80018	/* offset */
-#define SH7750_SCFCR2         SH7750_P4_REG32(SH7750_SCFCR2_REGOFS)
-#define SH7750_SCFCR2_A7      SH7750_A7_REG32(SH7750_SCFCR2_REGOFS)
-
-#define SH7750_SCFCR2_RSTRG   0x700	/* RTS2\ Output Active Trigger; RTS2\
-					   signal goes to high level when the
-					   number of received data stored in
-					   FIFO exceeds the trigger number */
-#define SH7750_SCFCR2_RSTRG_15 0x000	/* 15 bytes */
-#define SH7750_SCFCR2_RSTRG_1  0x000	/* 1 byte */
-#define SH7750_SCFCR2_RSTRG_4  0x000	/* 4 bytes */
-#define SH7750_SCFCR2_RSTRG_6  0x000	/* 6 bytes */
-#define SH7750_SCFCR2_RSTRG_8  0x000	/* 8 bytes */
-#define SH7750_SCFCR2_RSTRG_10 0x000	/* 10 bytes */
-#define SH7750_SCFCR2_RSTRG_14 0x000	/* 14 bytes */
-
-#define SH7750_SCFCR2_RTRG    0x0C0	/* Receive FIFO Data Number Trigger,
-					   Receive Data Full (RDF) Flag sets
-					   when number of receive data bytes is
-					   equal or greater than the trigger
-					   number */
-#define SH7750_SCFCR2_RTRG_1  0x000	/* 1 byte */
-#define SH7750_SCFCR2_RTRG_4  0x040	/* 4 bytes */
-#define SH7750_SCFCR2_RTRG_8  0x080	/* 8 bytes */
-#define SH7750_SCFCR2_RTRG_14 0x0C0	/* 14 bytes */
-
-#define SH7750_SCFCR2_TTRG    0x030	/* Transmit FIFO Data Number Trigger,
-					   Transmit FIFO Data Register Empty (TDFE)
-					   flag sets when the number of remaining
-					   transmit data bytes is equal or less
-					   than the trigger number */
-#define SH7750_SCFCR2_TTRG_8  0x000	/* 8 bytes */
-#define SH7750_SCFCR2_TTRG_4  0x010	/* 4 bytes */
-#define SH7750_SCFCR2_TTRG_2  0x020	/* 2 bytes */
-#define SH7750_SCFCR2_TTRG_1  0x030	/* 1 byte */
-
-#define SH7750_SCFCR2_MCE     0x008	/* Modem Control Enable */
-#define SH7750_SCFCR2_TFRST   0x004	/* Transmit FIFO Data Register Reset,
-					   invalidates the transmit data in the
-					   transmit FIFO */
-#define SH7750_SCFCR2_RFRST   0x002	/* Receive FIFO Data Register Reset,
-					   invalidates the receive data in the
-					   receive FIFO data register and resets
-					   it to the empty state */
-#define SH7750_SCFCR2_LOOP    0x001	/* Loopback Test */
-
-/* SCIF FIFO Data Count Register - SCFDR2(half, read-only) */
-#define SH7750_SCFDR2_REGOFS  0xE8001C	/* offset */
-#define SH7750_SCFDR2         SH7750_P4_REG32(SH7750_SCFDR2_REGOFS)
-#define SH7750_SCFDR2_A7      SH7750_A7_REG32(SH7750_SCFDR2_REGOFS)
-
-#define SH7750_SCFDR2_T       0x1F00	/* Number of untransmitted data bytes
-					   in transmit FIFO */
-#define SH7750_SCFDR2_T_S     8
-#define SH7750_SCFDR2_R       0x001F	/* Number of received data bytes in
-					   receive FIFO */
-#define SH7750_SCFDR2_R_S     0
-
-/* SCIF Line Status Register - SCLSR2(half, read-only) */
-#define SH7750_SCLSR2_REGOFS  0xE80024	/* offset */
-#define SH7750_SCLSR2         SH7750_P4_REG32(SH7750_SCLSR2_REGOFS)
-#define SH7750_SCLSR2_A7      SH7750_A7_REG32(SH7750_SCLSR2_REGOFS)
-
-#define SH7750_SCLSR2_ORER    0x0001	/* Overrun Error */
-
-/*
- * SCI-based Smart Card Interface
- */
-/* Smart Card Mode Register - SCSCMR1(byte) */
-#define SH7750_SCSCMR1_REGOFS 0xE00018	/* offset */
-#define SH7750_SCSCMR1        SH7750_P4_REG32(SH7750_SCSCMR1_REGOFS)
-#define SH7750_SCSCMR1_A7     SH7750_A7_REG32(SH7750_SCSCMR1_REGOFS)
-
-#define SH7750_SCSCMR1_SDIR   0x08	/* Smart Card Data Transfer Direction: */
-#define SH7750_SCSCMR1_SDIR_LSBF 0x00	/* LSB-first */
-#define SH7750_SCSCMR1_SDIR_MSBF 0x08	/* MSB-first */
-
-#define SH7750_SCSCMR1_SINV   0x04	/* Smart Card Data Inversion */
-#define SH7750_SCSCMR1_SMIF   0x01	/* Smart Card Interface Mode Select */
-
-/* Smart-card specific bits in other registers */
-/* SCSMR1: */
-#define SH7750_SCSMR1_GSM     0x80	/* GSM mode select */
-
-/* SCSSR1: */
-#define SH7750_SCSSR1_ERS     0x10	/* Error Signal Status */
-
-/*
  * I/O Ports
  */
 /* Port Control Register A - PCTRA */
@@ -1554,48 +1241,6 @@
 #define SH7750_ICR_IRLM_RAW   0x0080	/*   IRL\ pins used as a four independent
 					   interrupt requests */
 
-/* Interrupt Priority Register A - IPRA (half) */
-#define SH7750_IPRA_REGOFS    0xD00004	/* offset */
-#define SH7750_IPRA           SH7750_P4_REG32(SH7750_IPRA_REGOFS)
-#define SH7750_IPRA_A7        SH7750_A7_REG32(SH7750_IPRA_REGOFS)
-
-#define SH7750_IPRA_TMU0      0xF000	/* TMU0 interrupt priority */
-#define SH7750_IPRA_TMU0_S    12
-#define SH7750_IPRA_TMU1      0x0F00	/* TMU1 interrupt priority */
-#define SH7750_IPRA_TMU1_S    8
-#define SH7750_IPRA_TMU2      0x00F0	/* TMU2 interrupt priority */
-#define SH7750_IPRA_TMU2_S    4
-#define SH7750_IPRA_RTC       0x000F	/* RTC interrupt priority */
-#define SH7750_IPRA_RTC_S     0
-
-/* Interrupt Priority Register B - IPRB (half) */
-#define SH7750_IPRB_REGOFS    0xD00008	/* offset */
-#define SH7750_IPRB           SH7750_P4_REG32(SH7750_IPRB_REGOFS)
-#define SH7750_IPRB_A7        SH7750_A7_REG32(SH7750_IPRB_REGOFS)
-
-#define SH7750_IPRB_WDT       0xF000	/* WDT interrupt priority */
-#define SH7750_IPRB_WDT_S     12
-#define SH7750_IPRB_REF       0x0F00	/* Memory Refresh unit interrupt
-					   priority */
-#define SH7750_IPRB_REF_S     8
-#define SH7750_IPRB_SCI1      0x00F0	/* SCI1 interrupt priority */
-#define SH7750_IPRB_SCI1_S    4
-
-/* Interrupt Priority Register ó - IPRó (half) */
-#define SH7750_IPRC_REGOFS    0xD00004	/* offset */
-#define SH7750_IPRC           SH7750_P4_REG32(SH7750_IPRC_REGOFS)
-#define SH7750_IPRC_A7        SH7750_A7_REG32(SH7750_IPRC_REGOFS)
-
-#define SH7750_IPRC_GPIO      0xF000	/* GPIO interrupt priority */
-#define SH7750_IPRC_GPIO_S    12
-#define SH7750_IPRC_DMAC      0x0F00	/* DMAC interrupt priority */
-#define SH7750_IPRC_DMAC_S    8
-#define SH7750_IPRC_SCIF      0x00F0	/* SCIF interrupt priority */
-#define SH7750_IPRC_SCIF_S    4
-#define SH7750_IPRC_HUDI      0x000F	/* H-UDI interrupt priority */
-#define SH7750_IPRC_HUDI_S    0
-
-
 /*
  * User Break Controller registers
  */

Added: trunk/src/host/qemu-neo1973/hw/sh_intc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh_intc.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh_intc.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,383 @@
+/*
+ * SuperH interrupt controller module
+ *
+ * Copyright (c) 2007 Magnus Damm
+ * Based on sh_timer.c and arm_timer.c by Paul Brook
+ * Copyright (c) 2005-2006 CodeSourcery.
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include <assert.h>
+#include "sh_intc.h"
+#include "vl.h"
+
+//#define DEBUG_INTC
+
+#define INTC_A7(x) ((x) & 0x1fffffff)
+#define INTC_ARRAY(x) (sizeof(x) / sizeof(x[0]))
+
+#define INTC_MODE_NONE       0
+#define INTC_MODE_DUAL_SET   1
+#define INTC_MODE_DUAL_CLR   2
+#define INTC_MODE_ENABLE_REG 3
+#define INTC_MODE_MASK_REG   4
+#define INTC_MODE_IS_PRIO    8
+
+static unsigned int sh_intc_mode(unsigned long address,
+				 unsigned long set_reg, unsigned long clr_reg)
+{
+    if ((address != INTC_A7(set_reg)) &&
+	(address != INTC_A7(clr_reg)))
+        return INTC_MODE_NONE;
+
+    if (set_reg && clr_reg) {
+        if (address == INTC_A7(set_reg))
+            return INTC_MODE_DUAL_SET;
+	else
+            return INTC_MODE_DUAL_CLR;
+    }
+
+    if (set_reg)
+        return INTC_MODE_ENABLE_REG;
+    else
+        return INTC_MODE_MASK_REG;
+}
+
+static void sh_intc_locate(struct intc_desc *desc,
+			   unsigned long address,
+			   unsigned long **datap,
+			   intc_enum **enums,
+			   unsigned int *first,
+			   unsigned int *width,
+			   unsigned int *modep)
+{
+    unsigned int i, mode;
+
+    /* this is slow but works for now */
+
+    if (desc->mask_regs) {
+        for (i = 0; i < desc->nr_mask_regs; i++) {
+	    struct intc_mask_reg *mr = desc->mask_regs + i;
+
+	    mode = sh_intc_mode(address, mr->set_reg, mr->clr_reg);
+	    if (mode == INTC_MODE_NONE)
+                continue;
+
+	    *modep = mode;
+	    *datap = &mr->value;
+	    *enums = mr->enum_ids;
+	    *first = mr->reg_width - 1;
+	    *width = 1;
+	    return;
+	}
+    }
+
+    if (desc->prio_regs) {
+        for (i = 0; i < desc->nr_prio_regs; i++) {
+	    struct intc_prio_reg *pr = desc->prio_regs + i;
+
+	    mode = sh_intc_mode(address, pr->set_reg, pr->clr_reg);
+	    if (mode == INTC_MODE_NONE)
+                continue;
+
+	    *modep = mode | INTC_MODE_IS_PRIO;
+	    *datap = &pr->value;
+	    *enums = pr->enum_ids;
+	    *first = (pr->reg_width / pr->field_width) - 1;
+	    *width = pr->field_width;
+	    return;
+	}
+    }
+
+    assert(0);
+}
+
+static void sh_intc_toggle(struct intc_desc *desc, intc_enum id,
+			   int enable, int is_group)
+{
+    struct intc_source *source = desc->sources + id;
+    int old = source->enable_count;
+
+    if (!id)
+	return;
+
+    if (!source->next_enum_id && (!source->enable_max || !source->vect)) {
+#ifdef DEBUG_INTC
+        printf("sh_intc: reserved interrupt source %d modified\n", id);
+#endif
+	return;
+    }
+
+    if (source->vect) {
+        if (enable)
+            source->enable_count++;
+	else 
+            source->enable_count--;
+
+        if (source->enable_count == source->enable_max) {
+#ifdef DEBUG_INTC
+            printf("sh_intc: enabling interrupt source %d -> 0x%04x\n",
+		   id, source->vect);
+#endif
+	}
+
+        if (old == source->enable_max) {
+#ifdef DEBUG_INTC
+            printf("sh_intc: disabling interrupt source %d -> 0x%04x\n",
+		   id, source->vect);
+#endif
+	}
+    }
+#ifdef DEBUG_INTC
+    else {
+        printf("setting interrupt group %d to %d\n", id, !!enable);
+    }
+#endif
+
+    if ((is_group || !source->vect) && source->next_enum_id) {
+        sh_intc_toggle(desc, source->next_enum_id, enable, 1);
+    }
+
+#ifdef DEBUG_INTC
+    if (!source->vect) {
+        printf("setting interrupt group %d to %d - done\n", id, !!enable);
+    }
+#endif
+}
+
+static uint32_t sh_intc_read(void *opaque, target_phys_addr_t offset)
+{
+    struct intc_desc *desc = opaque;
+    intc_enum *enum_ids = NULL;
+    unsigned int first = 0;
+    unsigned int width = 0;
+    unsigned int mode = 0;
+    unsigned long *valuep;
+
+#ifdef DEBUG_INTC
+    printf("sh_intc_read 0x%lx\n", (unsigned long) offset);
+#endif
+
+    sh_intc_locate(desc, (unsigned long)offset, &valuep, 
+		   &enum_ids, &first, &width, &mode);
+    return *valuep;
+}
+
+static void sh_intc_write(void *opaque, target_phys_addr_t offset,
+			  uint32_t value)
+{
+    struct intc_desc *desc = opaque;
+    intc_enum *enum_ids = NULL;
+    unsigned int first = 0;
+    unsigned int width = 0;
+    unsigned int mode = 0;
+    unsigned int k;
+    unsigned long *valuep;
+    unsigned long mask;
+
+#ifdef DEBUG_INTC
+    printf("sh_intc_write 0x%lx 0x%08x\n", (unsigned long) offset, value);
+#endif
+
+    sh_intc_locate(desc, (unsigned long)offset, &valuep, 
+		   &enum_ids, &first, &width, &mode);
+
+    switch (mode) {
+    case INTC_MODE_ENABLE_REG | INTC_MODE_IS_PRIO: break;
+    case INTC_MODE_DUAL_SET: value |= *valuep; break;
+    case INTC_MODE_DUAL_CLR: value = *valuep & ~value; break;
+    default: assert(0);
+    }
+
+    for (k = 0; k <= first; k++) {
+        mask = ((1 << width) - 1) << ((first - k) * width);
+
+	if ((*valuep & mask) == (value & mask))
+            continue;
+#if 0
+	printf("k = %d, first = %d, enum = %d, mask = 0x%08x\n", 
+	       k, first, enum_ids[k], (unsigned int)mask);
+#endif
+        sh_intc_toggle(desc, enum_ids[k], value & mask, 0);
+    }
+
+    *valuep = value;
+
+#ifdef DEBUG_INTC
+    printf("sh_intc_write 0x%lx -> 0x%08x\n", (unsigned long) offset, value);
+#endif
+}
+
+static CPUReadMemoryFunc *sh_intc_readfn[] = {
+    sh_intc_read,
+    sh_intc_read,
+    sh_intc_read
+};
+
+static CPUWriteMemoryFunc *sh_intc_writefn[] = {
+    sh_intc_write,
+    sh_intc_write,
+    sh_intc_write
+};
+
+struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id)
+{
+    if (id)
+        return desc->sources + id;
+
+    return NULL;
+}
+
+static void sh_intc_register(struct intc_desc *desc, 
+			     unsigned long address)
+{
+    if (address)
+        cpu_register_physical_memory(INTC_A7(address), 4, desc->iomemtype);
+}
+
+static void sh_intc_register_source(struct intc_desc *desc,
+				    intc_enum source,
+				    struct intc_group *groups,
+				    int nr_groups)
+{
+    unsigned int i, k;
+    struct intc_source *s;
+
+    if (desc->mask_regs) {
+        for (i = 0; i < desc->nr_mask_regs; i++) {
+	    struct intc_mask_reg *mr = desc->mask_regs + i;
+
+	    for (k = 0; k < INTC_ARRAY(mr->enum_ids); k++) {
+                if (mr->enum_ids[k] != source)
+                    continue;
+
+		s = sh_intc_source(desc, mr->enum_ids[k]);
+		if (s)
+                    s->enable_max++;
+	    }
+	}
+    }
+
+    if (desc->prio_regs) {
+        for (i = 0; i < desc->nr_prio_regs; i++) {
+	    struct intc_prio_reg *pr = desc->prio_regs + i;
+
+	    for (k = 0; k < INTC_ARRAY(pr->enum_ids); k++) {
+                if (pr->enum_ids[k] != source)
+                    continue;
+
+		s = sh_intc_source(desc, pr->enum_ids[k]);
+		if (s)
+                    s->enable_max++;
+	    }
+	}
+    }
+
+    if (groups) {
+        for (i = 0; i < nr_groups; i++) {
+	    struct intc_group *gr = groups + i;
+
+	    for (k = 0; k < INTC_ARRAY(gr->enum_ids); k++) {
+                if (gr->enum_ids[k] != source)
+                    continue;
+
+		s = sh_intc_source(desc, gr->enum_ids[k]);
+		if (s)
+                    s->enable_max++;
+	    }
+	}
+    }
+
+}
+
+void sh_intc_register_sources(struct intc_desc *desc,
+			      struct intc_vect *vectors,
+			      int nr_vectors,
+			      struct intc_group *groups,
+			      int nr_groups)
+{
+    unsigned int i, k;
+    struct intc_source *s;
+
+    for (i = 0; i < nr_vectors; i++) {
+	struct intc_vect *vect = vectors + i;
+
+	sh_intc_register_source(desc, vect->enum_id, groups, nr_groups);
+	s = sh_intc_source(desc, vect->enum_id);
+	if (s)
+	    s->vect = vect->vect;
+
+#ifdef DEBUG_INTC
+	printf("sh_intc: registered source %d -> 0x%04x (%d/%d)\n",
+	       vect->enum_id, s->vect, s->enable_count, s->enable_max);
+#endif
+    }
+
+    if (groups) {
+        for (i = 0; i < nr_groups; i++) {
+	    struct intc_group *gr = groups + i;
+
+	    s = sh_intc_source(desc, gr->enum_id);
+	    s->next_enum_id = gr->enum_ids[0];
+
+	    for (k = 1; k < INTC_ARRAY(gr->enum_ids); k++) {
+                if (!gr->enum_ids[k])
+                    continue;
+
+		s = sh_intc_source(desc, gr->enum_ids[k - 1]);
+		s->next_enum_id = gr->enum_ids[k];
+	    }
+
+#ifdef DEBUG_INTC
+	    printf("sh_intc: registered group %d (%d/%d)\n",
+		   gr->enum_id, s->enable_count, s->enable_max);
+#endif
+	}
+    }
+}
+
+int sh_intc_init(struct intc_desc *desc,
+		 int nr_sources,
+		 struct intc_mask_reg *mask_regs,
+		 int nr_mask_regs,
+		 struct intc_prio_reg *prio_regs,
+		 int nr_prio_regs)
+{
+    unsigned int i;
+
+    desc->nr_sources = nr_sources;
+    desc->mask_regs = mask_regs;
+    desc->nr_mask_regs = nr_mask_regs;
+    desc->prio_regs = prio_regs;
+    desc->nr_prio_regs = nr_prio_regs;
+
+    i = sizeof(struct intc_source) * nr_sources;
+    desc->sources = malloc(i);
+    if (!desc->sources)
+        return -1;
+
+    memset(desc->sources, 0, i);
+ 
+    desc->iomemtype = cpu_register_io_memory(0, sh_intc_readfn,
+					     sh_intc_writefn, desc);
+    if (desc->mask_regs) {
+        for (i = 0; i < desc->nr_mask_regs; i++) {
+	    struct intc_mask_reg *mr = desc->mask_regs + i;
+
+	    sh_intc_register(desc, mr->set_reg);
+	    sh_intc_register(desc, mr->clr_reg);
+	}
+    }
+
+    if (desc->prio_regs) {
+        for (i = 0; i < desc->nr_prio_regs; i++) {
+	    struct intc_prio_reg *pr = desc->prio_regs + i;
+
+	    sh_intc_register(desc, pr->set_reg);
+	    sh_intc_register(desc, pr->clr_reg);
+	}
+    }
+
+    return 0;
+}

Added: trunk/src/host/qemu-neo1973/hw/sh_intc.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh_intc.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh_intc.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,69 @@
+#ifndef __SH_INTC_H__
+#define __SH_INTC_H__
+
+typedef unsigned char intc_enum;
+
+struct intc_vect {
+    intc_enum enum_id;
+    unsigned short vect;
+};
+
+#define INTC_VECT(enum_id, vect) { enum_id, vect }
+
+struct intc_group {
+    intc_enum enum_id;
+    intc_enum enum_ids[32];
+};
+
+#define INTC_GROUP(enum_id, ids...) { enum_id, { ids } }
+
+struct intc_mask_reg {
+    unsigned long set_reg, clr_reg, reg_width;
+    intc_enum enum_ids[32];
+    unsigned long value;
+};
+
+struct intc_prio_reg {
+    unsigned long set_reg, clr_reg, reg_width, field_width;
+    intc_enum enum_ids[16];
+    unsigned long value;
+};
+
+#define _INTC_ARRAY(a) a, sizeof(a)/sizeof(*a)
+
+struct intc_source {
+    unsigned short vect;
+    intc_enum next_enum_id;
+
+    int asserted;
+    int enable_count;
+    int enable_max;
+};
+
+struct intc_desc {
+    struct intc_source *sources;
+    int nr_sources;
+    struct intc_mask_reg *mask_regs;
+    int nr_mask_regs;
+    struct intc_prio_reg *prio_regs;
+    int nr_prio_regs;
+
+    int iomemtype;
+};
+
+struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id);
+
+void sh_intc_register_sources(struct intc_desc *desc,
+			      struct intc_vect *vectors,
+			      int nr_vectors,
+			      struct intc_group *groups,
+			      int nr_groups);
+
+int sh_intc_init(struct intc_desc *desc,
+		 int nr_sources,
+		 struct intc_mask_reg *mask_regs,
+		 int nr_mask_regs,
+		 struct intc_prio_reg *prio_regs,
+		 int nr_prio_regs);
+
+#endif /* __SH_INTC_H__ */

Added: trunk/src/host/qemu-neo1973/hw/sh_serial.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh_serial.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh_serial.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,315 @@
+/*
+ * QEMU SCI/SCIF serial port emulation
+ *
+ * Copyright (c) 2007 Magnus Damm
+ *
+ * Based on serial.c - QEMU 16450 UART emulation
+ * Copyright (c) 2003-2004 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"
+#include <assert.h>
+
+//#define DEBUG_SERIAL
+
+#define SH_SERIAL_FLAG_TEND (1 << 0)
+#define SH_SERIAL_FLAG_TDE  (1 << 1)
+#define SH_SERIAL_FLAG_RDF  (1 << 2)
+#define SH_SERIAL_FLAG_BRK  (1 << 3)
+#define SH_SERIAL_FLAG_DR   (1 << 4)
+
+typedef struct {
+    uint8_t smr;
+    uint8_t brr;
+    uint8_t scr;
+    uint8_t dr; /* ftdr / tdr */
+    uint8_t sr; /* fsr / ssr */
+    uint16_t fcr;
+    uint8_t sptr;
+
+    uint8_t rx_fifo[16]; /* frdr / rdr */
+    uint8_t rx_cnt;
+
+    target_phys_addr_t base;
+    int freq;
+    int feat;
+    int flags;
+
+    CharDriverState *chr;
+} sh_serial_state;
+
+static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
+{
+    sh_serial_state *s = opaque;
+    unsigned char ch;
+
+#ifdef DEBUG_SERIAL
+    printf("sh_serial: write base=0x%08lx offs=0x%02x val=0x%02x\n",
+	   (unsigned long) s->base, offs, val);
+#endif
+    switch(offs) {
+    case 0x00: /* SMR */
+        s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff);
+        return;
+    case 0x04: /* BRR */
+        s->brr = val;
+	return;
+    case 0x08: /* SCR */
+        s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfb : 0xff);
+        if (!(val & (1 << 5)))
+            s->flags |= SH_SERIAL_FLAG_TEND;
+        return;
+    case 0x0c: /* FTDR / TDR */
+        if (s->chr) {
+            ch = val;
+            qemu_chr_write(s->chr, &ch, 1);
+	}
+	s->dr = val;
+	s->flags &= ~SH_SERIAL_FLAG_TDE;
+        return;
+#if 0
+    case 0x14: /* FRDR / RDR */
+        ret = 0;
+        break;
+#endif
+    }
+    if (s->feat & SH_SERIAL_FEAT_SCIF) {
+        switch(offs) {
+        case 0x10: /* FSR */
+            if (!(val & (1 << 6)))
+                s->flags &= ~SH_SERIAL_FLAG_TEND;
+            if (!(val & (1 << 5)))
+                s->flags &= ~SH_SERIAL_FLAG_TDE;
+            if (!(val & (1 << 4)))
+                s->flags &= ~SH_SERIAL_FLAG_BRK;
+            if (!(val & (1 << 1)))
+                s->flags &= ~SH_SERIAL_FLAG_RDF;
+            if (!(val & (1 << 0)))
+                s->flags &= ~SH_SERIAL_FLAG_DR;
+            return;
+        case 0x18: /* FCR */
+            s->fcr = val;
+            return;
+        case 0x20: /* SPTR */
+            s->sptr = val;
+            return;
+        case 0x24: /* LSR */
+            return;
+        }
+    }
+    else {
+#if 0
+        switch(offs) {
+        case 0x0c:
+            ret = s->dr;
+            break;
+        case 0x10:
+            ret = 0;
+            break;
+        case 0x1c:
+            ret = s->sptr;
+            break;
+        }
+#endif
+    }
+
+    fprintf(stderr, "sh_serial: unsupported write to 0x%02x\n", offs);
+    assert(0);
+}
+
+static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs)
+{
+    sh_serial_state *s = opaque;
+    uint32_t ret = ~0;
+
+#if 0
+    switch(offs) {
+    case 0x00:
+        ret = s->smr;
+        break;
+    case 0x04:
+        ret = s->brr;
+	break;
+    case 0x08:
+        ret = s->scr;
+        break;
+    case 0x14:
+        ret = 0;
+        break;
+    }
+#endif
+    if (s->feat & SH_SERIAL_FEAT_SCIF) {
+        switch(offs) {
+        case 0x10: /* FSR */
+            ret = 0;
+            if (s->flags & SH_SERIAL_FLAG_TEND)
+                ret |= (1 << 6);
+            if (s->flags & SH_SERIAL_FLAG_TDE)
+                ret |= (1 << 5);
+            if (s->flags & SH_SERIAL_FLAG_BRK)
+                ret |= (1 << 4);
+            if (s->flags & SH_SERIAL_FLAG_RDF)
+                ret |= (1 << 1);
+            if (s->flags & SH_SERIAL_FLAG_DR)
+                ret |= (1 << 0);
+
+	    if (s->scr & (1 << 5))
+                s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
+
+            break;
+#if 0
+        case 0x18:
+            ret = s->fcr;
+            break;
+#endif
+        case 0x1c:
+            ret = s->rx_cnt;
+            break;
+        case 0x20:
+            ret = s->sptr;
+            break;
+        case 0x24:
+            ret = 0;
+            break;
+        }
+    }
+    else {
+#if 0
+        switch(offs) {
+        case 0x0c:
+            ret = s->dr;
+            break;
+        case 0x10:
+            ret = 0;
+            break;
+        case 0x1c:
+            ret = s->sptr;
+            break;
+        }
+#endif
+    }
+#ifdef DEBUG_SERIAL
+    printf("sh_serial: read base=0x%08lx offs=0x%02x val=0x%x\n",
+	   (unsigned long) s->base, offs, ret);
+#endif
+
+    if (ret & ~((1 << 16) - 1)) {
+        fprintf(stderr, "sh_serial: unsupported read from 0x%02x\n", offs);
+	assert(0);
+    }
+
+    return ret;
+}
+
+static int sh_serial_can_receive(sh_serial_state *s)
+{
+    return 0;
+}
+
+static void sh_serial_receive_byte(sh_serial_state *s, int ch)
+{
+}
+
+static void sh_serial_receive_break(sh_serial_state *s)
+{
+}
+
+static int sh_serial_can_receive1(void *opaque)
+{
+    sh_serial_state *s = opaque;
+    return sh_serial_can_receive(s);
+}
+
+static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
+{
+    sh_serial_state *s = opaque;
+    sh_serial_receive_byte(s, buf[0]);
+}
+
+static void sh_serial_event(void *opaque, int event)
+{
+    sh_serial_state *s = opaque;
+    if (event == CHR_EVENT_BREAK)
+        sh_serial_receive_break(s);
+}
+
+uint32_t sh_serial_read (void *opaque, target_phys_addr_t addr)
+{
+    sh_serial_state *s = opaque;
+    return sh_serial_ioport_read(s, addr - s->base);
+}
+
+void sh_serial_write (void *opaque,
+		      target_phys_addr_t addr, uint32_t value)
+{
+    sh_serial_state *s = opaque;
+    sh_serial_ioport_write(s, addr - s->base, value);
+}
+
+static CPUReadMemoryFunc *sh_serial_readfn[] = {
+    &sh_serial_read,
+    &sh_serial_read,
+    &sh_serial_read,
+};
+
+static CPUWriteMemoryFunc *sh_serial_writefn[] = {
+    &sh_serial_write,
+    &sh_serial_write,
+    &sh_serial_write,
+};
+
+void sh_serial_init (target_phys_addr_t base, int feat,
+		     uint32_t freq, CharDriverState *chr)
+{
+    sh_serial_state *s;
+    int s_io_memory;
+
+    s = qemu_mallocz(sizeof(sh_serial_state));
+    if (!s)
+        return;
+
+    s->base = base;
+    s->feat = feat;
+    s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
+
+    s->smr = 0;
+    s->brr = 0xff;
+    s->scr = 0;
+    s->sptr = 0;
+
+    if (feat & SH_SERIAL_FEAT_SCIF) {
+        s->fcr = 0;
+    }
+    else {
+        s->dr = 0xff;
+    }
+
+    s->rx_cnt = 0;
+
+    s_io_memory = cpu_register_io_memory(0, sh_serial_readfn,
+					 sh_serial_writefn, s);
+    cpu_register_physical_memory(base, 0x28, s_io_memory);
+
+    s->chr = chr;
+
+    if (chr)
+        qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
+			      sh_serial_event, s);
+}

Added: trunk/src/host/qemu-neo1973/hw/sh_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh_timer.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sh_timer.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,323 @@
+/*
+ * SuperH Timer modules.
+ *
+ * Copyright (c) 2007 Magnus Damm
+ * Based on arm_timer.c by Paul Brook
+ * Copyright (c) 2005-2006 CodeSourcery.
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include "vl.h"
+
+//#define DEBUG_TIMER
+
+#define TIMER_TCR_TPSC          (7 << 0)
+#define TIMER_TCR_CKEG          (3 << 3)
+#define TIMER_TCR_UNIE          (1 << 5)
+#define TIMER_TCR_ICPE          (3 << 6)
+#define TIMER_TCR_UNF           (1 << 8)
+#define TIMER_TCR_ICPF          (1 << 9)
+#define TIMER_TCR_RESERVED      (0x3f << 10)
+
+#define TIMER_FEAT_CAPT   (1 << 0)
+#define TIMER_FEAT_EXTCLK (1 << 1)
+
+typedef struct {
+    ptimer_state *timer;
+    uint32_t tcnt;
+    uint32_t tcor;
+    uint32_t tcr;
+    uint32_t tcpr;
+    int freq;
+    int int_level;
+    int feat;
+    int enabled;
+    qemu_irq irq;
+} sh_timer_state;
+
+/* Check all active timers, and schedule the next timer interrupt. */
+
+static void sh_timer_update(sh_timer_state *s)
+{
+#if 0 /* not yet */
+    /* Update interrupts.  */
+    if (s->int_level && (s->tcr & TIMER_TCR_UNIE)) {
+        qemu_irq_raise(s->irq);
+    } else {
+        qemu_irq_lower(s->irq);
+    }
+#endif
+}
+
+uint32_t sh_timer_read(void *opaque, target_phys_addr_t offset)
+{
+    sh_timer_state *s = (sh_timer_state *)opaque;
+
+    switch (offset >> 2) {
+    case 0:
+        return s->tcor;
+    case 1:
+        return ptimer_get_count(s->timer);
+    case 2:
+        return s->tcr | (s->int_level ? TIMER_TCR_UNF : 0);
+    case 3:
+        if (s->feat & TIMER_FEAT_CAPT)
+            return s->tcpr;
+    default:
+        cpu_abort (cpu_single_env, "sh_timer_read: Bad offset %x\n",
+                   (int)offset);
+        return 0;
+    }
+}
+
+static void sh_timer_write(void *opaque, target_phys_addr_t offset,
+                            uint32_t value)
+{
+    sh_timer_state *s = (sh_timer_state *)opaque;
+    int freq;
+
+    switch (offset >> 2) {
+    case 0:
+        s->tcor = value;
+        ptimer_set_limit(s->timer, s->tcor, 0);
+        break;
+    case 1:
+        s->tcnt = value;
+        ptimer_set_count(s->timer, s->tcnt);
+        break;
+    case 2:
+        if (s->enabled) {
+            /* Pause the timer if it is running.  This may cause some
+               inaccuracy dure to rounding, but avoids a whole lot of other
+               messyness.  */
+            ptimer_stop(s->timer);
+        }
+        freq = s->freq;
+        /* ??? Need to recalculate expiry time after changing divisor.  */
+        switch (value & TIMER_TCR_TPSC) {
+        case 0: freq >>= 2; break;
+        case 1: freq >>= 4; break;
+        case 2: freq >>= 6; break;
+        case 3: freq >>= 8; break;
+        case 4: freq >>= 10; break;
+	case 6:
+	case 7: if (s->feat & TIMER_FEAT_EXTCLK) break;
+	default: cpu_abort (cpu_single_env,
+			   "sh_timer_write: Reserved TPSC value\n"); break;
+        }
+        switch ((value & TIMER_TCR_CKEG) >> 3) {
+	case 0: break;
+        case 1:
+        case 2:
+        case 3: if (s->feat & TIMER_FEAT_EXTCLK) break;
+	default: cpu_abort (cpu_single_env,
+			   "sh_timer_write: Reserved CKEG value\n"); break;
+        }
+        switch ((value & TIMER_TCR_ICPE) >> 6) {
+	case 0: break;
+        case 2:
+        case 3: if (s->feat & TIMER_FEAT_CAPT) break;
+	default: cpu_abort (cpu_single_env,
+			   "sh_timer_write: Reserved ICPE value\n"); break;
+        }
+	if ((value & TIMER_TCR_UNF) == 0)
+            s->int_level = 0;
+
+	value &= ~TIMER_TCR_UNF;
+
+	if ((value & TIMER_TCR_ICPF) && (!(s->feat & TIMER_FEAT_CAPT)))
+            cpu_abort (cpu_single_env,
+		       "sh_timer_write: Reserved ICPF value\n");
+
+	value &= ~TIMER_TCR_ICPF; /* capture not supported */
+
+	if (value & TIMER_TCR_RESERVED)
+            cpu_abort (cpu_single_env,
+		       "sh_timer_write: Reserved TCR bits set\n");
+        s->tcr = value;
+        ptimer_set_limit(s->timer, s->tcor, 0);
+        ptimer_set_freq(s->timer, freq);
+        if (s->enabled) {
+            /* Restart the timer if still enabled.  */
+            ptimer_run(s->timer, 0);
+        }
+        break;
+    case 3:
+        if (s->feat & TIMER_FEAT_CAPT) {
+            s->tcpr = value;
+	    break;
+	}
+    default:
+        cpu_abort (cpu_single_env, "sh_timer_write: Bad offset %x\n",
+                   (int)offset);
+    }
+    sh_timer_update(s);
+}
+
+static void sh_timer_start_stop(void *opaque, int enable)
+{
+    sh_timer_state *s = (sh_timer_state *)opaque;
+
+#ifdef DEBUG_TIMER
+    printf("sh_timer_start_stop %d (%d)\n", enable, s->enabled);
+#endif
+
+    if (s->enabled && !enable) {
+        ptimer_stop(s->timer);
+    }
+    if (!s->enabled && enable) {
+        ptimer_run(s->timer, 0);
+    }
+    s->enabled = !!enable;
+
+#ifdef DEBUG_TIMER
+    printf("sh_timer_start_stop done %d\n", s->enabled);
+#endif
+}
+
+static void sh_timer_tick(void *opaque)
+{
+    sh_timer_state *s = (sh_timer_state *)opaque;
+    s->int_level = s->enabled;
+    sh_timer_update(s);
+}
+
+static void *sh_timer_init(uint32_t freq, int feat)
+{
+    sh_timer_state *s;
+    QEMUBH *bh;
+
+    s = (sh_timer_state *)qemu_mallocz(sizeof(sh_timer_state));
+    s->freq = freq;
+    s->feat = feat;
+    s->tcor = 0xffffffff;
+    s->tcnt = 0xffffffff;
+    s->tcpr = 0xdeadbeef;
+    s->tcor = 0;
+    s->enabled = 0;
+
+    bh = qemu_bh_new(sh_timer_tick, s);
+    s->timer = ptimer_init(bh);
+    /* ??? Save/restore.  */
+    return s;
+}
+
+typedef struct {
+    void *timer[3];
+    int level[3];
+    uint32_t tocr;
+    uint32_t tstr;
+    target_phys_addr_t base;
+    int feat;
+} tmu012_state;
+
+static uint32_t tmu012_read(void *opaque, target_phys_addr_t offset)
+{
+    tmu012_state *s = (tmu012_state *)opaque;
+
+#ifdef DEBUG_TIMER
+    printf("tmu012_read 0x%lx\n", (unsigned long) offset);
+#endif
+    offset -= s->base;
+
+    if (offset >= 0x20) {
+        if (!(s->feat & TMU012_FEAT_3CHAN))
+	    cpu_abort (cpu_single_env, "tmu012_write: Bad channel offset %x\n",
+		       (int)offset);
+        return sh_timer_read(s->timer[2], offset - 0x20);
+    }
+
+    if (offset >= 0x14)
+        return sh_timer_read(s->timer[1], offset - 0x14);
+
+    if (offset >= 0x08)
+        return sh_timer_read(s->timer[0], offset - 0x08);
+
+    if (offset == 4)
+        return s->tstr;
+
+    if ((s->feat & TMU012_FEAT_TOCR) && offset == 0)
+        return s->tocr;
+
+    cpu_abort (cpu_single_env, "tmu012_write: Bad offset %x\n",
+	       (int)offset);
+    return 0;
+}
+
+static void tmu012_write(void *opaque, target_phys_addr_t offset,
+                        uint32_t value)
+{
+    tmu012_state *s = (tmu012_state *)opaque;
+
+#ifdef DEBUG_TIMER
+    printf("tmu012_write 0x%lx 0x%08x\n", (unsigned long) offset, value);
+#endif
+    offset -= s->base;
+
+    if (offset >= 0x20) {
+        if (!(s->feat & TMU012_FEAT_3CHAN))
+	    cpu_abort (cpu_single_env, "tmu012_write: Bad channel offset %x\n",
+		       (int)offset);
+        sh_timer_write(s->timer[2], offset - 0x20, value);
+	return;
+    }
+
+    if (offset >= 0x14) {
+        sh_timer_write(s->timer[1], offset - 0x14, value);
+	return;
+    }
+
+    if (offset >= 0x08) {
+        sh_timer_write(s->timer[0], offset - 0x08, value);
+	return;
+    }
+
+    if (offset == 4) {
+        sh_timer_start_stop(s->timer[0], value & (1 << 0));
+        sh_timer_start_stop(s->timer[1], value & (1 << 1));
+        if (s->feat & TMU012_FEAT_3CHAN)
+            sh_timer_start_stop(s->timer[2], value & (1 << 2));
+	else
+            if (value & (1 << 2))
+                cpu_abort (cpu_single_env, "tmu012_write: Bad channel\n");
+
+	s->tstr = value;
+	return;
+    }
+
+    if ((s->feat & TMU012_FEAT_TOCR) && offset == 0) {
+        s->tocr = value & (1 << 0);
+    }
+}
+
+static CPUReadMemoryFunc *tmu012_readfn[] = {
+    tmu012_read,
+    tmu012_read,
+    tmu012_read
+};
+
+static CPUWriteMemoryFunc *tmu012_writefn[] = {
+    tmu012_write,
+    tmu012_write,
+    tmu012_write
+};
+
+void tmu012_init(uint32_t base, int feat, uint32_t freq)
+{
+    int iomemtype;
+    tmu012_state *s;
+    int timer_feat = (feat & TMU012_FEAT_EXTCLK) ? TIMER_FEAT_EXTCLK : 0;
+
+    s = (tmu012_state *)qemu_mallocz(sizeof(tmu012_state));
+    s->base = base;
+    s->feat = feat;
+    s->timer[0] = sh_timer_init(freq, timer_feat);
+    s->timer[1] = sh_timer_init(freq, timer_feat);
+    if (feat & TMU012_FEAT_3CHAN)
+        s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT);
+    iomemtype = cpu_register_io_memory(0, tmu012_readfn,
+                                       tmu012_writefn, s);
+    cpu_register_physical_memory(base, 0x00001000, iomemtype);
+    /* ??? Save/restore.  */
+}

Modified: trunk/src/host/qemu-neo1973/hw/shix.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/shix.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/shix.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -83,12 +83,14 @@
     cpu_register_physical_memory(0x0c000000, 0x01000000, 0x01004000);
 
     /* Load BIOS in 0 (and access it through P2, 0xA0000000) */
-    printf("%s: load BIOS '%s'\n", __func__, BIOS_FILENAME);
-    ret = load_image(BIOS_FILENAME, phys_ram_base);
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    printf("%s: load BIOS '%s'\n", __func__, bios_name);
+    ret = load_image(bios_name, phys_ram_base);
     if (ret < 0) {		/* Check bios size */
 	fprintf(stderr, "ret=%d\n", ret);
 	fprintf(stderr, "qemu: could not load SHIX bios '%s'\n",
-		BIOS_FILENAME);
+		bios_name);
 	exit(1);
     }
 

Modified: trunk/src/host/qemu-neo1973/hw/slavio_intctl.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_intctl.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/slavio_intctl.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -100,21 +100,21 @@
     DPRINTF("write cpu %d reg 0x" TARGET_FMT_plx " = %x\n", cpu, addr, val);
     switch (saddr) {
     case 1: // clear pending softints
-	if (val & 0x4000)
-	    val |= 80000000;
-	val &= 0xfffe0000;
-	s->intreg_pending[cpu] &= ~val;
+        if (val & 0x4000)
+            val |= 80000000;
+        val &= 0xfffe0000;
+        s->intreg_pending[cpu] &= ~val;
         slavio_check_interrupts(s);
-	DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
-	break;
+        DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
+        break;
     case 2: // set softint
-	val &= 0xfffe0000;
-	s->intreg_pending[cpu] |= val;
+        val &= 0xfffe0000;
+        s->intreg_pending[cpu] |= val;
         slavio_check_interrupts(s);
-	DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
-	break;
+        DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
+        break;
     default:
-	break;
+        break;
     }
 }
 
@@ -165,27 +165,27 @@
     DPRINTF("write system reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
     switch (saddr) {
     case 2: // clear (enable)
-	// Force clear unused bits
-	val &= ~0x4fb2007f;
-	s->intregm_disabled &= ~val;
-	DPRINTF("Enabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
-	slavio_check_interrupts(s);
-	break;
+        // Force clear unused bits
+        val &= ~0x4fb2007f;
+        s->intregm_disabled &= ~val;
+        DPRINTF("Enabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
+        slavio_check_interrupts(s);
+        break;
     case 3: // set (disable, clear pending)
-	// Force clear unused bits
-	val &= ~0x4fb2007f;
-	s->intregm_disabled |= val;
-	s->intregm_pending &= ~val;
+        // Force clear unused bits
+        val &= ~0x4fb2007f;
+        s->intregm_disabled |= val;
+        s->intregm_pending &= ~val;
         slavio_check_interrupts(s);
-	DPRINTF("Disabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
-	break;
+        DPRINTF("Disabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
+        break;
     case 4:
-	s->target_cpu = val & (MAX_CPUS - 1);
+        s->target_cpu = val & (MAX_CPUS - 1);
         slavio_check_interrupts(s);
-	DPRINTF("Set master irq cpu %d\n", s->target_cpu);
-	break;
+        DPRINTF("Set master irq cpu %d\n", s->target_cpu);
+        break;
     default:
-	break;
+        break;
     }
 }
 
@@ -207,7 +207,7 @@
     int i;
 
     for (i = 0; i < MAX_CPUS; i++) {
-	term_printf("per-cpu %d: pending 0x%08x\n", i, s->intreg_pending[i]);
+        term_printf("per-cpu %d: pending 0x%08x\n", i, s->intreg_pending[i]);
     }
     term_printf("master: pending 0x%08x, disabled 0x%08x\n", s->intregm_pending, s->intregm_disabled);
 }
@@ -310,7 +310,7 @@
     int i;
 
     for (i = 0; i < MAX_CPUS; i++) {
-	qemu_put_be32s(f, &s->intreg_pending[i]);
+        qemu_put_be32s(f, &s->intreg_pending[i]);
     }
     qemu_put_be32s(f, &s->intregm_pending);
     qemu_put_be32s(f, &s->intregm_disabled);
@@ -326,7 +326,7 @@
         return -EINVAL;
 
     for (i = 0; i < MAX_CPUS; i++) {
-	qemu_get_be32s(f, &s->intreg_pending[i]);
+        qemu_get_be32s(f, &s->intreg_pending[i]);
     }
     qemu_get_be32s(f, &s->intregm_pending);
     qemu_get_be32s(f, &s->intregm_disabled);
@@ -341,7 +341,7 @@
     int i;
 
     for (i = 0; i < MAX_CPUS; i++) {
-	s->intreg_pending[i] = 0;
+        s->intreg_pending[i] = 0;
     }
     s->intregm_disabled = ~0xffb2007f;
     s->intregm_pending = 0;
@@ -363,8 +363,8 @@
 
     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_SIZE,
+        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_SIZE,
                                      slavio_intctl_io_memory);
         s->cpu_irqs[i] = parent_irq[i];
     }

Modified: trunk/src/host/qemu-neo1973/hw/slavio_misc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_misc.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/slavio_misc.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -76,9 +76,9 @@
 
     MISC_DPRINTF("Power fail: %d, config: %d\n", power_failing, s->config);
     if (power_failing && (s->config & 0x8)) {
-	s->aux2 |= 0x4;
+        s->aux2 |= 0x4;
     } else {
-	s->aux2 &= ~0x4;
+        s->aux2 &= ~0x4;
     }
     slavio_misc_update_irq(s);
 }
@@ -89,44 +89,44 @@
 
     switch (addr & 0xfff0000) {
     case 0x1800000:
-	MISC_DPRINTF("Write config %2.2x\n", val & 0xff);
-	s->config = val & 0xff;
-	slavio_misc_update_irq(s);
-	break;
+        MISC_DPRINTF("Write config %2.2x\n", val & 0xff);
+        s->config = val & 0xff;
+        slavio_misc_update_irq(s);
+        break;
     case 0x1900000:
-	MISC_DPRINTF("Write aux1 %2.2x\n", val & 0xff);
-	s->aux1 = val & 0xff;
-	break;
+        MISC_DPRINTF("Write aux1 %2.2x\n", val & 0xff);
+        s->aux1 = val & 0xff;
+        break;
     case 0x1910000:
-	val &= 0x3;
-	MISC_DPRINTF("Write aux2 %2.2x\n", val);
-	val |= s->aux2 & 0x4;
-	if (val & 0x2) // Clear Power Fail int
-	    val &= 0x1;
-	s->aux2 = val;
-	if (val & 1)
-	    qemu_system_shutdown_request();
-	slavio_misc_update_irq(s);
-	break;
+        val &= 0x3;
+        MISC_DPRINTF("Write aux2 %2.2x\n", val);
+        val |= s->aux2 & 0x4;
+        if (val & 0x2) // Clear Power Fail int
+            val &= 0x1;
+        s->aux2 = val;
+        if (val & 1)
+            qemu_system_shutdown_request();
+        slavio_misc_update_irq(s);
+        break;
     case 0x1a00000:
-	MISC_DPRINTF("Write diag %2.2x\n", val & 0xff);
-	s->diag = val & 0xff;
-	break;
+        MISC_DPRINTF("Write diag %2.2x\n", val & 0xff);
+        s->diag = val & 0xff;
+        break;
     case 0x1b00000:
-	MISC_DPRINTF("Write modem control %2.2x\n", val & 0xff);
-	s->mctrl = val & 0xff;
-	break;
+        MISC_DPRINTF("Write modem control %2.2x\n", val & 0xff);
+        s->mctrl = val & 0xff;
+        break;
     case 0x1f00000:
-	MISC_DPRINTF("Write system control %2.2x\n", val & 0xff);
-	if (val & 1) {
-	    s->sysctrl = 0x2;
-	    qemu_system_reset_request();
-	}
-	break;
+        MISC_DPRINTF("Write system control %2.2x\n", val & 0xff);
+        if (val & 1) {
+            s->sysctrl = 0x2;
+            qemu_system_reset_request();
+        }
+        break;
     case 0xa000000:
-	MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
+        MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
         cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
-	break;
+        break;
     }
 }
 
@@ -137,32 +137,32 @@
 
     switch (addr & 0xfff0000) {
     case 0x1800000:
-	ret = s->config;
-	MISC_DPRINTF("Read config %2.2x\n", ret);
-	break;
+        ret = s->config;
+        MISC_DPRINTF("Read config %2.2x\n", ret);
+        break;
     case 0x1900000:
-	ret = s->aux1;
-	MISC_DPRINTF("Read aux1 %2.2x\n", ret);
-	break;
+        ret = s->aux1;
+        MISC_DPRINTF("Read aux1 %2.2x\n", ret);
+        break;
     case 0x1910000:
-	ret = s->aux2;
-	MISC_DPRINTF("Read aux2 %2.2x\n", ret);
-	break;
+        ret = s->aux2;
+        MISC_DPRINTF("Read aux2 %2.2x\n", ret);
+        break;
     case 0x1a00000:
-	ret = s->diag;
-	MISC_DPRINTF("Read diag %2.2x\n", ret);
-	break;
+        ret = s->diag;
+        MISC_DPRINTF("Read diag %2.2x\n", ret);
+        break;
     case 0x1b00000:
-	ret = s->mctrl;
-	MISC_DPRINTF("Read modem control %2.2x\n", ret);
-	break;
+        ret = s->mctrl;
+        MISC_DPRINTF("Read modem control %2.2x\n", ret);
+        break;
     case 0x1f00000:
-	MISC_DPRINTF("Read system control %2.2x\n", ret);
-	ret = s->sysctrl;
-	break;
+        MISC_DPRINTF("Read system control %2.2x\n", ret);
+        ret = s->sysctrl;
+        break;
     case 0xa000000:
-	MISC_DPRINTF("Read power management %2.2x\n", ret);
-	break;
+        MISC_DPRINTF("Read power management %2.2x\n", ret);
+        break;
     }
     return ret;
 }

Modified: trunk/src/host/qemu-neo1973/hw/slavio_serial.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_serial.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/slavio_serial.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -95,6 +95,7 @@
     uint8_t rx, tx, wregs[16], rregs[16];
     SERIOQueue queue;
     CharDriverState *chr;
+    int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
 } ChannelState;
 
 struct SerialState {
@@ -138,7 +139,7 @@
     int val;
 
     if (q->count == 0) {
-	return 0;
+        return 0;
     } else {
         val = q->data[q->rptr];
         if (++q->rptr == SERIO_QUEUE_SIZE)
@@ -147,17 +148,17 @@
     }
     SER_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
     if (q->count > 0)
-	serial_receive_byte(s, 0);
+        serial_receive_byte(s, 0);
     return val;
 }
 
 static int slavio_serial_update_irq_chn(ChannelState *s)
 {
     if ((s->wregs[1] & 1) && // interrupts enabled
-	(((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
-	 ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
-	  s->rxint == 1) || // rx ints enabled, pending
-	 ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
+        (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
+         ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
+          s->rxint == 1) || // rx ints enabled, pending
+         ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
         return 1;
     }
     return 0;
@@ -180,8 +181,8 @@
 
     s->reg = 0;
     for (i = 0; i < SERIAL_SIZE; i++) {
-	s->rregs[i] = 0;
-	s->wregs[i] = 0;
+        s->rregs[i] = 0;
+        s->wregs[i] = 0;
     }
     s->wregs[4] = 4;
     s->wregs[9] = 0xc0;
@@ -194,6 +195,7 @@
     s->rx = s->tx = 0;
     s->rxint = s->txint = 0;
     s->rxint_under_svc = s->txint_under_svc = 0;
+    s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0;
     clear_queue(s);
 }
 
@@ -365,82 +367,82 @@
     s = &serial->chn[channel];
     switch (saddr) {
     case 0:
-	SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff);
-	newreg = 0;
-	switch (s->reg) {
-	case 0:
-	    newreg = val & 7;
-	    val &= 0x38;
-	    switch (val) {
-	    case 8:
-		newreg |= 0x8;
-		break;
-	    case 0x28:
+        SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff);
+        newreg = 0;
+        switch (s->reg) {
+        case 0:
+            newreg = val & 7;
+            val &= 0x38;
+            switch (val) {
+            case 8:
+                newreg |= 0x8;
+                break;
+            case 0x28:
                 clr_txint(s);
-		break;
-	    case 0x38:
+                break;
+            case 0x38:
                 if (s->rxint_under_svc)
                     clr_rxint(s);
                 else if (s->txint_under_svc)
                     clr_txint(s);
-		break;
-	    default:
-		break;
-	    }
-	    break;
+                break;
+            default:
+                break;
+            }
+            break;
         case 1 ... 3:
         case 6 ... 8:
         case 10 ... 11:
         case 14 ... 15:
-	    s->wregs[s->reg] = val;
-	    break;
+            s->wregs[s->reg] = val;
+            break;
         case 4:
         case 5:
         case 12:
         case 13:
-	    s->wregs[s->reg] = val;
+            s->wregs[s->reg] = val;
             slavio_serial_update_parameters(s);
-	    break;
-	case 9:
-	    switch (val & 0xc0) {
-	    case 0:
-	    default:
-		break;
-	    case 0x40:
-		slavio_serial_reset_chn(&serial->chn[1]);
-		return;
-	    case 0x80:
-		slavio_serial_reset_chn(&serial->chn[0]);
-		return;
-	    case 0xc0:
-		slavio_serial_reset(serial);
-		return;
-	    }
-	    break;
-	default:
-	    break;
-	}
-	if (s->reg == 0)
-	    s->reg = newreg;
-	else
-	    s->reg = 0;
-	break;
+            break;
+        case 9:
+            switch (val & 0xc0) {
+            case 0:
+            default:
+                break;
+            case 0x40:
+                slavio_serial_reset_chn(&serial->chn[1]);
+                return;
+            case 0x80:
+                slavio_serial_reset_chn(&serial->chn[0]);
+                return;
+            case 0xc0:
+                slavio_serial_reset(serial);
+                return;
+            }
+            break;
+        default:
+            break;
+        }
+        if (s->reg == 0)
+            s->reg = newreg;
+        else
+            s->reg = 0;
+        break;
     case 1:
-	SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
+        SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
         s->tx = val;
-	if (s->wregs[5] & 8) { // tx enabled
-	    if (s->chr)
-		qemu_chr_write(s->chr, &s->tx, 1);
-	    else if (s->type == kbd) {
-		handle_kbd_command(s, val);
-	    }
-	}
+        if (s->wregs[5] & 8) { // tx enabled
+            if (s->chr)
+                qemu_chr_write(s->chr, &s->tx, 1);
+            else if (s->type == kbd) {
+                handle_kbd_command(s, val);
+            }
+        }
         s->rregs[0] |= 4; // Tx buffer empty
         s->rregs[1] |= 1; // All sent
         set_txint(s);
-	break;
+        break;
     default:
-	break;
+        break;
     }
 }
 
@@ -457,21 +459,21 @@
     s = &serial->chn[channel];
     switch (saddr) {
     case 0:
-	SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]);
-	ret = s->rregs[s->reg];
-	s->reg = 0;
-	return ret;
+        SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]);
+        ret = s->rregs[s->reg];
+        s->reg = 0;
+        return ret;
     case 1:
-	s->rregs[0] &= ~1;
+        s->rregs[0] &= ~1;
         clr_rxint(s);
-	if (s->type == kbd || s->type == mouse)
-	    ret = get_queue(s);
-	else
-	    ret = s->rx;
-	SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
-	return ret;
+        if (s->type == kbd || s->type == mouse)
+            ret = get_queue(s);
+        else
+            ret = s->rx;
+        SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
+        return ret;
     default:
-	break;
+        break;
     }
     return 0;
 }
@@ -482,10 +484,10 @@
     int ret;
 
     if (((s->wregs[3] & 1) == 0) // Rx not enabled
-	|| ((s->rregs[0] & 1) == 1)) // char already available
-	ret = 0;
+        || ((s->rregs[0] & 1) == 1)) // char already available
+        ret = 0;
     else
-	ret = 1;
+        ret = 1;
     //SER_DPRINTF("channel %c can receive %d\n", CHN_C(s), ret);
     return ret;
 }
@@ -582,7 +584,7 @@
 
     ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
     if (ret != 0)
-	return ret;
+        return ret;
     ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
     return ret;
 
@@ -605,13 +607,13 @@
     s->chn[1].chr = chr2;
 
     for (i = 0; i < 2; i++) {
-	s->chn[i].irq = irq;
-	s->chn[i].chn = 1 - i;
-	s->chn[i].type = ser;
-	if (s->chn[i].chr) {
-	    qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
+        s->chn[i].irq = irq;
+        s->chn[i].chn = 1 - i;
+        s->chn[i].type = ser;
+        if (s->chn[i].chr) {
+            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];
     s->chn[1].otherchn = &s->chn[0];
@@ -632,33 +634,85 @@
     0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
 };
 
+static const uint8_t e0_keycodes[128] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 76, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 109, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, 91, 0, 93, 0, 112,
+    113, 114, 94, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
 static void sunkbd_event(void *opaque, int ch)
 {
     ChannelState *s = opaque;
     int release = ch & 0x80;
 
-    ch = keycodes[ch & 0x7f];
-    KBD_DPRINTF("Keycode %d (%s)\n", ch, release? "release" : "press");
+    KBD_DPRINTF("Untranslated keycode %2.2x (%s)\n", ch, release? "release" : "press");
+    switch (ch) {
+    case 58: // Caps lock press
+        s->caps_lock_mode ^= 1;
+        if (s->caps_lock_mode == 2)
+            return; // Drop second press
+        break;
+    case 69: // Num lock press
+        s->num_lock_mode ^= 1;
+        if (s->num_lock_mode == 2)
+            return; // Drop second press
+        break;
+    case 186: // Caps lock release
+        s->caps_lock_mode ^= 2;
+        if (s->caps_lock_mode == 3)
+            return; // Drop first release
+        break;
+    case 197: // Num lock release
+        s->num_lock_mode ^= 2;
+        if (s->num_lock_mode == 3)
+            return; // Drop first release
+        break;
+    case 0xe0:
+        s->e0_mode = 1;
+        return;
+    default:
+        break;
+    }
+    if (s->e0_mode) {
+        s->e0_mode = 0;
+        ch = e0_keycodes[ch & 0x7f];
+    } else {
+        ch = keycodes[ch & 0x7f];
+    }
+    KBD_DPRINTF("Translated keycode %2.2x\n", ch);
     put_queue(s, ch | release);
 }
 
 static void handle_kbd_command(ChannelState *s, int val)
 {
     KBD_DPRINTF("Command %d\n", val);
+    if (s->led_mode) { // Ignore led byte
+        s->led_mode = 0;
+        return;
+    }
     switch (val) {
     case 1: // Reset, return type code
         clear_queue(s);
-	put_queue(s, 0xff);
-	put_queue(s, 4); // Type 4
-	break;
+        put_queue(s, 0xff);
+        put_queue(s, 4); // Type 4
+        put_queue(s, 0x7f);
+        break;
+    case 0xe: // Set leds
+        s->led_mode = 1;
+        break;
     case 7: // Query layout
     case 0xf:
         clear_queue(s);
-	put_queue(s, 0xfe);
-	put_queue(s, 19); // XXX, layout?
-	break;
+        put_queue(s, 0xfe);
+        put_queue(s, 0); // XXX, layout?
+        break;
     default:
-	break;
+        break;
     }
 }
 
@@ -714,9 +768,9 @@
     if (!s)
         return;
     for (i = 0; i < 2; i++) {
-	s->chn[i].irq = irq;
-	s->chn[i].chn = 1 - i;
-	s->chn[i].chr = NULL;
+        s->chn[i].irq = irq;
+        s->chn[i].chn = 1 - i;
+        s->chn[i].chr = NULL;
     }
     s->chn[0].otherchn = &s->chn[1];
     s->chn[1].otherchn = &s->chn[0];

Modified: trunk/src/host/qemu-neo1973/hw/slavio_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_timer.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/slavio_timer.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -47,18 +47,31 @@
  *
  */
 
+#define MAX_CPUS 16
+
 typedef struct SLAVIO_TIMERState {
     qemu_irq irq;
     ptimer_state *timer;
     uint32_t count, counthigh, reached;
     uint64_t limit;
-    int stopped;
-    int mode; // 0 = processor, 1 = user, 2 = system
+    // processor only
+    int running;
+    struct SLAVIO_TIMERState *master;
+    int slave_index;
+    // system only
+    struct SLAVIO_TIMERState *slave[MAX_CPUS];
+    uint32_t slave_mode;
 } SLAVIO_TIMERState;
 
 #define TIMER_MAXADDR 0x1f
-#define TIMER_SIZE (TIMER_MAXADDR + 1)
+#define SYS_TIMER_SIZE 0x14
+#define CPU_TIMER_SIZE 0x10
 
+static int slavio_timer_is_user(SLAVIO_TIMERState *s)
+{
+    return s->master && (s->master->slave_mode & (1 << s->slave_index));
+}
+
 // Update count, set irq, update expire_time
 // Convert from ptimer countdown units
 static void slavio_timer_get_out(SLAVIO_TIMERState *s)
@@ -79,9 +92,10 @@
 
     slavio_timer_get_out(s);
     DPRINTF("callback: count %x%08x\n", s->counthigh, s->count);
-    s->reached = 0x80000000;
-    if (s->mode != 1)
-	qemu_irq_raise(s->irq);
+    if (!slavio_timer_is_user(s)) {
+        s->reached = 0x80000000;
+        qemu_irq_raise(s->irq);
+    }
 }
 
 static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
@@ -92,37 +106,41 @@
     saddr = (addr & TIMER_MAXADDR) >> 2;
     switch (saddr) {
     case 0:
-	// read limit (system counter mode) or read most signifying
-	// part of counter (user mode)
-	if (s->mode != 1) {
-	    // clear irq
+        // read limit (system counter mode) or read most signifying
+        // part of counter (user mode)
+        if (slavio_timer_is_user(s)) {
+            // read user timer MSW
+            slavio_timer_get_out(s);
+            ret = s->counthigh;
+        } else {
+            // read limit
+            // clear irq
             qemu_irq_lower(s->irq);
-	    s->reached = 0;
+            s->reached = 0;
             ret = s->limit & 0x7fffffff;
-	}
-	else {
-	    slavio_timer_get_out(s);
-            ret = s->counthigh & 0x7fffffff;
-	}
+        }
         break;
     case 1:
-	// read counter and reached bit (system mode) or read lsbits
-	// of counter (user mode)
-	slavio_timer_get_out(s);
-	if (s->mode != 1)
-            ret = (s->count & 0x7fffffff) | s->reached;
-	else
-            ret = s->count;
+        // read counter and reached bit (system mode) or read lsbits
+        // of counter (user mode)
+        slavio_timer_get_out(s);
+        if (slavio_timer_is_user(s)) // read user timer LSW
+            ret = s->count & 0xffffffe00;
+        else // read limit
+            ret = (s->count & 0x7ffffe00) | s->reached;
         break;
     case 3:
-	// read start/stop status
-        ret = s->stopped;
+        // only available in processor counter/timer
+        // read start/stop status
+        ret = s->running;
         break;
     case 4:
-	// read user/system mode
-        ret = s->mode & 1;
+        // only available in system counter
+        // read user/system mode
+        ret = s->slave_mode;
         break;
     default:
+        DPRINTF("invalid read address " TARGET_FMT_plx "\n", addr);
         ret = 0;
         break;
     }
@@ -141,42 +159,75 @@
     saddr = (addr & TIMER_MAXADDR) >> 2;
     switch (saddr) {
     case 0:
-	// set limit, reset counter
-        reload = 1;
-	qemu_irq_lower(s->irq);
-	// fall through
+        if (slavio_timer_is_user(s)) {
+            // set user counter MSW, reset counter
+            qemu_irq_lower(s->irq);
+            s->limit = 0x7ffffffffffffe00ULL;
+            DPRINTF("processor %d user timer reset\n", s->slave_index);
+            ptimer_set_limit(s->timer, s->limit >> 9, 1);
+        } else {
+            // set limit, reset counter
+            qemu_irq_lower(s->irq);
+            s->limit = val & 0x7ffffe00ULL;
+            if (!s->limit)
+                s->limit = 0x7ffffe00ULL;
+            ptimer_set_limit(s->timer, s->limit >> 9, 1);
+        }
+        break;
+    case 1:
+        if (slavio_timer_is_user(s)) {
+            // set user counter LSW, reset counter
+            qemu_irq_lower(s->irq);
+            s->limit = 0x7ffffffffffffe00ULL;
+            DPRINTF("processor %d user timer reset\n", s->slave_index);
+            ptimer_set_limit(s->timer, s->limit >> 9, 1);
+        } else
+            DPRINTF("not user timer\n");
+        break;
     case 2:
-	// set limit without resetting counter
+        // set limit without resetting counter
         s->limit = val & 0x7ffffe00ULL;
         if (!s->limit)
             s->limit = 0x7ffffe00ULL;
         ptimer_set_limit(s->timer, s->limit >> 9, reload);
-	break;
+        break;
     case 3:
-	// start/stop user counter
-	if (s->mode == 1) {
-	    if (val & 1) {
+        if (slavio_timer_is_user(s)) {
+            // start/stop user counter
+            if ((val & 1) && !s->running) {
+                DPRINTF("processor %d user timer started\n", s->slave_index);
+                ptimer_run(s->timer, 0);
+                s->running = 1;
+            } else if (!(val & 1) && s->running) {
+                DPRINTF("processor %d user timer stopped\n", s->slave_index);
                 ptimer_stop(s->timer);
-		s->stopped = 1;
-	    }
-	    else {
-                ptimer_run(s->timer, 0);
-		s->stopped = 0;
-	    }
-	}
-	break;
+                s->running = 0;
+            }
+        }
+        break;
     case 4:
-	// bit 0: user (1) or system (0) counter mode
-	if (s->mode == 0 || s->mode == 1)
-	    s->mode = val & 1;
-        if (s->mode == 1) {
-            qemu_irq_lower(s->irq);
-            s->limit = -1ULL;
-        }
-        ptimer_set_limit(s->timer, s->limit >> 9, 1);
-	break;
+        if (s->master == NULL) {
+            unsigned int i;
+
+            for (i = 0; i < MAX_CPUS; i++) {
+                if (val & (1 << i)) {
+                    qemu_irq_lower(s->slave[i]->irq);
+                    s->slave[i]->limit = -1ULL;
+                }
+                if ((val & (1 << i)) != (s->slave_mode & (1 << i))) {
+                    ptimer_stop(s->slave[i]->timer);
+                    ptimer_set_limit(s->slave[i]->timer, s->slave[i]->limit >> 9, 1);
+                    DPRINTF("processor %d timer changed\n", s->slave[i]->slave_index);
+                    ptimer_run(s->slave[i]->timer, 0);
+                }
+            }
+            s->slave_mode = val & ((1 << MAX_CPUS) - 1);
+        } else
+            DPRINTF("not system timer\n");
+        break;
     default:
-	break;
+        DPRINTF("invalid write address " TARGET_FMT_plx "\n", addr);
+        break;
     }
 }
 
@@ -201,8 +252,8 @@
     qemu_put_be32s(f, &s->counthigh);
     qemu_put_be32(f, 0); // Was irq
     qemu_put_be32s(f, &s->reached);
-    qemu_put_be32s(f, &s->stopped);
-    qemu_put_be32s(f, &s->mode);
+    qemu_put_be32s(f, &s->running);
+    qemu_put_be32s(f, 0); // Was mode
     qemu_put_ptimer(f, s->timer);
 }
 
@@ -219,8 +270,8 @@
     qemu_get_be32s(f, &s->counthigh);
     qemu_get_be32s(f, &tmp); // Was irq
     qemu_get_be32s(f, &s->reached);
-    qemu_get_be32s(f, &s->stopped);
-    qemu_get_be32s(f, &s->mode);
+    qemu_get_be32s(f, &s->running);
+    qemu_get_be32s(f, &tmp); // Was mode
     qemu_get_ptimer(f, s->timer);
 
     return 0;
@@ -230,17 +281,22 @@
 {
     SLAVIO_TIMERState *s = opaque;
 
-    s->limit = 0x7ffffe00ULL;
+    if (slavio_timer_is_user(s))
+        s->limit = 0x7ffffffffffffe00ULL;
+    else
+        s->limit = 0x7ffffe00ULL;
     s->count = 0;
     s->reached = 0;
-    s->mode &= 2;
     ptimer_set_limit(s->timer, s->limit >> 9, 1);
     ptimer_run(s->timer, 0);
-    s->stopped = 1;
+    s->running = 1;
     qemu_irq_lower(s->irq);
 }
 
-void slavio_timer_init(target_phys_addr_t addr, qemu_irq irq, int mode)
+static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr,
+                                            qemu_irq irq,
+                                            SLAVIO_TIMERState *master,
+                                            int slave_index)
 {
     int slavio_timer_io_memory;
     SLAVIO_TIMERState *s;
@@ -248,17 +304,38 @@
 
     s = qemu_mallocz(sizeof(SLAVIO_TIMERState));
     if (!s)
-        return;
+        return s;
     s->irq = irq;
-    s->mode = mode;
+    s->master = master;
+    s->slave_index = slave_index;
     bh = qemu_bh_new(slavio_timer_irq, s);
     s->timer = ptimer_init(bh);
     ptimer_set_period(s->timer, 500ULL);
 
     slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
-						    slavio_timer_mem_write, s);
-    cpu_register_physical_memory(addr, TIMER_SIZE, slavio_timer_io_memory);
+                                                    slavio_timer_mem_write, s);
+    if (master)
+        cpu_register_physical_memory(addr, CPU_TIMER_SIZE, slavio_timer_io_memory);
+    else
+        cpu_register_physical_memory(addr, SYS_TIMER_SIZE, slavio_timer_io_memory);
     register_savevm("slavio_timer", addr, 2, slavio_timer_save, slavio_timer_load, s);
     qemu_register_reset(slavio_timer_reset, s);
     slavio_timer_reset(s);
+
+    return s;
 }
+
+void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq,
+                           qemu_irq *cpu_irqs)
+{
+    SLAVIO_TIMERState *master;
+    unsigned int i;
+
+    master = slavio_timer_init(base + 0x10000ULL, master_irq, NULL, 0);
+
+    for (i = 0; i < MAX_CPUS; i++) {
+        master->slave[i] = slavio_timer_init(base + (target_phys_addr_t)
+                                             (i * TARGET_PAGE_SIZE),
+                                             cpu_irqs[i], master, i);
+    }
+}

Modified: trunk/src/host/qemu-neo1973/hw/spitz.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/spitz.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/spitz.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -194,8 +194,8 @@
     { 0x0f, 0x10, 0x12, 0x14, 0x22, 0x16, 0x24, 0x25,  -1 ,  -1 ,  -1  },
     { 0x3c, 0x11, 0x1f, 0x21, 0x2f, 0x23, 0x32, 0x26,  -1 , 0x36,  -1  },
     { 0x3b, 0x1e, 0x20, 0x2e, 0x30, 0x31, 0x34,  -1 , 0x1c, 0x2a,  -1  },
-    { 0x44, 0x2c, 0x2d, 0x0c, 0x39, 0x33,  -1 , 0x48,  -1 ,  -1 , 0x3d },
-    { 0x37, 0x38,  -1 , 0x45, 0x57, 0x58, 0x4b, 0x50, 0x4d,  -1 ,  -1  },
+    { 0x44, 0x2c, 0x2d, 0x0c, 0x39, 0x33,  -1 , 0x48,  -1 ,  -1 , 0x38 },
+    { 0x37, 0x3d,  -1 , 0x45, 0x57, 0x58, 0x4b, 0x50, 0x4d,  -1 ,  -1  },
     { 0x52, 0x43, 0x01, 0x47, 0x49,  -1 ,  -1 ,  -1 ,  -1 ,  -1 ,  -1  },
 };
 
@@ -415,13 +415,17 @@
     s->pre_map[0x0d | SHIFT	] = 0x13 | FN;		/* plus */
     s->pre_map[0x1a		] = 0x14 | FN;		/* bracketleft */
     s->pre_map[0x1b		] = 0x15 | FN;		/* bracketright */
+    s->pre_map[0x1a | SHIFT	] = 0x16 | FN;		/* braceleft */
+    s->pre_map[0x1b | SHIFT	] = 0x17 | FN;		/* braceright */
     s->pre_map[0x27		] = 0x22 | FN;		/* semicolon */
     s->pre_map[0x27 | SHIFT	] = 0x23 | FN;		/* colon */
     s->pre_map[0x09 | SHIFT	] = 0x24 | FN;		/* asterisk */
     s->pre_map[0x2b		] = 0x25 | FN;		/* backslash */
     s->pre_map[0x2b | SHIFT	] = 0x26 | FN;		/* bar */
     s->pre_map[0x0c | SHIFT	] = 0x30 | FN;		/* underscore */
+    s->pre_map[0x33 | SHIFT	] = 0x33 | FN;		/* less */
     s->pre_map[0x35		] = 0x33 | SHIFT;	/* slash */
+    s->pre_map[0x34 | SHIFT	] = 0x34 | FN;		/* greater */
     s->pre_map[0x35 | SHIFT	] = 0x34 | SHIFT;	/* question */
     s->pre_map[0x49		] = 0x48 | FN;		/* Page_Up */
     s->pre_map[0x51		] = 0x50 | FN;		/* Page_Down */

Modified: trunk/src/host/qemu-neo1973/hw/sun4m.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4m.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sun4m.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -49,9 +49,10 @@
 #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 PROM_SIZE_MAX        (512 * 1024)
+#define PROM_PADDR           0xff0000000ULL
+#define PROM_VADDR           0xffd00000
+#define PROM_FILENAME        "openbios-sparc32"
 
 #define MAX_CPUS 16
 #define MAX_PILS 16
@@ -157,9 +158,9 @@
 extern int nographic;
 
 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 boot_device, uint32_t RAM_size,
+                       uint32_t kernel_size,
+                       int width, int height, int depth,
                        int machine_id)
 {
     unsigned char tmp = 0;
@@ -178,8 +179,8 @@
     nvram_set_lword(nvram,  0x38, KERNEL_LOAD_ADDR);
     nvram_set_lword(nvram,  0x3C, kernel_size);
     if (cmdline) {
-	strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
-	nvram_set_lword(nvram,  0x40, CMDLINE_ADDR);
+        strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
+        nvram_set_lword(nvram,  0x40, CMDLINE_ADDR);
         nvram_set_lword(nvram,  0x44, strlen(cmdline));
     }
     // initrd_image, initrd_size passed differently
@@ -326,7 +327,7 @@
 
     for(i = 0; i < smp_cpus; i++) {
         env = cpu_init();
-        cpu_sparc_register(env, def);
+        cpu_sparc_register(env, def, i);
         envs[i] = env;
         if (i == 0) {
             qemu_register_reset(main_cpu_reset, env);
@@ -379,13 +380,10 @@
 
     nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0,
                         hwdef->nvram_size, 8);
-    for (i = 0; i < MAX_CPUS; i++) {
-        slavio_timer_init(hwdef->counter_base +
-                          (target_phys_addr_t)(i * TARGET_PAGE_SIZE),
-                           slavio_cpu_irq[i], 0);
-    }
-    slavio_timer_init(hwdef->counter_base + 0x10000ULL,
-                      slavio_irq[hwdef->clock1_irq], 2);
+
+    slavio_timer_init_all(hwdef->counter_base, slavio_irq[hwdef->clock1_irq],
+                          slavio_cpu_irq);
+
     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
@@ -425,29 +423,34 @@
     linux_boot = (kernel_filename != NULL);
 
     prom_offset = RAM_size + vram_size;
-    cpu_register_physical_memory(PROM_ADDR,
+    cpu_register_physical_memory(PROM_PADDR,
                                  (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, NULL, NULL);
-    if (ret < 0) {
-	fprintf(stderr, "qemu: could not load prom '%s'\n",
-		buf);
-	exit(1);
+    if (bios_name == NULL)
+        bios_name = PROM_FILENAME;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
+    ret = load_elf(buf, PROM_PADDR - PROM_VADDR, NULL, NULL, NULL);
+    if (ret < 0 || ret > PROM_SIZE_MAX)
+        ret = load_image(buf, phys_ram_base + prom_offset);
+    if (ret < 0 || ret > PROM_SIZE_MAX) {
+        fprintf(stderr, "qemu: could not load prom '%s'\n",
+                buf);
+        exit(1);
     }
 
     kernel_size = 0;
     if (linux_boot) {
-        kernel_size = load_elf(kernel_filename, -0xf0000000, NULL, NULL, NULL);
+        kernel_size = load_elf(kernel_filename, -0xf0000000ULL, NULL, NULL,
+                               NULL);
         if (kernel_size < 0)
-	    kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
-	if (kernel_size < 0)
-	    kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
+            kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
+        if (kernel_size < 0)
+            kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
         if (kernel_size < 0) {
             fprintf(stderr, "qemu: could not load kernel '%s'\n",
                     kernel_filename);
-	    exit(1);
+            exit(1);
         }
 
         /* load initrd */
@@ -461,14 +464,14 @@
             }
         }
         if (initrd_size > 0) {
-	    for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
-		if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
-		    == 0x48647253) { // HdrS
-		    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
-		    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
-		    break;
-		}
-	    }
+            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
+                if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
+                    == 0x48647253) { // HdrS
+                    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
+                    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
+                    break;
+                }
+            }
         }
     }
     nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
@@ -506,8 +509,8 @@
         .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,
+            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 */
@@ -539,8 +542,8 @@
         .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,
+            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,
         },
     },
 };
@@ -588,7 +591,7 @@
         cpu_model = "TI SuperSparc II";
     sun4m_common_init(RAM_size, boot_device, ds, kernel_filename,
                       kernel_cmdline, initrd_filename, cpu_model,
-                      1, PROM_ADDR); // XXX prom overlap, actually first 4GB ok
+                      1, 0xffffffff); // XXX actually first 62GB ok
 }
 
 QEMUMachine ss5_machine = {

Modified: trunk/src/host/qemu-neo1973/hw/sun4u.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4u.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/sun4u.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -28,12 +28,12 @@
 #define CMDLINE_ADDR         0x003ff000
 #define INITRD_LOAD_ADDR     0x00300000
 #define PROM_SIZE_MAX        (512 * 1024)
-#define PROM_ADDR	     0x1fff0000000ULL
-#define PROM_VADDR	     0x000ffd00000ULL
+#define PROM_ADDR            0x1fff0000000ULL
+#define PROM_VADDR           0x000ffd00000ULL
 #define APB_SPECIAL_BASE     0x1fe00000000ULL
-#define APB_MEM_BASE	     0x1ff00000000ULL
-#define VGA_BASE	     (APB_MEM_BASE + 0x400000ULL)
-#define PROM_FILENAME	     "openbios-sparc64"
+#define APB_MEM_BASE         0x1ff00000000ULL
+#define VGA_BASE             (APB_MEM_BASE + 0x400000ULL)
+#define PROM_FILENAME        "openbios-sparc64"
 #define NVRAM_SIZE           0x2000
 
 /* TSC handling */
@@ -162,10 +162,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;
@@ -358,7 +358,7 @@
         exit(1);
     }
     env = cpu_init();
-    cpu_sparc_register(env, def);
+    cpu_sparc_register(env, def, 0);
     bh = qemu_bh_new(tick_irq, env);
     env->tick = ptimer_init(bh);
     ptimer_set_period(env->tick, 1ULL);
@@ -382,12 +382,14 @@
                                  (PROM_SIZE_MAX + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK,
                                  prom_offset | IO_MEM_ROM);
 
-    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
+    if (bios_name == NULL)
+        bios_name = PROM_FILENAME;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
     ret = load_elf(buf, PROM_ADDR - PROM_VADDR, NULL, NULL, NULL);
     if (ret < 0) {
-	fprintf(stderr, "qemu: could not load prom '%s'\n",
-		buf);
-	exit(1);
+        fprintf(stderr, "qemu: could not load prom '%s'\n",
+                buf);
+        exit(1);
     }
 
     kernel_size = 0;
@@ -396,13 +398,13 @@
         /* XXX: put correct offset */
         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)
-	    kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
+            kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
+        if (kernel_size < 0)
+            kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
         if (kernel_size < 0) {
             fprintf(stderr, "qemu: could not load kernel '%s'\n",
                     kernel_filename);
-	    exit(1);
+            exit(1);
         }
 
         /* load initrd */
@@ -415,14 +417,14 @@
             }
         }
         if (initrd_size > 0) {
-	    for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
-		if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
-		    == 0x48647253) { // HdrS
-		    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
-		    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
-		    break;
-		}
-	    }
+            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
+                if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
+                    == 0x48647253) { // HdrS
+                    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
+                    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
+                    break;
+                }
+            }
         }
     }
     pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, NULL);
@@ -444,7 +446,7 @@
     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], -1);
+        pci_nic_init(pci_bus, &nd_table[i], -1);
     }
 
     irq = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, 32);

Modified: trunk/src/host/qemu-neo1973/hw/tcx.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/tcx.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/tcx.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -84,39 +84,39 @@
 }
 
 static void tcx_draw_line32(TCXState *s1, uint8_t *d,
-			    const uint8_t *s, int width)
+                            const uint8_t *s, int width)
 {
     int x;
     uint8_t val;
     uint32_t *p = (uint32_t *)d;
 
     for(x = 0; x < width; x++) {
-	val = *s++;
+        val = *s++;
         *p++ = s1->palette[val];
     }
 }
 
 static void tcx_draw_line16(TCXState *s1, uint8_t *d,
-			    const uint8_t *s, int width)
+                            const uint8_t *s, int width)
 {
     int x;
     uint8_t val;
     uint16_t *p = (uint16_t *)d;
 
     for(x = 0; x < width; x++) {
-	val = *s++;
+        val = *s++;
         *p++ = s1->palette[val];
     }
 }
 
 static void tcx_draw_line8(TCXState *s1, uint8_t *d,
-			   const uint8_t *s, int width)
+                           const uint8_t *s, int width)
 {
     int x;
     uint8_t val;
 
     for(x = 0; x < width; x++) {
-	val = *s++;
+        val = *s++;
         *d++ = s1->palette[val];
     }
 }
@@ -183,7 +183,7 @@
     void (*f)(TCXState *s1, uint8_t *dst, const uint8_t *src, int width);
 
     if (ts->ds->depth == 0)
-	return;
+        return;
     page = ts->vram_offset;
     y_start = -1;
     page_min = 0xffffffff;
@@ -195,55 +195,55 @@
 
     switch (ts->ds->depth) {
     case 32:
-	f = tcx_draw_line32;
-	break;
+        f = tcx_draw_line32;
+        break;
     case 15:
     case 16:
-	f = tcx_draw_line16;
-	break;
+        f = tcx_draw_line16;
+        break;
     default:
     case 8:
-	f = tcx_draw_line8;
-	break;
+        f = tcx_draw_line8;
+        break;
     case 0:
-	return;
+        return;
     }
 
     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
-	if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {
-	    if (y_start < 0)
+        if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {
+            if (y_start < 0)
                 y_start = y;
             if (page < page_min)
                 page_min = page;
             if (page > page_max)
                 page_max = page;
-	    f(ts, d, s, ts->width);
-	    d += dd;
-	    s += ds;
-	    f(ts, d, s, ts->width);
-	    d += dd;
-	    s += ds;
-	    f(ts, d, s, ts->width);
-	    d += dd;
-	    s += ds;
-	    f(ts, d, s, ts->width);
-	    d += dd;
-	    s += ds;
-	} else {
+            f(ts, d, s, ts->width);
+            d += dd;
+            s += ds;
+            f(ts, d, s, ts->width);
+            d += dd;
+            s += ds;
+            f(ts, d, s, ts->width);
+            d += dd;
+            s += ds;
+            f(ts, d, s, ts->width);
+            d += dd;
+            s += 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;
-	}
+            d += dd * 4;
+            s += ds * 4;
+        }
     }
     if (y_start >= 0) {
-	/* flush to display */
-	dpy_update(ts->ds, 0, y_start,
-		   ts->width, y - y_start);
+        /* flush to display */
+        dpy_update(ts->ds, 0, y_start,
+                   ts->width, y - y_start);
     }
     /* reset modified pages */
     if (page_min <= page_max) {
@@ -334,7 +334,7 @@
     int i;
 
     for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) {
-	cpu_physical_memory_set_dirty(s->vram_offset + i);
+        cpu_physical_memory_set_dirty(s->vram_offset + i);
     }
 }
 
@@ -424,32 +424,32 @@
     saddr = (addr & (TCX_DAC_NREGS - 1)) >> 2;
     switch (saddr) {
     case 0:
-	s->dac_index = val >> 24;
-	s->dac_state = 0;
-	break;
+        s->dac_index = val >> 24;
+        s->dac_state = 0;
+        break;
     case 1:
-	switch (s->dac_state) {
-	case 0:
-	    s->r[s->dac_index] = val >> 24;
+        switch (s->dac_state) {
+        case 0:
+            s->r[s->dac_index] = val >> 24;
             update_palette_entries(s, s->dac_index, s->dac_index + 1);
-	    s->dac_state++;
-	    break;
-	case 1:
-	    s->g[s->dac_index] = val >> 24;
+            s->dac_state++;
+            break;
+        case 1:
+            s->g[s->dac_index] = val >> 24;
             update_palette_entries(s, s->dac_index, s->dac_index + 1);
-	    s->dac_state++;
-	    break;
-	case 2:
-	    s->b[s->dac_index] = val >> 24;
+            s->dac_state++;
+            break;
+        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;
-	}
-	break;
+        default:
+            s->dac_state = 0;
+            break;
+        }
+        break;
     default:
-	break;
+        break;
     }
     return;
 }

Added: trunk/src/host/qemu-neo1973/hw/tsc210x.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/tsc210x.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/tsc210x.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,848 @@
+/*
+ * TI TSC2102 (touchscreen/sensors/audio controller) controller.
+ *
+ * Copyright (c) 2006 Andrzej Zaborowski  <balrog at zabor.org>
+ *
+ * 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
+ */
+
+#include "vl.h"
+
+#define TSC_DATA_REGISTERS_PAGE		0x0
+#define TSC_CONTROL_REGISTERS_PAGE	0x1
+#define TSC_AUDIO_REGISTERS_PAGE	0x2
+
+#define TSC_VERBOSE
+
+#define TSC_CUT_RESOLUTION(value, p)	((value) >> (16 - resolution[p]))
+
+struct tsc210x_state_s {
+    qemu_irq pint;
+    QEMUTimer *timer;
+    struct uwire_slave_s chip;
+
+    int x, y;
+    int pressure;
+
+    int state, page, offset, irq;
+    uint16_t command, dav;
+
+    int busy;
+    int enabled;
+    int host_mode;
+    int function;
+    int nextfunction;
+    int precision;
+    int nextprecision;
+    int filter;
+    int pin_func;
+    int ref;
+    int timing;
+    int noise;
+
+    uint16_t audio_ctrl1;
+    uint16_t audio_ctrl2;
+    uint16_t audio_ctrl3;
+    uint16_t pll[2];
+    uint16_t volume;
+    int64_t volume_change;
+    int softstep;
+    uint16_t dac_power;
+    int64_t powerdown;
+    uint16_t filter_data[0x14];
+};
+
+static const int resolution[4] = { 12, 8, 10, 12 };
+
+#define TSC_MODE_NO_SCAN	0x0
+#define TSC_MODE_XY_SCAN	0x1
+#define TSC_MODE_XYZ_SCAN	0x2
+#define TSC_MODE_X		0x3
+#define TSC_MODE_Y		0x4
+#define TSC_MODE_Z		0x5
+#define TSC_MODE_BAT1		0x6
+#define TSC_MODE_BAT2		0x7
+#define TSC_MODE_AUX		0x8
+#define TSC_MODE_AUX_SCAN	0x9
+#define TSC_MODE_TEMP1		0xa
+#define TSC_MODE_PORT_SCAN	0xb
+#define TSC_MODE_TEMP2		0xc
+#define TSC_MODE_XX_DRV		0xd
+#define TSC_MODE_YY_DRV		0xe
+#define TSC_MODE_YX_DRV		0xf
+
+static const uint16_t mode_regs[16] = {
+    0x0000,	/* No scan */
+    0x0600,	/* X, Y scan */
+    0x0780,	/* X, Y, Z scan */
+    0x0400,	/* X */
+    0x0200,	/* Y */
+    0x0180,	/* Z */
+    0x0040,	/* BAT1 */
+    0x0030,	/* BAT2 */
+    0x0010,	/* AUX */
+    0x0010,	/* AUX scan */
+    0x0004,	/* TEMP1 */
+    0x0070,	/* Port scan */
+    0x0002,	/* TEMP2 */
+    0x0000,	/* X+, X- drivers */
+    0x0000,	/* Y+, Y- drivers */
+    0x0000,	/* Y+, X- drivers */
+};
+
+/*
+ * Convert screen coordinates to arbitrary values that the
+ * touchscreen in my Palm Tungsten E device returns.
+ * This shouldn't really matter (because the guest system
+ * should calibrate the touchscreen anyway), but let's
+ * imitate some real hardware.
+ */
+#define X_TRANSFORM(value)		\
+    ((3850 - ((int) (value) * (3850 - 250) / 32768)) << 4)
+#define Y_TRANSFORM(value)		\
+    ((150 + ((int) (value) * (3037 - 150) / 32768)) << 4)
+#define Z1_TRANSFORM(s)			\
+    ((400 - (s)->x + ((s)->pressure << 9)) << 4)
+#define Z2_TRANSFORM(s)			\
+    ((4000 + (s)->y - ((s)->pressure << 10)) << 4)
+#define BAT1_VAL			0x8660
+#define BAT2_VAL			0x0000
+#define AUX1_VAL			0x35c0
+#define AUX2_VAL			0xffff
+#define TEMP1_VAL			0x8c70
+#define TEMP2_VAL			0xa5b0
+
+#define TSC_POWEROFF_DELAY		50
+#define TSC_SOFTSTEP_DELAY		50
+
+static void tsc210x_reset(struct tsc210x_state_s *s)
+{
+    s->state = 0;
+    s->pin_func = 2;
+    s->enabled = 0;
+    s->busy = 0;
+    s->nextfunction = 0;
+    s->ref = 0;
+    s->timing = 0;
+    s->irq = 0;
+    s->dav = 0;
+
+    s->audio_ctrl1 = 0x0000;
+    s->audio_ctrl2 = 0x4410;
+    s->audio_ctrl3 = 0x0000;
+    s->pll[0] = 0x1004;
+    s->pll[1] = 0x0000;
+    s->volume = 0xffff;
+    s->dac_power = 0x8540;
+    s->softstep = 1;
+    s->volume_change = 0;
+    s->powerdown = 0;
+    s->filter_data[0x00] = 0x6be3;
+    s->filter_data[0x01] = 0x9666;
+    s->filter_data[0x02] = 0x675d;
+    s->filter_data[0x03] = 0x6be3;
+    s->filter_data[0x04] = 0x9666;
+    s->filter_data[0x05] = 0x675d;
+    s->filter_data[0x06] = 0x7d83;
+    s->filter_data[0x07] = 0x84ee;
+    s->filter_data[0x08] = 0x7d83;
+    s->filter_data[0x09] = 0x84ee;
+    s->filter_data[0x0a] = 0x6be3;
+    s->filter_data[0x0b] = 0x9666;
+    s->filter_data[0x0c] = 0x675d;
+    s->filter_data[0x0d] = 0x6be3;
+    s->filter_data[0x0e] = 0x9666;
+    s->filter_data[0x0f] = 0x675d;
+    s->filter_data[0x10] = 0x7d83;
+    s->filter_data[0x11] = 0x84ee;
+    s->filter_data[0x12] = 0x7d83;
+    s->filter_data[0x13] = 0x84ee;
+
+    qemu_set_irq(s->pint, s->irq);
+}
+
+static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg)
+{
+    switch (reg) {
+    case 0x00:	/* X */
+        s->dav &= 0xfbff;
+        return TSC_CUT_RESOLUTION(X_TRANSFORM(s->x), s->precision) +
+                (s->noise & 3);
+
+    case 0x01:	/* Y */
+        s->noise ++;
+        s->dav &= 0xfdff;
+        return TSC_CUT_RESOLUTION(Y_TRANSFORM(s->y), s->precision) ^
+                (s->noise & 3);
+
+    case 0x02:	/* Z1 */
+        s->dav &= 0xfeff;
+        return TSC_CUT_RESOLUTION(Z1_TRANSFORM(s), s->precision) -
+                (s->noise & 3);
+
+    case 0x03:	/* Z2 */
+        s->dav &= 0xff7f;
+        return TSC_CUT_RESOLUTION(Z2_TRANSFORM(s), s->precision) |
+                (s->noise & 3);
+
+    case 0x04:	/* KPData */
+        return 0xffff;
+
+    case 0x05:	/* BAT1 */
+        s->dav &= 0xffbf;
+        return TSC_CUT_RESOLUTION(BAT1_VAL, s->precision);
+
+    case 0x06:	/* BAT2 */
+        s->dav &= 0xffdf;
+        return TSC_CUT_RESOLUTION(BAT2_VAL, s->precision);
+
+    case 0x07:	/* AUX1 */
+        s->dav &= 0xffef;
+        return TSC_CUT_RESOLUTION(AUX1_VAL, s->precision);
+
+    case 0x08:	/* AUX2 */
+        s->dav &= 0xfff7;
+        return 0xffff;
+
+    case 0x09:	/* TEMP1 */
+        s->dav &= 0xfffb;
+        return TSC_CUT_RESOLUTION(TEMP1_VAL, s->precision);
+
+    case 0x0a:	/* TEMP2 */
+        s->dav &= 0xfffd;
+        return TSC_CUT_RESOLUTION(TEMP2_VAL, s->precision);
+
+    case 0x0b:	/* DAC */
+        s->dav &= 0xfffe;
+        return 0xffff;
+
+    default:
+#ifdef TSC_VERBOSE
+        fprintf(stderr, "tsc2102_data_register_read: "
+                        "no such register: 0x%02x\n", reg);
+#endif
+        return 0xffff;
+    }
+}
+
+static uint16_t tsc2102_control_register_read(
+                struct tsc210x_state_s *s, int reg)
+{
+    switch (reg) {
+    case 0x00:	/* TSC ADC */
+        return (s->pressure << 15) | ((!s->busy) << 14) |
+                (s->nextfunction << 10) | (s->nextprecision << 8) | s->filter; 
+
+    case 0x01:	/* Status */
+        return (s->pin_func << 14) | ((!s->enabled) << 13) |
+                (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav;
+
+    case 0x03:	/* Reference */
+        return s->ref;
+
+    case 0x04:	/* Reset */
+        return 0xffff;
+
+    case 0x05:	/* Configuration */
+        return s->timing;
+
+    default:
+#ifdef TSC_VERBOSE
+        fprintf(stderr, "tsc2102_control_register_read: "
+                        "no such register: 0x%02x\n", reg);
+#endif
+        return 0xffff;
+    }
+}
+
+static uint16_t tsc2102_audio_register_read(struct tsc210x_state_s *s, int reg)
+{
+    int l_ch, r_ch;
+    uint16_t val;
+
+    switch (reg) {
+    case 0x00:	/* Audio Control 1 */
+        return s->audio_ctrl1;
+
+    case 0x01:
+        return 0xff00;
+
+    case 0x02:	/* DAC Volume Control */
+        return s->volume;
+
+    case 0x03:
+        return 0x8b00;
+
+    case 0x04:	/* Audio Control 2 */
+        l_ch = 1;
+        r_ch = 1;
+        if (s->softstep && !(s->dac_power & (1 << 10))) {
+            l_ch = (qemu_get_clock(vm_clock) >
+                            s->volume_change + TSC_SOFTSTEP_DELAY);
+            r_ch = (qemu_get_clock(vm_clock) >
+                            s->volume_change + TSC_SOFTSTEP_DELAY);
+        }
+
+        return s->audio_ctrl2 | (l_ch << 3) | (r_ch << 2);
+
+    case 0x05:	/* Stereo DAC Power Control */
+        return 0x2aa0 | s->dac_power |
+                (((s->dac_power & (1 << 10)) &&
+                  (qemu_get_clock(vm_clock) >
+                   s->powerdown + TSC_POWEROFF_DELAY)) << 6);
+
+    case 0x06:	/* Audio Control 3 */
+        val = s->audio_ctrl3 | 0x0001;
+        s->audio_ctrl3 &= 0xff3f;
+        return val;
+
+    case 0x07:	/* LCH_BASS_BOOST_N0 */
+    case 0x08:	/* LCH_BASS_BOOST_N1 */
+    case 0x09:	/* LCH_BASS_BOOST_N2 */
+    case 0x0a:	/* LCH_BASS_BOOST_N3 */
+    case 0x0b:	/* LCH_BASS_BOOST_N4 */
+    case 0x0c:	/* LCH_BASS_BOOST_N5 */
+    case 0x0d:	/* LCH_BASS_BOOST_D1 */
+    case 0x0e:	/* LCH_BASS_BOOST_D2 */
+    case 0x0f:	/* LCH_BASS_BOOST_D4 */
+    case 0x10:	/* LCH_BASS_BOOST_D5 */
+    case 0x11:	/* RCH_BASS_BOOST_N0 */
+    case 0x12:	/* RCH_BASS_BOOST_N1 */
+    case 0x13:	/* RCH_BASS_BOOST_N2 */
+    case 0x14:	/* RCH_BASS_BOOST_N3 */
+    case 0x15:	/* RCH_BASS_BOOST_N4 */
+    case 0x16:	/* RCH_BASS_BOOST_N5 */
+    case 0x17:	/* RCH_BASS_BOOST_D1 */
+    case 0x18:	/* RCH_BASS_BOOST_D2 */
+    case 0x19:	/* RCH_BASS_BOOST_D4 */
+    case 0x1a:	/* RCH_BASS_BOOST_D5 */
+        return s->filter_data[reg - 0x07];
+
+    case 0x1b:	/* PLL Programmability 1 */
+        return s->pll[0];
+
+    case 0x1c:	/* PLL Programmability 2 */
+        return s->pll[1];
+
+    case 0x1d:	/* Audio Control 4 */
+        return (!s->softstep) << 14;
+
+    default:
+#ifdef TSC_VERBOSE
+        fprintf(stderr, "tsc2102_audio_register_read: "
+                        "no such register: 0x%02x\n", reg);
+#endif
+        return 0xffff;
+    }
+}
+
+static void tsc2102_data_register_write(
+                struct tsc210x_state_s *s, int reg, uint16_t value)
+{
+    switch (reg) {
+    case 0x00:	/* X */
+    case 0x01:	/* Y */
+    case 0x02:	/* Z1 */
+    case 0x03:	/* Z2 */
+    case 0x05:	/* BAT1 */
+    case 0x06:	/* BAT2 */
+    case 0x07:	/* AUX1 */
+    case 0x08:	/* AUX2 */
+    case 0x09:	/* TEMP1 */
+    case 0x0a:	/* TEMP2 */
+        return;
+
+    default:
+#ifdef TSC_VERBOSE
+        fprintf(stderr, "tsc2102_data_register_write: "
+                        "no such register: 0x%02x\n", reg);
+#endif
+    }
+}
+
+static void tsc2102_control_register_write(
+                struct tsc210x_state_s *s, int reg, uint16_t value)
+{
+    switch (reg) {
+    case 0x00:	/* TSC ADC */
+        s->host_mode = value >> 15;
+        s->enabled = !(value & 0x4000);
+        if (s->busy && !s->enabled)
+            qemu_del_timer(s->timer);
+        s->busy &= s->enabled;
+        s->nextfunction = (value >> 10) & 0xf;
+        s->nextprecision = (value >> 8) & 3;
+        s->filter = value & 0xff;
+        return;
+
+    case 0x01:	/* Status */
+        s->pin_func = value >> 14;
+        return;
+
+    case 0x03:	/* Reference */
+        s->ref = value & 0x1f;
+        return;
+
+    case 0x04:	/* Reset */
+        if (value == 0xbb00) {
+            if (s->busy)
+                qemu_del_timer(s->timer);
+            tsc210x_reset(s);
+#ifdef TSC_VERBOSE
+        } else {
+            fprintf(stderr, "tsc2102_control_register_write: "
+                            "wrong value written into RESET\n");
+#endif
+        }
+        return;
+
+    case 0x05:	/* Configuration */
+        s->timing = value & 0x3f;
+#ifdef TSC_VERBOSE
+        if (value & ~0x3f)
+            fprintf(stderr, "tsc2102_control_register_write: "
+                            "wrong value written into CONFIG\n");
+#endif
+        return;
+
+    default:
+#ifdef TSC_VERBOSE
+        fprintf(stderr, "tsc2102_control_register_write: "
+                        "no such register: 0x%02x\n", reg);
+#endif
+    }
+}
+
+static void tsc2102_audio_register_write(
+                struct tsc210x_state_s *s, int reg, uint16_t value)
+{
+    switch (reg) {
+    case 0x00:	/* Audio Control 1 */
+        s->audio_ctrl1 = value & 0x0f3f;
+#ifdef TSC_VERBOSE
+        if ((value & ~0x0f3f) || ((value & 7) != ((value >> 3) & 7)))
+            fprintf(stderr, "tsc2102_audio_register_write: "
+                            "wrong value written into Audio 1\n");
+#endif
+        return;
+
+    case 0x01:
+#ifdef TSC_VERBOSE
+        if (value != 0xff00)
+            fprintf(stderr, "tsc2102_audio_register_write: "
+                            "wrong value written into reg 0x01\n");
+#endif
+        return;
+
+    case 0x02:	/* DAC Volume Control */
+        s->volume = value;
+        s->volume_change = qemu_get_clock(vm_clock);
+        return;
+
+    case 0x03:
+#ifdef TSC_VERBOSE
+        if (value != 0x8b00)
+            fprintf(stderr, "tsc2102_audio_register_write: "
+                            "wrong value written into reg 0x03\n");
+#endif
+        return;
+
+    case 0x04:	/* Audio Control 2 */
+        s->audio_ctrl2 = value & 0xf7f2;
+#ifdef TSC_VERBOSE
+        if (value & ~0xf7fd)
+            fprintf(stderr, "tsc2102_audio_register_write: "
+                            "wrong value written into Audio 2\n");
+#endif
+        return;
+
+    case 0x05:	/* Stereo DAC Power Control */
+        if ((value & ~s->dac_power) & (1 << 10))
+            s->powerdown = qemu_get_clock(vm_clock);
+
+        s->dac_power = value & 0x9543;
+#ifdef TSC_VERBOSE
+        if ((value & ~0x9543) != 0x2aa0)
+            fprintf(stderr, "tsc2102_audio_register_write: "
+                            "wrong value written into Power\n");
+#endif
+        return;
+
+    case 0x06:	/* Audio Control 3 */
+        s->audio_ctrl3 &= 0x00c0;
+        s->audio_ctrl3 |= value & 0xf800;
+#ifdef TSC_VERBOSE
+        if (value & ~0xf8c7)
+            fprintf(stderr, "tsc2102_audio_register_write: "
+                            "wrong value written into Audio 3\n");
+#endif
+        return;
+
+    case 0x07:	/* LCH_BASS_BOOST_N0 */
+    case 0x08:	/* LCH_BASS_BOOST_N1 */
+    case 0x09:	/* LCH_BASS_BOOST_N2 */
+    case 0x0a:	/* LCH_BASS_BOOST_N3 */
+    case 0x0b:	/* LCH_BASS_BOOST_N4 */
+    case 0x0c:	/* LCH_BASS_BOOST_N5 */
+    case 0x0d:	/* LCH_BASS_BOOST_D1 */
+    case 0x0e:	/* LCH_BASS_BOOST_D2 */
+    case 0x0f:	/* LCH_BASS_BOOST_D4 */
+    case 0x10:	/* LCH_BASS_BOOST_D5 */
+    case 0x11:	/* RCH_BASS_BOOST_N0 */
+    case 0x12:	/* RCH_BASS_BOOST_N1 */
+    case 0x13:	/* RCH_BASS_BOOST_N2 */
+    case 0x14:	/* RCH_BASS_BOOST_N3 */
+    case 0x15:	/* RCH_BASS_BOOST_N4 */
+    case 0x16:	/* RCH_BASS_BOOST_N5 */
+    case 0x17:	/* RCH_BASS_BOOST_D1 */
+    case 0x18:	/* RCH_BASS_BOOST_D2 */
+    case 0x19:	/* RCH_BASS_BOOST_D4 */
+    case 0x1a:	/* RCH_BASS_BOOST_D5 */
+        s->filter_data[reg - 0x07] = value;
+        return;
+
+    case 0x1b:	/* PLL Programmability 1 */
+        s->pll[0] = value & 0xfffc;
+#ifdef TSC_VERBOSE
+        if (value & ~0xfffc)
+            fprintf(stderr, "tsc2102_audio_register_write: "
+                            "wrong value written into PLL 1\n");
+#endif
+        return;
+
+    case 0x1c:	/* PLL Programmability 2 */
+        s->pll[1] = value & 0xfffc;
+#ifdef TSC_VERBOSE
+        if (value & ~0xfffc)
+            fprintf(stderr, "tsc2102_audio_register_write: "
+                            "wrong value written into PLL 2\n");
+#endif
+        return;
+
+    case 0x1d:	/* Audio Control 4 */
+        s->softstep = !(value & 0x4000);
+#ifdef TSC_VERBOSE
+        if (value & ~0x4000)
+            fprintf(stderr, "tsc2102_audio_register_write: "
+                            "wrong value written into Audio 4\n");
+#endif
+        return;
+
+    default:
+#ifdef TSC_VERBOSE
+        fprintf(stderr, "tsc2102_audio_register_write: "
+                        "no such register: 0x%02x\n", reg);
+#endif
+    }
+}
+
+/* This handles most of the chip logic.  */
+static void tsc210x_pin_update(struct tsc210x_state_s *s)
+{
+    int64_t expires;
+    int pin_state;
+
+    switch (s->pin_func) {
+    case 0:
+        pin_state = s->pressure;
+        break;
+    case 1:
+        pin_state = !!s->dav;
+        break;
+    case 2:
+    default:
+        pin_state = s->pressure && !s->dav;
+    }
+
+    if (!s->enabled)
+        pin_state = 0;
+
+    if (pin_state != s->irq) {
+        s->irq = pin_state;
+        qemu_set_irq(s->pint, s->irq);
+    }
+
+    switch (s->nextfunction) {
+    case TSC_MODE_XY_SCAN:
+    case TSC_MODE_XYZ_SCAN:
+        if (!s->pressure)
+            return;
+        break;
+
+    case TSC_MODE_X:
+    case TSC_MODE_Y:
+    case TSC_MODE_Z:
+        if (!s->pressure)
+            return;
+        /* Fall through */
+    case TSC_MODE_BAT1:
+    case TSC_MODE_BAT2:
+    case TSC_MODE_AUX:
+    case TSC_MODE_TEMP1:
+    case TSC_MODE_TEMP2:
+        if (s->dav)
+            s->enabled = 0;
+        break;
+
+    case TSC_MODE_AUX_SCAN:
+    case TSC_MODE_PORT_SCAN:
+        break;
+
+    case TSC_MODE_NO_SCAN:
+    case TSC_MODE_XX_DRV:
+    case TSC_MODE_YY_DRV:
+    case TSC_MODE_YX_DRV:
+    default:
+        return;
+    }
+
+    if (!s->enabled || s->busy)
+        return;
+
+    s->busy = 1;
+    s->precision = s->nextprecision;
+    s->function = s->nextfunction;
+    expires = qemu_get_clock(vm_clock) + (ticks_per_sec >> 10);
+    qemu_mod_timer(s->timer, expires);
+}
+
+static uint16_t tsc210x_read(struct tsc210x_state_s *s)
+{
+    uint16_t ret = 0x0000;
+
+    if (!s->command)
+        fprintf(stderr, "tsc210x_read: SPI underrun!\n");
+
+    switch (s->page) {
+    case TSC_DATA_REGISTERS_PAGE:
+        ret = tsc2102_data_register_read(s, s->offset);
+        break;
+    case TSC_CONTROL_REGISTERS_PAGE:
+        ret = tsc2102_control_register_read(s, s->offset);
+        break;
+    case TSC_AUDIO_REGISTERS_PAGE:
+        ret = tsc2102_audio_register_read(s, s->offset);
+        break;
+    default:
+        cpu_abort(cpu_single_env, "tsc210x_read: wrong memory page\n");
+    }
+
+    tsc210x_pin_update(s);
+
+    /* Allow sequential reads.  */
+    s->offset ++;
+    s->state = 0;
+    return ret;
+}
+
+static void tsc210x_write(struct tsc210x_state_s *s, uint16_t value)
+{
+    /*
+     * This is a two-state state machine for reading
+     * command and data every second time.
+     */
+    if (!s->state) {
+        s->command = value >> 15;
+        s->page = (value >> 11) & 0x0f;
+        s->offset = (value >> 5) & 0x3f;
+        s->state = 1;
+    } else {
+        if (s->command)
+            fprintf(stderr, "tsc210x_write: SPI overrun!\n");
+        else
+            switch (s->page) {
+            case TSC_DATA_REGISTERS_PAGE:
+                tsc2102_data_register_write(s, s->offset, value);
+                break;
+            case TSC_CONTROL_REGISTERS_PAGE:
+                tsc2102_control_register_write(s, s->offset, value);
+                break;
+            case TSC_AUDIO_REGISTERS_PAGE:
+                tsc2102_audio_register_write(s, s->offset, value);
+                break;
+            default:
+                cpu_abort(cpu_single_env,
+                                "tsc210x_write: wrong memory page\n");
+            }
+
+        tsc210x_pin_update(s);
+        s->state = 0;
+    }
+}
+
+static void tsc210x_timer_tick(void *opaque)
+{
+    struct tsc210x_state_s *s = opaque;
+
+    /* Timer ticked -- a set of conversions has been finished.  */
+
+    if (!s->busy)
+        return;
+
+    s->busy = 0;
+    s->dav |= mode_regs[s->function];
+    tsc210x_pin_update(s);
+}
+
+static void tsc210x_touchscreen_event(void *opaque,
+                int x, int y, int z, int buttons_state)
+{
+    struct tsc210x_state_s *s = opaque;
+    int p = s->pressure;
+
+    if (buttons_state) {
+        s->x = x;
+        s->y = y;
+    }
+    s->pressure = !!buttons_state;
+
+    /*
+     * Note: We would get better responsiveness in the guest by
+     * signaling TS events immediately, but for now we simulate
+     * the first conversion delay for sake of correctness.
+     */
+    if (p != s->pressure)
+        tsc210x_pin_update(s);
+}
+
+static void tsc210x_save(QEMUFile *f, void *opaque)
+{
+    struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque;
+    int64_t now = qemu_get_clock(vm_clock);
+    int i;
+
+    qemu_put_be16(f, s->x);
+    qemu_put_be16(f, s->y);
+    qemu_put_byte(f, s->pressure);
+
+    qemu_put_byte(f, s->state);
+    qemu_put_byte(f, s->page);
+    qemu_put_byte(f, s->offset);
+    qemu_put_byte(f, s->command);
+
+    qemu_put_byte(f, s->irq);
+    qemu_put_be16s(f, &s->dav);
+
+    qemu_put_timer(f, s->timer);
+    qemu_put_byte(f, s->enabled);
+    qemu_put_byte(f, s->host_mode);
+    qemu_put_byte(f, s->function);
+    qemu_put_byte(f, s->nextfunction);
+    qemu_put_byte(f, s->precision);
+    qemu_put_byte(f, s->nextprecision);
+    qemu_put_byte(f, s->filter);
+    qemu_put_byte(f, s->pin_func);
+    qemu_put_byte(f, s->ref);
+    qemu_put_byte(f, s->timing);
+    qemu_put_be32(f, s->noise);
+
+    qemu_put_be16s(f, &s->audio_ctrl1);
+    qemu_put_be16s(f, &s->audio_ctrl2);
+    qemu_put_be16s(f, &s->audio_ctrl3);
+    qemu_put_be16s(f, &s->pll[0]);
+    qemu_put_be16s(f, &s->pll[1]);
+    qemu_put_be16s(f, &s->volume);
+    qemu_put_be64(f, (uint64_t) (s->volume_change - now));
+    qemu_put_be64(f, (uint64_t) (s->powerdown - now));
+    qemu_put_byte(f, s->softstep);
+    qemu_put_be16s(f, &s->dac_power);
+
+    for (i = 0; i < 0x14; i ++)
+        qemu_put_be16s(f, &s->filter_data[i]);
+}
+
+static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque;
+    int64_t now = qemu_get_clock(vm_clock);
+    int i;
+
+    s->x = qemu_get_be16(f);
+    s->y = qemu_get_be16(f);
+    s->pressure = qemu_get_byte(f);
+
+    s->state = qemu_get_byte(f);
+    s->page = qemu_get_byte(f);
+    s->offset = qemu_get_byte(f);
+    s->command = qemu_get_byte(f);
+
+    s->irq = qemu_get_byte(f);
+    qemu_get_be16s(f, &s->dav);
+
+    qemu_get_timer(f, s->timer);
+    s->enabled = qemu_get_byte(f);
+    s->host_mode = qemu_get_byte(f);
+    s->function = qemu_get_byte(f);
+    s->nextfunction = qemu_get_byte(f);
+    s->precision = qemu_get_byte(f);
+    s->nextprecision = qemu_get_byte(f);
+    s->filter = qemu_get_byte(f);
+    s->pin_func = qemu_get_byte(f);
+    s->ref = qemu_get_byte(f);
+    s->timing = qemu_get_byte(f);
+    s->noise = qemu_get_be32(f);
+
+    qemu_get_be16s(f, &s->audio_ctrl1);
+    qemu_get_be16s(f, &s->audio_ctrl2);
+    qemu_get_be16s(f, &s->audio_ctrl3);
+    qemu_get_be16s(f, &s->pll[0]);
+    qemu_get_be16s(f, &s->pll[1]);
+    qemu_get_be16s(f, &s->volume);
+    s->volume_change = (int64_t) qemu_get_be64(f) + now;
+    s->powerdown = (int64_t) qemu_get_be64(f) + now;
+    s->softstep = qemu_get_byte(f);
+    qemu_get_be16s(f, &s->dac_power);
+
+    for (i = 0; i < 0x14; i ++)
+        qemu_get_be16s(f, &s->filter_data[i]);
+
+    s->busy = qemu_timer_pending(s->timer);
+    qemu_set_irq(s->pint, s->irq);
+
+    return 0;
+}
+
+static int tsc2102_iid = 0;
+
+struct uwire_slave_s *tsc2102_init(qemu_irq pint)
+{
+    struct tsc210x_state_s *s;
+
+    s = (struct tsc210x_state_s *)
+            qemu_mallocz(sizeof(struct tsc210x_state_s));
+    memset(s, 0, sizeof(struct tsc210x_state_s));
+    s->x = 160;
+    s->y = 160;
+    s->pressure = 0;
+    s->precision = s->nextprecision = 0;
+    s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
+    s->pint = pint;
+
+    s->chip.opaque = s;
+    s->chip.send = (void *) tsc210x_write;
+    s->chip.receive = (void *) tsc210x_read;
+
+    tsc210x_reset(s);
+
+    qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
+                    "QEMU TSC2102-driven Touchscreen");
+
+    qemu_register_reset((void *) tsc210x_reset, s);
+    register_savevm("tsc2102", tsc2102_iid ++, 0,
+                    tsc210x_save, tsc210x_load, s);
+
+    return &s->chip;
+}

Modified: trunk/src/host/qemu-neo1973/hw/usb-uhci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/usb-uhci.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/usb-uhci.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -25,6 +25,7 @@
 
 //#define DEBUG
 //#define DEBUG_PACKET
+//#define DEBUG_ISOCH
 
 #define UHCI_CMD_FGR      (1 << 4)
 #define UHCI_CMD_EGSM     (1 << 3)
@@ -88,6 +89,7 @@
        other queues will not be processed until the next frame.  The solution
        is to allow multiple pending requests.  */
     uint32_t async_qh;
+    uint32_t async_frame_addr;
     USBPacket usb_packet;
     uint8_t usb_buf[2048];
 } UHCIState;
@@ -146,6 +148,58 @@
     }
 }
 
+static void uhci_save(QEMUFile *f, void *opaque)
+{
+    UHCIState *s = opaque;
+    uint8_t num_ports = NB_PORTS;
+    int i;
+
+    pci_device_save(&s->dev, f);
+
+    qemu_put_8s(f, &num_ports);
+    for (i = 0; i < num_ports; ++i)
+        qemu_put_be16s(f, &s->ports[i].ctrl);
+    qemu_put_be16s(f, &s->cmd);
+    qemu_put_be16s(f, &s->status);
+    qemu_put_be16s(f, &s->intr);
+    qemu_put_be16s(f, &s->frnum);
+    qemu_put_be32s(f, &s->fl_base_addr);
+    qemu_put_8s(f, &s->sof_timing);
+    qemu_put_8s(f, &s->status2);
+    qemu_put_timer(f, s->frame_timer);
+}
+
+static int uhci_load(QEMUFile *f, void *opaque, int version_id)
+{
+    UHCIState *s = opaque;
+    uint8_t num_ports;
+    int i, ret;
+
+    if (version_id > 1)
+        return -EINVAL;
+
+    ret = pci_device_load(&s->dev, f);
+    if (ret < 0)
+        return ret;
+
+    qemu_get_8s(f, &num_ports);
+    if (num_ports != NB_PORTS)
+        return -EINVAL;
+
+    for (i = 0; i < num_ports; ++i)
+        qemu_get_be16s(f, &s->ports[i].ctrl);
+    qemu_get_be16s(f, &s->cmd);
+    qemu_get_be16s(f, &s->status);
+    qemu_get_be16s(f, &s->intr);
+    qemu_get_be16s(f, &s->frnum);
+    qemu_get_be32s(f, &s->fl_base_addr);
+    qemu_get_8s(f, &s->sof_timing);
+    qemu_get_8s(f, &s->status2);
+    qemu_get_timer(f, s->frame_timer);
+
+    return 0;
+}
+
 static void uhci_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
     UHCIState *s = opaque;
@@ -449,10 +503,11 @@
           0 if TD successful
           1 if TD unsuccessful or inactive
 */
-static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
+static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask,
+                          int completion)
 {
     uint8_t pid;
-    int len, max_len, err, ret;
+    int len = 0, max_len, err, ret = 0;
 
     /* ??? This is wrong for async completion.  */
     if (td->ctrl & TD_CTRL_IOC) {
@@ -465,7 +520,8 @@
     /* TD is active */
     max_len = ((td->token >> 21) + 1) & 0x7ff;
     pid = td->token & 0xff;
-    if (s->async_qh) {
+
+    if (completion && (s->async_qh || s->async_frame_addr)) {
         ret = s->usb_packet.len;
         if (ret >= 0) {
             len = ret;
@@ -481,7 +537,8 @@
             len = 0;
         }
         s->async_qh = 0;
-    } else {
+        s->async_frame_addr = 0;
+    } else if (!completion) {
         s->usb_packet.pid = pid;
         s->usb_packet.devaddr = (td->token >> 8) & 0x7f;
         s->usb_packet.devep = (td->token >> 15) & 0xf;
@@ -519,6 +576,7 @@
             return -1;
         }
     }
+
     if (ret == USB_RET_ASYNC) {
         return 2;
     }
@@ -584,8 +642,42 @@
     uint32_t link;
     uint32_t old_td_ctrl;
     uint32_t val;
+    uint32_t frame_addr;
     int ret;
 
+    /* Handle async isochronous packet completion */
+    frame_addr = s->async_frame_addr;
+    if (frame_addr) {
+        cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
+        le32_to_cpus(&link);
+
+        cpu_physical_memory_read(link & ~0xf, (uint8_t *)&td, sizeof(td));
+        le32_to_cpus(&td.link);
+        le32_to_cpus(&td.ctrl);
+        le32_to_cpus(&td.token);
+        le32_to_cpus(&td.buffer);
+        old_td_ctrl = td.ctrl;
+        ret = uhci_handle_td(s, &td, &s->pending_int_mask, 1);
+
+        /* update the status bits of the TD */
+        if (old_td_ctrl != td.ctrl) {
+            val = cpu_to_le32(td.ctrl);
+            cpu_physical_memory_write((link & ~0xf) + 4,
+                                      (const uint8_t *)&val,
+                                      sizeof(val));
+        }
+        if (ret == 2) {
+            s->async_frame_addr = frame_addr;
+        } else if (ret == 0) {
+            /* update qh element link */
+            val = cpu_to_le32(td.link);
+            cpu_physical_memory_write(frame_addr,
+                                      (const uint8_t *)&val,
+                                      sizeof(val));
+        }
+        return;
+    }
+
     link = s->async_qh;
     if (!link) {
         /* This should never happen. It means a TD somehow got removed
@@ -604,7 +696,8 @@
         le32_to_cpus(&td.token);
         le32_to_cpus(&td.buffer);
         old_td_ctrl = td.ctrl;
-        ret = uhci_handle_td(s, &td, &s->pending_int_mask);
+        ret = uhci_handle_td(s, &td, &s->pending_int_mask, 1);
+
         /* update the status bits of the TD */
         if (old_td_ctrl != td.ctrl) {
             val = cpu_to_le32(td.ctrl);
@@ -697,7 +790,8 @@
                 le32_to_cpus(&td.token);
                 le32_to_cpus(&td.buffer);
                 old_td_ctrl = td.ctrl;
-                ret = uhci_handle_td(s, &td, &int_mask);
+                ret = uhci_handle_td(s, &td, &int_mask, 0);
+
                 /* update the status bits of the TD */
                 if (old_td_ctrl != td.ctrl) {
                     val = cpu_to_le32(td.ctrl);
@@ -731,28 +825,24 @@
             le32_to_cpus(&td.ctrl);
             le32_to_cpus(&td.token);
             le32_to_cpus(&td.buffer);
-            /* Ignore isochonous transfers while there is an async packet
-               pending.  This is wrong, but we don't implement isochronous
-               transfers anyway.  */
-            if (s->async_qh == 0) {
-                old_td_ctrl = td.ctrl;
-                ret = uhci_handle_td(s, &td, &int_mask);
-                /* update the status bits of the TD */
-                if (old_td_ctrl != td.ctrl) {
-                    val = cpu_to_le32(td.ctrl);
-                    cpu_physical_memory_write((link & ~0xf) + 4,
-                                              (const uint8_t *)&val,
-                                              sizeof(val));
-                }
-                if (ret < 0)
-                    break; /* interrupted frame */
-                if (ret == 2) {
-                    /* We can't handle async isochronous transfers.
-                       Cancel The packet.  */
-                    fprintf(stderr, "usb-uhci: Unimplemented async packet\n");
-                    usb_cancel_packet(&s->usb_packet);
-                }
+
+            /* Handle isochonous transfer.  */
+            /* FIXME: might be more than one isoc in frame */
+            old_td_ctrl = td.ctrl;
+            ret = uhci_handle_td(s, &td, &int_mask, 0);
+
+            /* update the status bits of the TD */
+            if (old_td_ctrl != td.ctrl) {
+                val = cpu_to_le32(td.ctrl);
+                cpu_physical_memory_write((link & ~0xf) + 4,
+                                          (const uint8_t *)&val,
+                                          sizeof(val));
             }
+            if (ret < 0)
+                break; /* interrupted frame */
+            if (ret == 2) {
+                s->async_frame_addr = frame_addr;
+            }
             link = td.link;
         }
     }
@@ -767,6 +857,7 @@
         usb_cancel_packet(&s->usb_packet);
         s->async_qh = 0;
     }
+
     /* prepare the timer for the next frame */
     expire_time = qemu_get_clock(vm_clock) +
         (ticks_per_sec / FRAME_TIMER_FREQ);
@@ -855,4 +946,3 @@
     pci_register_io_region(&s->dev, 4, 0x20,
                            PCI_ADDRESS_SPACE_IO, uhci_map);
 }
-

Modified: trunk/src/host/qemu-neo1973/hw/vmport.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/vmport.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/hw/vmport.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -52,7 +52,7 @@
 {
     VMPortState *s = opaque;
     unsigned char command;
-    target_ulong eax;
+    uint32_t eax;
 
     eax = s->env->regs[R_EAX];
     if (eax != VMPORT_MAGIC)

Modified: trunk/src/host/qemu-neo1973/linux-user/alpha/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/alpha/syscall.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/alpha/syscall.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -2,40 +2,40 @@
 #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;
+	abi_ulong r0;
+	abi_ulong r1;
+	abi_ulong r2;
+	abi_ulong r3;
+	abi_ulong r4;
+	abi_ulong r5;
+	abi_ulong r6;
+	abi_ulong r7;
+	abi_ulong r8;
+	abi_ulong r19;
+	abi_ulong r20;
+	abi_ulong r21;
+	abi_ulong r22;
+	abi_ulong r23;
+	abi_ulong r24;
+	abi_ulong r25;
+	abi_ulong r26;
+	abi_ulong r27;
+	abi_ulong r28;
+	abi_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;
+	abi_ulong trap_a0;
+	abi_ulong trap_a1;
+	abi_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;
+	abi_ulong ps;
+	abi_ulong pc;
+	abi_ulong gp;
+	abi_ulong r16;
+	abi_ulong r17;
+	abi_ulong r18;
 /* Those is needed by qemu to temporary store the user stack pointer */
-        target_ulong usp;
-        target_ulong unique;
+        abi_ulong usp;
+        abi_ulong unique;
 };
 
 #define UNAME_MACHINE "alpha"

Modified: trunk/src/host/qemu-neo1973/linux-user/alpha/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/alpha/syscall_nr.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/alpha/syscall_nr.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -379,3 +379,35 @@
 #define TARGET_NR_inotify_init		444
 #define TARGET_NR_inotify_add_watch		445
 #define TARGET_NR_inotify_rm_watch		446
+#define TARGET_NR_fdatasync			447
+#define TARGET_NR_kexec_load			448
+#define TARGET_NR_migrate_pages		449
+#define TARGET_NR_openat			450
+#define TARGET_NR_mkdirat			451
+#define TARGET_NR_mknodat			452
+#define TARGET_NR_fchownat			453
+#define TARGET_NR_futimesat			454
+#define TARGET_NR_fstatat64			455
+#define TARGET_NR_unlinkat			456
+#define TARGET_NR_renameat			457
+#define TARGET_NR_linkat			458
+#define TARGET_NR_symlinkat			459
+#define TARGET_NR_readlinkat			460
+#define TARGET_NR_fchmodat			461
+#define TARGET_NR_faccessat			462
+#define TARGET_NR_pselect6			463
+#define TARGET_NR_ppoll			464
+#define TARGET_NR_unshare			465
+#define TARGET_NR_set_robust_list		466
+#define TARGET_NR_get_robust_list		467
+#define TARGET_NR_splice			468
+#define TARGET_NR_sync_file_range		469
+#define TARGET_NR_tee			470
+#define TARGET_NR_vmsplice			471
+#define TARGET_NR_move_pages			472
+#define TARGET_NR_getcpu			473
+#define TARGET_NR_epoll_pwait		474
+#define TARGET_NR_utimensat			475
+#define TARGET_NR_signalfd			476
+#define TARGET_NR_timerfd			477
+#define TARGET_NR_eventfd			478

Added: trunk/src/host/qemu-neo1973/linux-user/alpha/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/alpha/target_signal.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/alpha/target_signal.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+	abi_ulong ss_sp;
+	abi_long ss_flags;
+	abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK	1
+#define TARGET_SS_DISABLE	2
+
+#define TARGET_MINSIGSTKSZ	4096
+#define TARGET_SIGSTKSZ		16384
+
+static inline abi_ulong get_sp_from_cpustate(CPUAlphaState *state)
+{
+    return state->ir[IR_SP];
+}
+
+#endif /* TARGET_SIGNAL_H */

Modified: trunk/src/host/qemu-neo1973/linux-user/arm/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/arm/syscall.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/arm/syscall.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -3,7 +3,7 @@
    stack during a system call. */
 
 struct target_pt_regs {
-    target_long uregs[18];
+    abi_long uregs[18];
 };
 
 #define ARM_cpsr	uregs[16]

Modified: trunk/src/host/qemu-neo1973/linux-user/arm/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/arm/syscall_nr.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/arm/syscall_nr.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -325,3 +325,34 @@
 #define TARGET_NR_mbind			319
 #define TARGET_NR_get_mempolicy		320
 #define TARGET_NR_set_mempolicy		321
+#define TARGET_NR_openat			(322)
+#define TARGET_NR_mkdirat			(323)
+#define TARGET_NR_mknodat			(324)
+#define TARGET_NR_fchownat			(325)
+#define TARGET_NR_futimesat			(326)
+#define TARGET_NR_fstatat64			(327)
+#define TARGET_NR_unlinkat			(328)
+#define TARGET_NR_renameat			(329)
+#define TARGET_NR_linkat			(330)
+#define TARGET_NR_symlinkat			(331)
+#define TARGET_NR_readlinkat			(332)
+#define TARGET_NR_fchmodat			(333)
+#define TARGET_NR_faccessat			(334)
+					/* 335 for pselect6 */
+					/* 336 for ppoll */
+#define TARGET_NR_unshare			(337)
+#define TARGET_NR_set_robust_list		(338)
+#define TARGET_NR_get_robust_list		(339)
+#define TARGET_NR_splice			(340)
+#define TARGET_NR_arm_sync_file_range	(341)
+#define TARGET_NR_sync_file_range2		TARGET_NR_arm_sync_file_range
+#define TARGET_NR_tee			(342)
+#define TARGET_NR_vmsplice			(343)
+#define TARGET_NR_move_pages			(344)
+#define TARGET_NR_getcpu			(345)
+					/* 346 for epoll_pwait */
+#define TARGET_NR_kexec_load			(347)
+#define TARGET_NR_utimensat			(348)
+#define TARGET_NR_signalfd			(349)
+#define TARGET_NR_timerfd			(350)
+#define TARGET_NR_eventfd			(351)

Added: trunk/src/host/qemu-neo1973/linux-user/arm/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/arm/target_signal.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/arm/target_signal.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+	abi_ulong ss_sp;
+	abi_long ss_flags;
+	abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK	1
+#define TARGET_SS_DISABLE	2
+
+#define TARGET_MINSIGSTKSZ	2048
+#define TARGET_SIGSTKSZ		8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
+{
+   return state->regs[13];
+}
+
+#endif /* TARGET_SIGNAL_H */

Modified: trunk/src/host/qemu-neo1973/linux-user/arm/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/arm/termbits.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/arm/termbits.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -27,6 +27,7 @@
 #define TARGET_IXANY   0004000
 #define TARGET_IXOFF   0010000
 #define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8   0040000
 
 /* c_oflag bits */
 #define TARGET_OPOST   0000001
@@ -98,7 +99,8 @@
 #define  TARGET_B230400 0010003
 #define  TARGET_B460800 0010004
 #define TARGET_CIBAUD    002003600000  /* input baud rate (not used) */
-#define TARGET_CRTSCTS   020000000000          /* flow control */
+#define TARGET_CMSPAR    010000000000  /* mark or space (stick) parity */
+#define TARGET_CRTSCTS   020000000000  /* flow control */
 
 /* c_lflag bits */
 #define TARGET_ISIG    0000001

Added: trunk/src/host/qemu-neo1973/linux-user/cris/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/cris/syscall.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/cris/syscall.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,37 @@
+
+#define UNAME_MACHINE "cris"
+
+/* pt_regs not only specifices the format in the user-struct during
+ * ptrace but is also the frame format used in the kernel prologue/epilogues
+ * themselves
+ */
+
+struct target_pt_regs {
+        unsigned long orig_r10;
+        /* pushed by movem r13, [sp] in SAVE_ALL. */
+        unsigned long r0;
+        unsigned long r1;
+        unsigned long r2;
+        unsigned long r3;
+        unsigned long r4;
+        unsigned long r5;
+        unsigned long r6;
+        unsigned long r7;
+        unsigned long r8;
+        unsigned long r9;
+        unsigned long r10;
+        unsigned long r11;
+        unsigned long r12;
+        unsigned long r13;
+        unsigned long acr;
+        unsigned long srs;
+        unsigned long mof;
+        unsigned long spc;
+        unsigned long ccs;
+        unsigned long srp;
+        unsigned long erp; /* This is actually the debugged process' PC */
+        /* For debugging purposes; saved only when needed. */
+        unsigned long exs;
+        unsigned long eda;
+};
+

Added: trunk/src/host/qemu-neo1973/linux-user/cris/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/cris/syscall_nr.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/cris/syscall_nr.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,291 @@
+/*
+ * This file contains the system call numbers, and stub macros for libc.
+ */
+
+#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
+#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_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_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_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_pread64		180
+#define TARGET_NR_pwrite64		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_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_statfs64		268
+#define TARGET_NR_fstatfs64		269
+#define TARGET_NR_tgkill		270
+#define TARGET_NR_utimes		271
+#define TARGET_NR_fadvise64_64	272
+#define TARGET_NR_vserver		273
+#define TARGET_NR_mbind		274
+#define TARGET_NR_get_mempolicy	275
+#define TARGET_NR_set_mempolicy	276
+#define TARGET_NR_mq_open 		277
+#define TARGET_NR_mq_unlink		(TARGET_NR_mq_open+1)
+#define TARGET_NR_mq_timedsend	(TARGET_NR_mq_open+2)
+#define TARGET_NR_mq_timedreceive	(TARGET_NR_mq_open+3)
+#define TARGET_NR_mq_notify		(TARGET_NR_mq_open+4)
+#define TARGET_NR_mq_getsetattr	(TARGET_NR_mq_open+5)
+#define TARGET_NR_kexec_load		283
+#define TARGET_NR_waitid		284
+/* #define TARGET_NR_sys_setaltroot	285 */
+#define TARGET_NR_add_key		286
+#define TARGET_NR_request_key	287
+#define TARGET_NR_keyctl		288

Added: trunk/src/host/qemu-neo1973/linux-user/cris/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/cris/target_signal.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/cris/target_signal.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+	abi_ulong ss_sp;
+	abi_ulong ss_size;
+	abi_long ss_flags;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK     1
+#define TARGET_SS_DISABLE     2
+
+#define TARGET_MINSIGSTKSZ    2048
+#define TARGET_SIGSTKSZ       8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUCRISState *state)
+{
+    return state->regs[14];
+}
+
+#endif /* TARGET_SIGNAL_H */

Added: trunk/src/host/qemu-neo1973/linux-user/cris/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/cris/termbits.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/cris/termbits.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -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/elfload.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/elfload.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/elfload.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -12,6 +12,66 @@
 #include "qemu.h"
 #include "disas.h"
 
+/* from personality.h */
+
+/*
+ * Flags for bug emulation.
+ *
+ * These occupy the top three bytes.
+ */
+enum {
+	ADDR_NO_RANDOMIZE = 	0x0040000,	/* disable randomization of VA space */
+	FDPIC_FUNCPTRS =	0x0080000,	/* userspace function ptrs point to descriptors
+						 * (signal handling)
+						 */
+	MMAP_PAGE_ZERO =	0x0100000,
+	ADDR_COMPAT_LAYOUT =	0x0200000,
+	READ_IMPLIES_EXEC =	0x0400000,
+	ADDR_LIMIT_32BIT =	0x0800000,
+	SHORT_INODE =		0x1000000,
+	WHOLE_SECONDS =		0x2000000,
+	STICKY_TIMEOUTS	=	0x4000000,
+	ADDR_LIMIT_3GB = 	0x8000000,
+};
+
+/*
+ * Personality types.
+ *
+ * These go in the low byte.  Avoid using the top bit, it will
+ * conflict with error returns.
+ */
+enum {
+	PER_LINUX =		0x0000,
+	PER_LINUX_32BIT =	0x0000 | ADDR_LIMIT_32BIT,
+	PER_LINUX_FDPIC =	0x0000 | FDPIC_FUNCPTRS,
+	PER_SVR4 =		0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+	PER_SVR3 =		0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
+	PER_SCOSVR3 =		0x0003 | STICKY_TIMEOUTS |
+					 WHOLE_SECONDS | SHORT_INODE,
+	PER_OSR5 =		0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
+	PER_WYSEV386 =		0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
+	PER_ISCR4 =		0x0005 | STICKY_TIMEOUTS,
+	PER_BSD =		0x0006,
+	PER_SUNOS =		0x0006 | STICKY_TIMEOUTS,
+	PER_XENIX =		0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
+	PER_LINUX32 =		0x0008,
+	PER_LINUX32_3GB =	0x0008 | ADDR_LIMIT_3GB,
+	PER_IRIX32 =		0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
+	PER_IRIXN32 =		0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
+	PER_IRIX64 =		0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
+	PER_RISCOS =		0x000c,
+	PER_SOLARIS =		0x000d | STICKY_TIMEOUTS,
+	PER_UW7 =		0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+	PER_OSF4 =		0x000f,			 /* OSF/1 v4 */
+	PER_HPUX =		0x0010,
+	PER_MASK =		0x00ff,
+};
+
+/*
+ * Return the base personality without flags.
+ */
+#define personality(pers)	(pers & PER_MASK)
+
 /* this flag is uneffective under linux too, should be deleted */
 #ifndef MAP_DENYWRITE
 #define MAP_DENYWRITE 0
@@ -112,7 +172,7 @@
 
 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
 {
-    target_long stack = infop->start_stack;
+    abi_long stack = infop->start_stack;
     memset(regs, 0, sizeof(*regs));
     regs->ARM_cpsr = 0x10;
     if (infop->entry & 1)
@@ -124,6 +184,7 @@
     /* XXX: it seems that r0 is zeroed after ! */
     regs->ARM_r0 = 0;
     /* For uClinux PIC binaries.  */
+    /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
     regs->ARM_r10 = infop->start_data;
 }
 
@@ -153,7 +214,11 @@
 
 #define ELF_START_MMAP 0x80000000
 
-#define elf_check_arch(x) ( (x) == EM_SPARCV9 )
+#ifndef TARGET_ABI32
+#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
+#else
+#define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
+#endif
 
 #define ELF_CLASS   ELFCLASS64
 #define ELF_DATA    ELFDATA2MSB
@@ -163,11 +228,20 @@
 
 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
 {
+#ifndef TARGET_ABI32
     regs->tstate = 0;
+#endif
     regs->pc = infop->entry;
     regs->npc = regs->pc + 4;
     regs->y = 0;
-    regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
+#ifdef TARGET_ABI32
+    regs->u_regs[14] = infop->start_stack - 16 * 4;
+#else
+    if (personality(infop->personality) == PER_LINUX32)
+        regs->u_regs[14] = infop->start_stack - 16 * 4;
+    else
+        regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
+#endif
 }
 
 #else
@@ -195,7 +269,7 @@
 
 #define ELF_START_MMAP 0x80000000
 
-#ifdef TARGET_PPC64
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
 
 #define elf_check_arch(x) ( (x) == EM_PPC64 )
 
@@ -249,15 +323,14 @@
 
 static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
 {
-    target_ulong pos = infop->start_stack;
-    target_ulong tmp;
-#ifdef TARGET_PPC64
-    target_ulong entry, toc;
+    abi_ulong pos = infop->start_stack;
+    abi_ulong tmp;
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+    abi_ulong entry, toc;
 #endif
 
-    _regs->msr = 1 << MSR_PR; /* Set user mode */
     _regs->gpr[1] = infop->start_stack;
-#ifdef TARGET_PPC64
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
     entry = ldq_raw(infop->entry) + infop->load_addr;
     toc = ldq_raw(infop->entry + 8) + infop->load_addr;
     _regs->gpr[2] = toc;
@@ -269,9 +342,9 @@
      * execution of PPC BSD programs.
      */
     _regs->gpr[3] = tgetl(pos);
-    pos += sizeof(target_ulong);
+    pos += sizeof(abi_ulong);
     _regs->gpr[4] = pos;
-    for (tmp = 1; tmp != 0; pos += sizeof(target_ulong))
+    for (tmp = 1; tmp != 0; pos += sizeof(abi_ulong))
         tmp = ldl(pos);
     _regs->gpr[5] = pos;
 }
@@ -301,7 +374,7 @@
 
 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
 {
-    regs->cp0_status = CP0St_UM;
+    regs->cp0_status = 2 << CP0St_KSU;
     regs->cp0_epc = infop->entry;
     regs->regs[29] = infop->start_stack;
 }
@@ -333,6 +406,26 @@
 
 #endif
 
+#ifdef TARGET_CRIS
+
+#define ELF_START_MMAP 0x80000000
+
+#define elf_check_arch(x) ( (x) == EM_CRIS )
+
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA  ELFDATA2LSB
+#define ELF_ARCH  EM_CRIS
+
+static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+{
+  regs->erp = infop->entry;
+}
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE        8192
+
+#endif
+
 #ifdef TARGET_M68K
 
 #define ELF_START_MMAP 0x80000000
@@ -391,6 +484,13 @@
 #define ELF_HWCAP 0
 #endif
 
+#ifdef TARGET_ABI32
+#undef ELF_CLASS
+#define ELF_CLASS ELFCLASS32
+#undef bswaptls
+#define bswaptls(ptr) bswap32s(ptr)
+#endif
+
 #include "elf.h"
 
 struct exec
@@ -418,25 +518,6 @@
 /* max code+data+bss+brk space allocated to ET_DYN executables */
 #define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
 
-/* from personality.h */
-
-/* Flags for bug emulation. These occupy the top three bytes. */
-#define STICKY_TIMEOUTS		0x4000000
-#define WHOLE_SECONDS		0x2000000
-
-/* Personality types. These go in the low byte. Avoid using the top bit,
- * it will conflict with error returns.
- */
-#define PER_MASK		(0x00ff)
-#define PER_LINUX		(0x0000)
-#define PER_SVR4		(0x0001 | STICKY_TIMEOUTS)
-#define PER_SVR3		(0x0002 | STICKY_TIMEOUTS)
-#define PER_SCOSVR3		(0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS)
-#define PER_WYSEV386		(0x0004 | STICKY_TIMEOUTS)
-#define PER_ISCR4		(0x0005 | STICKY_TIMEOUTS)
-#define PER_BSD			(0x0006)
-#define PER_XENIX		(0x0007 | STICKY_TIMEOUTS)
-
 /* Necessary parameters */
 #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
 #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
@@ -516,8 +597,8 @@
  * to be put directly into the top of new user memory.
  *
  */
-static unsigned long copy_elf_strings(int argc,char ** argv, void **page,
-                                      unsigned long p)
+static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
+                                  abi_ulong p)
 {
     char *tmp, *tmp1, *pag = NULL;
     int len, offset = 0;
@@ -544,6 +625,7 @@
                 pag = (char *)page[p/TARGET_PAGE_SIZE];
                 if (!pag) {
                     pag = (char *)malloc(TARGET_PAGE_SIZE);
+                    memset(pag, 0, TARGET_PAGE_SIZE);
                     page[p/TARGET_PAGE_SIZE] = pag;
                     if (!pag)
                         return 0;
@@ -565,10 +647,10 @@
     return p;
 }
 
-unsigned long setup_arg_pages(target_ulong p, struct linux_binprm * bprm,
-					      struct image_info * info)
+static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
+                                 struct image_info *info)
 {
-    target_ulong stack_base, size, error;
+    abi_ulong stack_base, size, error;
     int i;
 
     /* Create enough stack to hold everything.  If we don't use
@@ -604,7 +686,7 @@
     return p;
 }
 
-static void set_brk(unsigned long start, unsigned long end)
+static void set_brk(abi_ulong start, abi_ulong end)
 {
 	/* page-align the start and end addresses... */
         start = HOST_PAGE_ALIGN(start);
@@ -623,9 +705,9 @@
 /* We need to explicitly zero any fractional pages after the data
    section (i.e. bss).  This would contain the junk from the file that
    should not be in memory. */
-static void padzero(unsigned long elf_bss, unsigned long last_bss)
+static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
 {
-        unsigned long nbyte;
+        abi_ulong nbyte;
 
 	if (elf_bss >= last_bss)
 		return;
@@ -636,12 +718,12 @@
            patch target_mmap(), but it is more complicated as the file
            size must be known */
         if (qemu_real_host_page_size < qemu_host_page_size) {
-            unsigned long end_addr, end_addr1;
+            abi_ulong end_addr, end_addr1;
             end_addr1 = (elf_bss + qemu_real_host_page_size - 1) &
                 ~(qemu_real_host_page_size - 1);
             end_addr = HOST_PAGE_ALIGN(elf_bss);
             if (end_addr1 < end_addr) {
-                mmap((void *)end_addr1, end_addr - end_addr1,
+                mmap((void *)g2h(end_addr1), end_addr - end_addr1,
                      PROT_READ|PROT_WRITE|PROT_EXEC,
                      MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
             }
@@ -658,18 +740,18 @@
 }
 
 
-static unsigned long create_elf_tables(target_ulong p, int argc, int envc,
-                                       struct elfhdr * exec,
-                                       unsigned long load_addr,
-                                       unsigned long load_bias,
-                                       unsigned long interp_load_addr, int ibcs,
-                                       struct image_info *info)
+static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
+                                   struct elfhdr * exec,
+                                   abi_ulong load_addr,
+                                   abi_ulong load_bias,
+                                   abi_ulong interp_load_addr, int ibcs,
+                                   struct image_info *info)
 {
-        target_ulong sp;
+        abi_ulong sp;
         int size;
-        target_ulong u_platform;
+        abi_ulong u_platform;
         const char *k_platform;
-        const int n = sizeof(target_ulong);
+        const int n = sizeof(elf_addr_t);
 
         sp = p;
         u_platform = 0;
@@ -683,7 +765,7 @@
 	/*
 	 * Force 16 byte _final_ alignment here for generality.
 	 */
-        sp = sp &~ (target_ulong)15;
+        sp = sp &~ (abi_ulong)15;
         size = (DLINFO_ITEMS + 1) * 2;
         if (k_platform)
           size += 2;
@@ -696,25 +778,35 @@
         if (size & 15)
             sp -= 16 - (size & 15);
 
+        /* This is correct because Linux defines
+         * elf_addr_t as Elf32_Off / Elf64_Off
+         */
+#if ELF_CLASS == ELFCLASS32
 #define NEW_AUX_ENT(id, val) do { \
-            sp -= n; tputl(sp, val); \
-            sp -= n; tputl(sp, id); \
+            sp -= n; tput32(sp, val); \
+            sp -= n; tput32(sp, id); \
           } while(0)
+#else
+#define NEW_AUX_ENT(id, val) do { \
+            sp -= n; tput64(sp, val); \
+            sp -= n; tput64(sp, id); \
+          } while(0)
+#endif
         NEW_AUX_ENT (AT_NULL, 0);
 
         /* There must be exactly DLINFO_ITEMS entries here.  */
-        NEW_AUX_ENT(AT_PHDR, (target_ulong)(load_addr + exec->e_phoff));
-        NEW_AUX_ENT(AT_PHENT, (target_ulong)(sizeof (struct elf_phdr)));
-        NEW_AUX_ENT(AT_PHNUM, (target_ulong)(exec->e_phnum));
-        NEW_AUX_ENT(AT_PAGESZ, (target_ulong)(TARGET_PAGE_SIZE));
-        NEW_AUX_ENT(AT_BASE, (target_ulong)(interp_load_addr));
-        NEW_AUX_ENT(AT_FLAGS, (target_ulong)0);
+        NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
+        NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
+        NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
+        NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
+        NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
+        NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
         NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
-        NEW_AUX_ENT(AT_UID, (target_ulong) getuid());
-        NEW_AUX_ENT(AT_EUID, (target_ulong) geteuid());
-        NEW_AUX_ENT(AT_GID, (target_ulong) getgid());
-        NEW_AUX_ENT(AT_EGID, (target_ulong) getegid());
-        NEW_AUX_ENT(AT_HWCAP, (target_ulong) ELF_HWCAP);
+        NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
+        NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
+        NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
+        NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
+        NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
         if (k_platform)
             NEW_AUX_ENT(AT_PLATFORM, u_platform);
 #ifdef ARCH_DLINFO
@@ -731,17 +823,17 @@
 }
 
 
-static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
-				     int interpreter_fd,
-				     unsigned long *interp_load_addr)
+static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
+                                 int interpreter_fd,
+                                 abi_ulong *interp_load_addr)
 {
 	struct elf_phdr *elf_phdata  =  NULL;
 	struct elf_phdr *eppnt;
-	unsigned long load_addr = 0;
+	abi_ulong load_addr = 0;
 	int load_addr_set = 0;
 	int retval;
-	unsigned long last_bss, elf_bss;
-	unsigned long error;
+	abi_ulong last_bss, elf_bss;
+	abi_ulong error;
 	int i;
 
 	elf_bss = 0;
@@ -755,20 +847,20 @@
 	if ((interp_elf_ex->e_type != ET_EXEC &&
              interp_elf_ex->e_type != ET_DYN) ||
 	   !elf_check_arch(interp_elf_ex->e_machine)) {
-		return ~0UL;
+		return ~((abi_ulong)0UL);
 	}
 
 
 	/* Now read in all of the header information */
 
 	if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
-	    return ~0UL;
+	    return ~(abi_ulong)0UL;
 
 	elf_phdata =  (struct elf_phdr *)
 		malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
 
 	if (!elf_phdata)
-	  return ~0UL;
+	  return ~((abi_ulong)0UL);
 
 	/*
 	 * If the size of this structure has changed, then punt, since
@@ -776,7 +868,7 @@
 	 */
 	if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
 	    free(elf_phdata);
-	    return ~0UL;
+	    return ~((abi_ulong)0UL);
         }
 
 	retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
@@ -817,8 +909,8 @@
 	  if (eppnt->p_type == PT_LOAD) {
 	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
 	    int elf_prot = 0;
-	    unsigned long vaddr = 0;
-	    unsigned long k;
+	    abi_ulong vaddr = 0;
+	    abi_ulong k;
 
 	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
 	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
@@ -838,7 +930,7 @@
 	      /* Real error */
 	      close(interpreter_fd);
 	      free(elf_phdata);
-	      return ~0UL;
+	      return ~((abi_ulong)0UL);
 	    }
 
 	    if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
@@ -883,7 +975,7 @@
 	free(elf_phdata);
 
 	*interp_load_addr = load_addr;
-	return ((unsigned long) interp_elf_ex->e_entry) + load_addr;
+	return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
 }
 
 /* Best attempt to load symbols from this ELF object. */
@@ -971,22 +1063,22 @@
     struct elfhdr interp_elf_ex;
     struct exec interp_ex;
     int interpreter_fd = -1; /* avoid warning */
-    unsigned long load_addr, load_bias;
+    abi_ulong load_addr, load_bias;
     int load_addr_set = 0;
     unsigned int interpreter_type = INTERPRETER_NONE;
     unsigned char ibcs2_interpreter;
     int i;
-    unsigned long mapped_addr;
+    abi_ulong mapped_addr;
     struct elf_phdr * elf_ppnt;
     struct elf_phdr *elf_phdata;
-    unsigned long elf_bss, k, elf_brk;
+    abi_ulong elf_bss, k, elf_brk;
     int retval;
     char * elf_interpreter;
-    unsigned long elf_entry, interp_load_addr = 0;
+    abi_ulong 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;
+    abi_ulong start_code, end_code, start_data, end_data;
+    abi_ulong reloc_func_desc = 0;
+    abi_ulong elf_stack;
     char passed_fileno[6];
 
     ibcs2_interpreter = 0;
@@ -1042,10 +1134,11 @@
     elf_brk = 0;
 
 
-    elf_stack = ~0UL;
+    elf_stack = ~((abi_ulong)0UL);
     elf_interpreter = NULL;
-    start_code = ~0UL;
+    start_code = ~((abi_ulong)0UL);
     end_code = 0;
+    start_data = 0;
     end_data = 0;
 
     for(i=0;i < elf_ex.e_phnum; i++) {
@@ -1179,9 +1272,9 @@
     /* OK, This is the point of no return */
     info->end_data = 0;
     info->end_code = 0;
-    info->start_mmap = (unsigned long)ELF_START_MMAP;
+    info->start_mmap = (abi_ulong)ELF_START_MMAP;
     info->mmap = 0;
-    elf_entry = (unsigned long) elf_ex.e_entry;
+    elf_entry = (abi_ulong) elf_ex.e_entry;
 
     /* Do this so that we can load the interpreter, if need be.  We will
        change some of these later */
@@ -1198,7 +1291,7 @@
     for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
         int elf_prot = 0;
         int elf_flags = 0;
-        unsigned long error;
+        abi_ulong error;
 
 	if (elf_ppnt->p_type != PT_LOAD)
             continue;
@@ -1256,6 +1349,8 @@
         k = elf_ppnt->p_vaddr;
         if (k < start_code)
             start_code = k;
+        if (start_data < k)
+            start_data = k;
         k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
         if (k > elf_bss)
             elf_bss = k;
@@ -1272,7 +1367,7 @@
     elf_brk += load_bias;
     start_code += load_bias;
     end_code += load_bias;
-    //    start_data += load_bias;
+    start_data += load_bias;
     end_data += load_bias;
 
     if (elf_interpreter) {
@@ -1288,7 +1383,7 @@
 	close(interpreter_fd);
 	free(elf_interpreter);
 
-	if (elf_entry == ~0UL) {
+	if (elf_entry == ~((abi_ulong)0UL)) {
 	    printf("Unable to load interpreter\n");
 	    free(elf_phdata);
 	    exit(-1);
@@ -1315,10 +1410,11 @@
 		    interp_load_addr,
 		    (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
 		    info);
+    info->load_addr = reloc_func_desc;
     info->start_brk = info->brk = elf_brk;
     info->end_code = end_code;
     info->start_code = start_code;
-    info->start_data = end_code;
+    info->start_data = start_data;
     info->end_data = end_data;
     info->start_stack = bprm->p;
 

Added: trunk/src/host/qemu-neo1973/linux-user/elfload32.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/elfload32.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/elfload32.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,30 @@
+#define TARGET_ABI32
+#define load_elf_binary load_elf_binary32
+#define do_init_thread do_init_thread32
+
+#include "elfload.c"
+
+#undef load_elf_binary
+#undef do_init_thread
+
+int load_elf_binary(struct linux_binprm *bprm, struct target_pt_regs *regs,
+                    struct image_info *info);
+
+int load_elf_binary_multi(struct linux_binprm *bprm,
+                          struct target_pt_regs *regs,
+                          struct image_info *info)
+{
+    struct elfhdr *elf_ex;
+    int retval;
+
+    elf_ex = (struct elfhdr *) bprm->buf;          /* exec-header */
+    if (elf_ex->e_ident[EI_CLASS] == ELFCLASS64) {
+        retval = load_elf_binary(bprm, regs, info);
+    } else {
+        retval = load_elf_binary32(bprm, regs, info);
+        if (personality(info->personality) == PER_LINUX)
+            info->personality = PER_LINUX32;
+    }
+
+    return retval;
+}


Property changes on: trunk/src/host/qemu-neo1973/linux-user/elfload32.c
___________________________________________________________________
Name: svn:executable
   + *

Modified: trunk/src/host/qemu-neo1973/linux-user/flat.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/flat.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/flat.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -22,25 +22,25 @@
 
 struct flat_hdr {
 	char magic[4];
-	target_ulong rev;          /* version (as above) */
-	target_ulong entry;        /* Offset of first executable instruction
-	                               with text segment from beginning of file */
-	target_ulong data_start;   /* Offset of data segment from beginning of
-	                               file */
-	target_ulong data_end;     /* Offset of end of data segment
-	                               from beginning of file */
-	target_ulong bss_end;      /* Offset of end of bss segment from beginning
-	                               of file */
+	abi_ulong rev;          /* version (as above) */
+	abi_ulong entry;        /* Offset of first executable instruction
+                                   with text segment from beginning of file */
+	abi_ulong data_start;   /* Offset of data segment from beginning of
+                                   file */
+	abi_ulong data_end;     /* Offset of end of data segment
+                                   from beginning of file */
+	abi_ulong bss_end;      /* Offset of end of bss segment from beginning
+                                   of file */
 
 	/* (It is assumed that data_end through bss_end forms the bss segment.) */
 
-	target_ulong stack_size;   /* Size of stack, in bytes */
-	target_ulong reloc_start;  /* Offset of relocation records from
-	                               beginning of file */
-	target_ulong reloc_count;  /* Number of relocation records */
-	target_ulong flags;
-	target_ulong build_date;   /* When the program/library was built */
-	target_ulong filler[5];    /* Reservered, set to zero */
+	abi_ulong stack_size;   /* Size of stack, in bytes */
+	abi_ulong reloc_start;  /* Offset of relocation records from
+                                   beginning of file */
+	abi_ulong reloc_count;  /* Number of relocation records */
+	abi_ulong flags;
+	abi_ulong build_date;   /* When the program/library was built */
+	abi_ulong filler[5];    /* Reservered, set to zero */
 };
 
 #define FLAT_FLAG_RAM    0x0001 /* load program entirely into RAM */

Modified: trunk/src/host/qemu-neo1973/linux-user/flatload.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/flatload.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/flatload.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -63,13 +63,13 @@
 #define UNLOADED_LIB 0x7ff000ff		/* Placeholder for unused library */
 
 struct lib_info {
-    target_ulong start_code;	/* Start of text segment */
-    target_ulong start_data;	/* Start of data segment */
-    target_ulong end_data;      /* Start of bss section */
-    target_ulong start_brk;	/* End of data segment */
-    target_ulong text_len;	/* Length of text segment */
-    target_ulong entry;		/* Start address for this module */
-    target_ulong build_date;	/* When this one was compiled */
+    abi_ulong start_code;       /* Start of text segment */
+    abi_ulong start_data;       /* Start of data segment */
+    abi_ulong end_data;         /* Start of bss section */
+    abi_ulong start_brk;        /* End of data segment */
+    abi_ulong text_len;	        /* Length of text segment */
+    abi_ulong entry;	        /* Start address for this module */
+    abi_ulong build_date;       /* When this one was compiled */
     short loaded;		/* Has this library been loaded? */
 };
 
@@ -89,7 +89,7 @@
  */
 
 /* Push a block of strings onto the guest stack.  */
-static target_ulong copy_strings(target_ulong p, int n, char **s)
+static abi_ulong copy_strings(abi_ulong p, int n, char **s)
 {
     int len;
 
@@ -102,8 +102,8 @@
     return p;
 }
 
-int target_pread(int fd, target_ulong ptr, target_ulong len,
-                 target_ulong offset)
+int target_pread(int fd, abi_ulong ptr, abi_ulong len,
+                 abi_ulong offset)
 {
     void *buf;
     int ret;
@@ -262,15 +262,15 @@
 
 /****************************************************************************/
 
-static target_ulong
-calc_reloc(target_ulong r, struct lib_info *p, int curid, int internalp)
+static abi_ulong
+calc_reloc(abi_ulong r, struct lib_info *p, int curid, int internalp)
 {
-    target_ulong addr;
+    abi_ulong addr;
     int id;
-    target_ulong start_brk;
-    target_ulong start_data;
-    target_ulong text_len;
-    target_ulong start_code;
+    abi_ulong start_brk;
+    abi_ulong start_data;
+    abi_ulong text_len;
+    abi_ulong start_code;
 
 #ifdef CONFIG_BINFMT_SHARED_FLAT
 #error needs checking
@@ -381,19 +381,19 @@
 /****************************************************************************/
 
 static int load_flat_file(struct linux_binprm * bprm,
-		struct lib_info *libinfo, int id, target_ulong *extra_stack)
+		struct lib_info *libinfo, int id, abi_ulong *extra_stack)
 {
     struct flat_hdr * hdr;
-    target_ulong textpos = 0, datapos = 0, result;
-    target_ulong realdatastart = 0;
-    target_ulong text_len, data_len, bss_len, stack_len, flags;
-    target_ulong memp = 0; /* for finding the brk area */
-    target_ulong extra;
-    target_ulong reloc = 0, rp;
+    abi_ulong textpos = 0, datapos = 0, result;
+    abi_ulong realdatastart = 0;
+    abi_ulong text_len, data_len, bss_len, stack_len, flags;
+    abi_ulong memp = 0; /* for finding the brk area */
+    abi_ulong extra;
+    abi_ulong reloc = 0, rp;
     int i, rev, relocs = 0;
-    target_ulong fpos;
-    target_ulong start_code, end_code;
-    target_ulong indx_len;
+    abi_ulong fpos;
+    abi_ulong start_code, end_code;
+    abi_ulong indx_len;
 
     hdr = ((struct flat_hdr *) bprm->buf);		/* exec-header */
 
@@ -440,14 +440,14 @@
     /*
      * calculate the extra space we need to map in
      */
-    extra = relocs * sizeof(target_ulong);
+    extra = relocs * sizeof(abi_ulong);
     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;
+    indx_len = MAX_SHARED_LIBS * sizeof(abi_ulong);
+    indx_len = (indx_len + 15) & ~(abi_ulong)15;
 
     /*
      * there are a couple of cases here,  the separate code/data
@@ -485,12 +485,12 @@
 #ifdef CONFIG_BINFMT_ZFLAT
         if (flags & FLAT_FLAG_GZDATA) {
             result = decompress_exec(bprm, fpos, (char *) datapos,
-                                     data_len + (relocs * sizeof(target_ulong)))
+                                     data_len + (relocs * sizeof(abi_ulong)))
         } else
 #endif
         {
             result = target_pread(bprm->fd, datapos,
-                                  data_len + (relocs * sizeof(target_ulong)),
+                                  data_len + (relocs * sizeof(abi_ulong)),
                                   fpos);
         }
         if (result < 0) {
@@ -544,7 +544,7 @@
                                   text_len, 0);
             if (result >= 0) {
                 result = target_pread(bprm->fd, datapos,
-                    data_len + (relocs * sizeof(target_ulong)),
+                    data_len + (relocs * sizeof(abi_ulong)),
                     ntohl(hdr->data_start));
             }
         }
@@ -597,7 +597,7 @@
     if (flags & FLAT_FLAG_GOTPIC) {
         rp = datapos;
         while (1) {
-            target_ulong addr;
+            abi_ulong addr;
             addr = tgetl(rp);
             if (addr == -1)
                 break;
@@ -607,7 +607,7 @@
                     return -ENOEXEC;
                 tputl(rp, addr);
             }
-            rp += sizeof(target_ulong);
+            rp += sizeof(abi_ulong);
         }
     }
 
@@ -624,12 +624,12 @@
      */
     if (rev > OLD_FLAT_VERSION) {
         for (i = 0; i < relocs; i++) {
-            target_ulong addr, relval;
+            abi_ulong addr, relval;
 
             /* Get the address of the pointer to be
                relocated (of course, the address has to be
                relocated first).  */
-            relval = tgetl(reloc + i * sizeof (target_ulong));
+            relval = tgetl(reloc + i * sizeof (abi_ulong));
             addr = flat_get_relocate_addr(relval);
             rp = calc_reloc(addr, libinfo, id, 1);
             if (rp == RELOC_FAILED)
@@ -657,8 +657,8 @@
         }
     } else {
         for (i = 0; i < relocs; i++) {
-            target_ulong relval;
-            relval = tgetl(reloc + i * sizeof (target_ulong));
+            abi_ulong relval;
+            relval = tgetl(reloc + i * sizeof (abi_ulong));
             old_reloc(&libinfo[0], relval);
         }
     }
@@ -712,10 +712,10 @@
                     struct image_info * info)
 {
     struct lib_info libinfo[MAX_SHARED_LIBS];
-    target_ulong p = bprm->p;
-    target_ulong stack_len;
-    target_ulong start_addr;
-    target_ulong sp;
+    abi_ulong p = bprm->p;
+    abi_ulong stack_len;
+    abi_ulong start_addr;
+    abi_ulong sp;
     int res;
     int i, j;
 
@@ -740,7 +740,7 @@
     /* Update data segment pointers for all libraries */
     for (i=0; i<MAX_SHARED_LIBS; i++) {
         if (libinfo[i].loaded) {
-            target_ulong p;
+            abi_ulong p;
             p = libinfo[i].start_data;
             for (j=0; j<MAX_SHARED_LIBS; j++) {
                 p -= 4;
@@ -758,12 +758,12 @@
     p = copy_strings(p, bprm->envc, bprm->envp);
     p = copy_strings(p, bprm->argc, bprm->argv);
     /* Align stack.  */
-    sp = p & ~(target_ulong)(sizeof(target_ulong) - 1);
+    sp = p & ~(abi_ulong)(sizeof(abi_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);
+    stack_len *= sizeof(abi_ulong);
     if ((sp + stack_len) & 15)
         sp -= 16 - ((sp + stack_len) & 15);
     sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, 1);

Modified: trunk/src/host/qemu-neo1973/linux-user/i386/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/i386/syscall.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/i386/syscall.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -31,7 +31,7 @@
 
 struct target_modify_ldt_ldt_s {
     unsigned int  entry_number;
-    target_ulong base_addr;
+    abi_ulong base_addr;
     unsigned int limit;
     unsigned int flags;
 };
@@ -79,22 +79,22 @@
 /*
  * 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;
+	abi_long ebx;
+	abi_long ecx;
+	abi_long edx;
+	abi_long esi;
+	abi_long edi;
+	abi_long ebp;
+	abi_long eax;
+	abi_long __null_ds;
+	abi_long __null_es;
+	abi_long __null_fs;
+	abi_long __null_gs;
+	abi_long orig_eax;
+	abi_long eip;
 	unsigned short cs, __csh;
-	target_long eflags;
-	target_long esp;
+	abi_long eflags;
+	abi_long esp;
 	unsigned short ss, __ssh;
 /*
  * these are specific to v86 mode:
@@ -106,14 +106,14 @@
 };
 
 struct target_revectored_struct {
-	target_ulong __map[8];			/* 256 bits */
+	abi_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;
+	abi_ulong flags;
+	abi_ulong screen_bitmap;
+	abi_ulong cpu_type;
 	struct target_revectored_struct int_revectored;
 	struct target_revectored_struct int21_revectored;
 };
@@ -124,7 +124,7 @@
 #define TARGET_VM86_SCREEN_BITMAP	0x0001
 
 struct target_vm86plus_info_struct {
-        target_ulong flags;
+        abi_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 */
@@ -134,9 +134,9 @@
 
 struct target_vm86plus_struct {
 	struct target_vm86_regs regs;
-	target_ulong flags;
-	target_ulong screen_bitmap;
-	target_ulong cpu_type;
+	abi_ulong flags;
+	abi_ulong screen_bitmap;
+	abi_ulong cpu_type;
 	struct target_revectored_struct int_revectored;
 	struct target_revectored_struct int21_revectored;
 	struct target_vm86plus_info_struct vm86plus;

Modified: trunk/src/host/qemu-neo1973/linux-user/i386/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/i386/syscall_nr.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/i386/syscall_nr.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -253,7 +253,7 @@
 #define TARGET_NR_io_submit		248
 #define TARGET_NR_io_cancel		249
 #define TARGET_NR_fadvise64		250
-
+/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
 #define TARGET_NR_exit_group		252
 #define TARGET_NR_lookup_dcookie	253
 #define TARGET_NR_epoll_create	254
@@ -270,8 +270,60 @@
 #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_statfs64		268
+#define TARGET_NR_fstatfs64		269
 #define TARGET_NR_tgkill		270
 #define TARGET_NR_utimes		271
-
+#define TARGET_NR_fadvise64_64	272
+#define TARGET_NR_vserver		273
+#define TARGET_NR_mbind		274
+#define TARGET_NR_get_mempolicy	275
+#define TARGET_NR_set_mempolicy	276
+#define TARGET_NR_mq_open 		277
+#define TARGET_NR_mq_unlink		(TARGET_NR_mq_open+1)
+#define TARGET_NR_mq_timedsend	(TARGET_NR_mq_open+2)
+#define TARGET_NR_mq_timedreceive	(TARGET_NR_mq_open+3)
+#define TARGET_NR_mq_notify		(TARGET_NR_mq_open+4)
+#define TARGET_NR_mq_getsetattr	(TARGET_NR_mq_open+5)
+#define TARGET_NR_kexec_load		283
+#define TARGET_NR_waitid		284
+/* #define TARGET_NR_sys_setaltroot	285 */
+#define TARGET_NR_add_key		286
+#define TARGET_NR_request_key	287
+#define TARGET_NR_keyctl		288
+#define TARGET_NR_ioprio_set		289
+#define TARGET_NR_ioprio_get		290
+#define TARGET_NR_inotify_init	291
+#define TARGET_NR_inotify_add_watch	292
+#define TARGET_NR_inotify_rm_watch	293
+#define TARGET_NR_migrate_pages	294
+#define TARGET_NR_openat		295
+#define TARGET_NR_mkdirat		296
+#define TARGET_NR_mknodat		297
+#define TARGET_NR_fchownat		298
+#define TARGET_NR_futimesat		299
+#define TARGET_NR_fstatat64		300
+#define TARGET_NR_unlinkat		301
+#define TARGET_NR_renameat		302
+#define TARGET_NR_linkat		303
+#define TARGET_NR_symlinkat		304
+#define TARGET_NR_readlinkat		305
+#define TARGET_NR_fchmodat		306
+#define TARGET_NR_faccessat		307
+#define TARGET_NR_pselect6		308
+#define TARGET_NR_ppoll		309
+#define TARGET_NR_unshare		310
 #define TARGET_NR_set_robust_list	311
+#define TARGET_NR_get_robust_list	312
+#define TARGET_NR_splice		313
+#define TARGET_NR_sync_file_range	314
+#define TARGET_NR_tee		315
+#define TARGET_NR_vmsplice		316
+#define TARGET_NR_move_pages		317
+#define TARGET_NR_getcpu		318
+#define TARGET_NR_epoll_pwait	319
+#define TARGET_NR_utimensat		320
+#define TARGET_NR_signalfd		321
+#define TARGET_NR_timerfd		322
+#define TARGET_NR_eventfd		323
+#define TARGET_NR_fallocate		324

Added: trunk/src/host/qemu-neo1973/linux-user/i386/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/i386/target_signal.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/i386/target_signal.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+	abi_ulong ss_sp;
+	abi_long ss_flags;
+	abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK	1
+#define TARGET_SS_DISABLE	2
+
+#define TARGET_MINSIGSTKSZ	2048
+#define TARGET_SIGSTKSZ		8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+{
+    return state->regs[R_ESP];
+}
+
+#endif /* TARGET_SIGNAL_H */

Modified: trunk/src/host/qemu-neo1973/linux-user/i386/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/i386/termbits.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/i386/termbits.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -26,6 +26,7 @@
 #define TARGET_IXANY   0004000
 #define TARGET_IXOFF   0010000
 #define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8   0040000
 
 /* c_oflag bits */
 #define TARGET_OPOST   0000001
@@ -96,8 +97,20 @@
 #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 (not used) */
-#define TARGET_CRTSCTS   020000000000          /* flow control */
+#define TARGET_CMSPAR    010000000000  /* mark or space (stick) parity */
+#define TARGET_CRTSCTS   020000000000  /* flow control */
 
 /* c_lflag bits */
 #define TARGET_ISIG    0000001

Modified: trunk/src/host/qemu-neo1973/linux-user/linuxload.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/linuxload.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/linuxload.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -13,7 +13,7 @@
 #define NGROUPS 32
 
 /* ??? This should really be somewhere else.  */
-void memcpy_to_target(target_ulong dest, const void *src,
+void memcpy_to_target(abi_ulong dest, const void *src,
                       unsigned long len)
 {
     void *host_ptr;
@@ -109,12 +109,12 @@
 }
 
 /* Construct the envp and argv tables on the target stack.  */
-target_ulong loader_build_argptr(int envc, int argc, target_ulong sp,
-                                 target_ulong stringp, int push_ptr)
+abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
+                              abi_ulong stringp, int push_ptr)
 {
-    int n = sizeof(target_ulong);
-    target_ulong envp;
-    target_ulong argv;
+    int n = sizeof(abi_ulong);
+    abi_ulong envp;
+    abi_ulong argv;
 
     sp -= (envc + 1) * n;
     envp = sp;
@@ -169,7 +169,11 @@
                 && bprm.buf[1] == 'E'
                 && bprm.buf[2] == 'L'
                 && bprm.buf[3] == 'F') {
+#ifndef TARGET_HAS_ELFLOAD32
             retval = load_elf_binary(&bprm,regs,infop);
+#else
+            retval = load_elf_binary_multi(&bprm, regs, infop);
+#endif
 #if defined(TARGET_HAS_BFLT)
         } else if (bprm.buf[0] == 'b'
                 && bprm.buf[1] == 'F'

Modified: trunk/src/host/qemu-neo1973/linux-user/m68k/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/m68k/syscall.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/m68k/syscall.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -3,14 +3,14 @@
    stack during a system call. */
 
 struct target_pt_regs {
-    target_long d1, d2, d3, d4, d5, d6, d7;
-    target_long a0, a1, a2, a3, a4, a5, a6;
-    target_ulong d0;
-    target_ulong usp;
-    target_ulong orig_d0;
+    abi_long d1, d2, d3, d4, d5, d6, d7;
+    abi_long a0, a1, a2, a3, a4, a5, a6;
+    abi_ulong d0;
+    abi_ulong usp;
+    abi_ulong orig_d0;
     int16_t stkadj;
     uint16_t sr;
-    target_ulong pc;
+    abi_ulong pc;
     uint16_t fntvex;
     uint16_t __fill;
 };

Modified: trunk/src/host/qemu-neo1973/linux-user/m68k/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/m68k/syscall_nr.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/m68k/syscall_nr.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -281,3 +281,42 @@
 #define TARGET_NR_add_key            279
 #define TARGET_NR_request_key        280
 #define TARGET_NR_keyctl             281
+#define TARGET_NR_ioprio_set		282
+#define TARGET_NR_ioprio_get		283
+#define TARGET_NR_inotify_init	284
+#define TARGET_NR_inotify_add_watch	285
+#define TARGET_NR_inotify_rm_watch	286
+#define TARGET_NR_migrate_pages	287
+#define TARGET_NR_openat		288
+#define TARGET_NR_mkdirat		289
+#define TARGET_NR_mknodat		290
+#define TARGET_NR_fchownat		291
+#define TARGET_NR_futimesat		292
+#define TARGET_NR_fstatat64		293
+#define TARGET_NR_unlinkat		294
+#define TARGET_NR_renameat		295
+#define TARGET_NR_linkat		296
+#define TARGET_NR_symlinkat		297
+#define TARGET_NR_readlinkat		298
+#define TARGET_NR_fchmodat		299
+#define TARGET_NR_faccessat		300
+#define TARGET_NR_pselect6		301
+#define TARGET_NR_ppoll		302
+#define TARGET_NR_unshare		303
+#define TARGET_NR_set_robust_list	304
+#define TARGET_NR_get_robust_list	305
+#define TARGET_NR_splice		306
+#define TARGET_NR_sync_file_range	307
+#define TARGET_NR_tee		308
+#define TARGET_NR_vmsplice		309
+#define TARGET_NR_move_pages		310
+#define TARGET_NR_sched_setaffinity	311
+#define TARGET_NR_sched_getaffinity	312
+#define TARGET_NR_kexec_load		313
+#define TARGET_NR_getcpu		314
+#define TARGET_NR_epoll_pwait	315
+#define TARGET_NR_utimensat		316
+#define TARGET_NR_signalfd		317
+#define TARGET_NR_timerfd		318
+#define TARGET_NR_eventfd		319
+#define TARGET_NR_fallocate		320

Added: trunk/src/host/qemu-neo1973/linux-user/m68k/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/m68k/target_signal.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/m68k/target_signal.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,24 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+	abi_ulong ss_sp;
+	abi_long ss_flags;
+	abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK	1
+#define TARGET_SS_DISABLE	2
+
+#define TARGET_MINSIGSTKSZ	2048
+#define TARGET_SIGSTKSZ	8192
+
+#endif /* TARGET_SIGNAL_H */

Modified: trunk/src/host/qemu-neo1973/linux-user/m68k/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/m68k/termbits.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/m68k/termbits.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -27,6 +27,7 @@
 #define TARGET_IXANY   0004000
 #define TARGET_IXOFF   0010000
 #define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8   0040000
 
 /* c_oflag bits */
 #define TARGET_OPOST   0000001
@@ -97,8 +98,20 @@
 #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 (not used) */
-#define TARGET_CRTSCTS   020000000000          /* flow control */
+#define TARGET_CMSPAR    010000000000  /* mark or space (stick) parity */
+#define TARGET_CRTSCTS   020000000000  /* flow control */
 
 /* c_lflag bits */
 #define TARGET_ISIG    0000001

Modified: trunk/src/host/qemu-neo1973/linux-user/main.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/main.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/main.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -168,7 +168,7 @@
 void cpu_loop(CPUX86State *env)
 {
     int trapnr;
-    target_ulong pc;
+    abi_ulong pc;
     target_siginfo_t info;
 
     for(;;) {
@@ -305,11 +305,11 @@
 #ifdef TARGET_ARM
 
 /* XXX: find a better solution */
-extern void tb_invalidate_page_range(target_ulong start, target_ulong end);
+extern void tb_invalidate_page_range(abi_ulong start, abi_ulong end);
 
-static void arm_cache_flush(target_ulong start, target_ulong last)
+static void arm_cache_flush(abi_ulong start, abi_ulong last)
 {
-    target_ulong addr, last1;
+    abi_ulong addr, last1;
 
     if (last < start)
         return;
@@ -474,7 +474,7 @@
 static inline void save_window_offset(CPUSPARCState *env, int cwp1)
 {
     unsigned int i;
-    target_ulong sp_ptr;
+    abi_ulong sp_ptr;
 
     sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
 #if defined(DEBUG_WIN)
@@ -483,7 +483,7 @@
 #endif
     for(i = 0; i < 16; i++) {
         tputl(sp_ptr, env->regbase[get_reg_index(env, cwp1, 8 + i)]);
-        sp_ptr += sizeof(target_ulong);
+        sp_ptr += sizeof(abi_ulong);
     }
 }
 
@@ -505,7 +505,7 @@
 static void restore_window(CPUSPARCState *env)
 {
     unsigned int new_wim, i, cwp1;
-    target_ulong sp_ptr;
+    abi_ulong sp_ptr;
 
     new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) &
         ((1LL << NWINDOWS) - 1);
@@ -519,7 +519,7 @@
 #endif
     for(i = 0; i < 16; i++) {
         env->regbase[get_reg_index(env, cwp1, 8 + i)] = tgetl(sp_ptr);
-        sp_ptr += sizeof(target_ulong);
+        sp_ptr += sizeof(abi_ulong);
     }
     env->wim = new_wim;
 #ifdef TARGET_SPARC64
@@ -564,6 +564,7 @@
         case 0x88:
         case 0x90:
 #else
+        case 0x110:
         case 0x16d:
 #endif
             ret = do_syscall (env, env->gregs[1],
@@ -571,14 +572,14 @@
                               env->regwptr[2], env->regwptr[3],
                               env->regwptr[4], env->regwptr[5]);
             if ((unsigned int)ret >= (unsigned int)(-515)) {
-#ifdef TARGET_SPARC64
+#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
                 env->xcc |= PSR_CARRY;
 #else
                 env->psr |= PSR_CARRY;
 #endif
                 ret = -ret;
             } else {
-#ifdef TARGET_SPARC64
+#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
                 env->xcc &= ~PSR_CARRY;
 #else
                 env->psr &= ~PSR_CARRY;
@@ -590,6 +591,9 @@
             env->npc = env->npc + 4;
             break;
         case 0x83: /* flush windows */
+#ifdef TARGET_ABI32
+        case 0x103:
+#endif
             flush_windows(env);
             /* next instruction */
             env->pc = env->npc;
@@ -634,6 +638,14 @@
                 queue_signal(info.si_signo, &info);
             }
             break;
+        case 0x16e:
+            flush_windows(env);
+            sparc64_get_context(env);
+            break;
+        case 0x16f:
+            flush_windows(env);
+            sparc64_set_context(env);
+            break;
 #endif
         case EXCP_INTERRUPT:
             /* just indicate that signals should be handled asap */
@@ -664,7 +676,6 @@
 #endif
 
 #ifdef TARGET_PPC
-
 static inline uint64_t cpu_ppc_get_tb (CPUState *env)
 {
     /* TO FIX */
@@ -681,37 +692,45 @@
     return cpu_ppc_get_tb(env) >> 32;
 }
 
-static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
+uint32_t cpu_ppc_load_atbl (CPUState *env)
 {
-    /* TO FIX */
+    return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
 }
 
-void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
+uint32_t cpu_ppc_load_atbu (CPUState *env)
 {
-    cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
+    return cpu_ppc_get_tb(env) >> 32;
 }
 
-void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
-{
-    cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
-}
-
-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)
+uint32_t cpu_ppc601_load_rtcl (CPUState *env)
 {
-    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
+    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
 }
 
-uint32_t cpu_ppc601_load_rtcl (CPUState *env)
+/* XXX: to be fixed */
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
 {
-    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
+    return -1;
 }
 
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
+{
+    return -1;
+}
+
+#define EXCP_DUMP(env, fmt, args...)                                         \
+do {                                                                          \
+    fprintf(stderr, fmt , ##args);                                            \
+    cpu_dump_state(env, stderr, fprintf, 0);                                  \
+    if (loglevel != 0) {                                                      \
+        fprintf(logfile, fmt , ##args);                                       \
+        cpu_dump_state(env, logfile, fprintf, 0);                             \
+    }                                                                         \
+} while (0)
+
 void cpu_loop(CPUPPCState *env)
 {
     target_siginfo_t info;
@@ -720,60 +739,22 @@
 
     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:
+        case POWERPC_EXCP_NONE:
+            /* Just go on */
             break;
-        case EXCP_SYSCALL_USER:
-            /* system call */
-            /* WARNING:
-             * PPC ABI uses overflow flag in cr0 to signal an error
-             * in syscalls.
-             */
-#if 0
-            printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
-                   env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
-#endif
-            env->crf[0] &= ~0x1;
-            ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
-                             env->gpr[5], env->gpr[6], env->gpr[7],
-                             env->gpr[8]);
-            if (ret > (uint32_t)(-515)) {
-                env->crf[0] |= 0x1;
-                ret = -ret;
-            }
-            env->gpr[3] = ret;
-#if 0
-            printf("syscall returned 0x%08x (%d)\n", ret, ret);
-#endif
+        case POWERPC_EXCP_CRITICAL: /* Critical input                        */
+            cpu_abort(env, "Critical interrupt while in user mode. "
+                      "Aborting\n");
             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 = TARGET_SIGBUS;
-            info.si_errno = 0;
-            info.si_code = TARGET_BUS_OBJERR;
-            info._sifields._sigfault._addr = env->nip - 4;
-            queue_signal(info.si_signo, &info);
-        case EXCP_DSI:
-            fprintf(stderr, "Invalid data memory access: 0x" ADDRX "\n",
-                    env->spr[SPR_DAR]);
-            if (loglevel) {
-                fprintf(logfile, "Invalid data memory access: 0x" ADDRX "\n",
-                        env->spr[SPR_DAR]);
-            }
+        case POWERPC_EXCP_MCHECK:   /* Machine check exception               */
+            cpu_abort(env, "Machine check exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_DSI:      /* Data storage exception                */
+            EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n",
+                      env->spr[SPR_DAR]);
+            /* XXX: check this. Seems bugged */
             switch (env->error_code & 0xFF000000) {
             case 0x40000000:
                 info.si_signo = TARGET_SIGSEGV;
@@ -792,12 +773,8 @@
                 break;
             default:
                 /* Let's send a regular segfault... */
-                fprintf(stderr, "Invalid segfault errno (%02x)\n",
-                        env->error_code);
-                if (loglevel) {
-                    fprintf(logfile, "Invalid segfault errno (%02x)\n",
-                            env->error_code);
-                }
+                EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
+                          env->error_code);
                 info.si_signo = TARGET_SIGSEGV;
                 info.si_errno = 0;
                 info.si_code = TARGET_SEGV_MAPERR;
@@ -806,10 +783,10 @@
             info._sifields._sigfault._addr = 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");
+        case POWERPC_EXCP_ISI:      /* Instruction storage exception         */
+            EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",
+                      env->spr[SPR_DAR]);
+            /* XXX: check this */
             switch (env->error_code & 0xFF000000) {
             case 0x40000000:
                 info.si_signo = TARGET_SIGSEGV;
@@ -824,12 +801,8 @@
                 break;
             default:
                 /* Let's send a regular segfault... */
-                fprintf(stderr, "Invalid segfault errno (%02x)\n",
-                        env->error_code);
-                if (loglevel) {
-                    fprintf(logfile, "Invalid segfault errno (%02x)\n",
-                            env->error_code);
-                }
+                EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
+                          env->error_code);
                 info.si_signo = TARGET_SIGSEGV;
                 info.si_errno = 0;
                 info.si_code = TARGET_SEGV_MAPERR;
@@ -838,186 +811,159 @@
             info._sifields._sigfault._addr = 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");
+        case POWERPC_EXCP_EXTERNAL: /* External input                        */
+            cpu_abort(env, "External interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_ALIGN:    /* Alignment exception                   */
+            EXCP_DUMP(env, "Unaligned memory access\n");
+            /* XXX: check this */
             info.si_signo = TARGET_SIGBUS;
             info.si_errno = 0;
             info.si_code = TARGET_BUS_ADRALN;
             info._sifields._sigfault._addr = env->nip - 4;
             queue_signal(info.si_signo, &info);
             break;
-        case EXCP_PROGRAM:
+        case POWERPC_EXCP_PROGRAM:  /* Program exception                     */
+            /* XXX: check this */
             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;
+            case POWERPC_EXCP_FP:
+                EXCP_DUMP(env, "Floating point program exception\n");
                 info.si_signo = TARGET_SIGFPE;
                 info.si_errno = 0;
                 switch (env->error_code & 0xF) {
-                case EXCP_FP_OX:
+                case POWERPC_EXCP_FP_OX:
                     info.si_code = TARGET_FPE_FLTOVF;
                     break;
-                case EXCP_FP_UX:
+                case POWERPC_EXCP_FP_UX:
                     info.si_code = TARGET_FPE_FLTUND;
                     break;
-                case EXCP_FP_ZX:
-                case EXCP_FP_VXZDZ:
+                case POWERPC_EXCP_FP_ZX:
+                case POWERPC_EXCP_FP_VXZDZ:
                     info.si_code = TARGET_FPE_FLTDIV;
                     break;
-                case EXCP_FP_XX:
+                case POWERPC_EXCP_FP_XX:
                     info.si_code = TARGET_FPE_FLTRES;
                     break;
-                case EXCP_FP_VXSOFT:
+                case POWERPC_EXCP_FP_VXSOFT:
                     info.si_code = TARGET_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:
+                case POWERPC_EXCP_FP_VXSNAN:
+                case POWERPC_EXCP_FP_VXISI:
+                case POWERPC_EXCP_FP_VXIDI:
+                case POWERPC_EXCP_FP_VXIMZ:
+                case POWERPC_EXCP_FP_VXVC:
+                case POWERPC_EXCP_FP_VXSQRT:
+                case POWERPC_EXCP_FP_VXCVI:
                     info.si_code = TARGET_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);
-                    }
+                    EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
+                              env->error_code);
+                    break;
                 }
-            break;
-        case EXCP_INVAL:
-                fprintf(stderr, "Invalid instruction\n");
-                if (loglevel)
-                    fprintf(logfile, "Invalid instruction\n");
+                break;
+            case POWERPC_EXCP_INVAL:
+                EXCP_DUMP(env, "Invalid instruction\n");
                 info.si_signo = TARGET_SIGILL;
                 info.si_errno = 0;
                 switch (env->error_code & 0xF) {
-                case EXCP_INVAL_INVAL:
+                case POWERPC_EXCP_INVAL_INVAL:
                     info.si_code = TARGET_ILL_ILLOPC;
                     break;
-                case EXCP_INVAL_LSWX:
-            info.si_code = TARGET_ILL_ILLOPN;
+                case POWERPC_EXCP_INVAL_LSWX:
+                    info.si_code = TARGET_ILL_ILLOPN;
                     break;
-                case EXCP_INVAL_SPR:
+                case POWERPC_EXCP_INVAL_SPR:
                     info.si_code = TARGET_ILL_PRVREG;
                     break;
-                case EXCP_INVAL_FP:
+                case POWERPC_EXCP_INVAL_FP:
                     info.si_code = TARGET_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);
-                    }
+                    EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
+                              env->error_code & 0xF);
                     info.si_code = TARGET_ILL_ILLADR;
                     break;
                 }
                 break;
-            case EXCP_PRIV:
-                fprintf(stderr, "Privilege violation\n");
-                if (loglevel)
-                    fprintf(logfile, "Privilege violation\n");
+            case POWERPC_EXCP_PRIV:
+                EXCP_DUMP(env, "Privilege violation\n");
                 info.si_signo = TARGET_SIGILL;
                 info.si_errno = 0;
                 switch (env->error_code & 0xF) {
-                case EXCP_PRIV_OPC:
+                case POWERPC_EXCP_PRIV_OPC:
                     info.si_code = TARGET_ILL_PRVOPC;
                     break;
-                case EXCP_PRIV_REG:
+                case POWERPC_EXCP_PRIV_REG:
                     info.si_code = TARGET_ILL_PRVREG;
-                break;
+                    break;
                 default:
-                    fprintf(stderr, "Unknown privilege violation (%02x)\n",
-                            env->error_code & 0xF);
+                    EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
+                              env->error_code & 0xF);
                     info.si_code = TARGET_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();
+            case POWERPC_EXCP_TRAP:
+                cpu_abort(env, "Tried to call a TRAP\n");
+                break;
             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();
+                cpu_abort(env, "Unknown program exception (%02x)\n",
+                          env->error_code);
+                break;
             }
             info._sifields._sigfault._addr = 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");
+        case POWERPC_EXCP_FPU:      /* Floating-point unavailable exception  */
+            EXCP_DUMP(env, "No floating point allowed\n");
             info.si_signo = TARGET_SIGILL;
             info.si_errno = 0;
             info.si_code = TARGET_ILL_COPROC;
             info._sifields._sigfault._addr = 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:
-            /* Do nothing: we use this to trace execution */
+        case POWERPC_EXCP_SYSCALL:  /* System call exception                 */
+            cpu_abort(env, "Syscall exception while in user mode. "
+                      "Aborting\n");
             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();
-        }
+        case POWERPC_EXCP_APU:      /* Auxiliary processor unavailable       */
+            EXCP_DUMP(env, "No APU instruction allowed\n");
+            info.si_signo = TARGET_SIGILL;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_COPROC;
+            info._sifields._sigfault._addr = env->nip - 4;
+            queue_signal(info.si_signo, &info);
             break;
-        case EXCP_BRANCH:
-            /* We stopped because of a jump... */
+        case POWERPC_EXCP_DECR:     /* Decrementer exception                 */
+            cpu_abort(env, "Decrementer interrupt while in user mode. "
+                      "Aborting\n");
             break;
-        case EXCP_INTERRUPT:
-            /* Don't know why this should ever happen... */
+        case POWERPC_EXCP_FIT:      /* Fixed-interval timer interrupt        */
+            cpu_abort(env, "Fix interval timer interrupt while in user mode. "
+                      "Aborting\n");
             break;
-        case EXCP_DEBUG:
+        case POWERPC_EXCP_WDT:      /* Watchdog timer interrupt              */
+            cpu_abort(env, "Watchdog timer interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_DTLB:     /* Data TLB error                        */
+            cpu_abort(env, "Data TLB exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_ITLB:     /* Instruction TLB error                 */
+            cpu_abort(env, "Instruction TLB exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_DEBUG:    /* Debug interrupt                       */
+            /* XXX: check this */
             {
                 int sig;
 
-                sig = gdb_handlesig (env, TARGET_SIGTRAP);
-                if (sig)
-                  {
+                sig = gdb_handlesig(env, TARGET_SIGTRAP);
+                if (sig) {
                     info.si_signo = sig;
                     info.si_errno = 0;
                     info.si_code = TARGET_TRAP_BRKPT;
@@ -1025,14 +971,176 @@
                   }
             }
             break;
+#if defined(TARGET_PPCEMB)
+        case POWERPC_EXCP_SPEU:     /* SPE/embedded floating-point unavail.  */
+            EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
+            info.si_signo = TARGET_SIGILL;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_COPROC;
+            info._sifields._sigfault._addr = env->nip - 4;
+            queue_signal(info.si_signo, &info);
+            break;
+        case POWERPC_EXCP_EFPDI:    /* Embedded floating-point data IRQ      */
+            cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
+            break;
+        case POWERPC_EXCP_EFPRI:    /* Embedded floating-point round IRQ     */
+            cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
+            break;
+        case POWERPC_EXCP_EPERFM:   /* Embedded performance monitor IRQ      */
+            cpu_abort(env, "Performance monitor exception not handled\n");
+            break;
+        case POWERPC_EXCP_DOORI:    /* Embedded doorbell interrupt           */
+            cpu_abort(env, "Doorbell interrupt while in user mode. "
+                       "Aborting\n");
+            break;
+        case POWERPC_EXCP_DOORCI:   /* Embedded doorbell critical interrupt  */
+            cpu_abort(env, "Doorbell critical interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_RESET:    /* System reset exception                */
+            cpu_abort(env, "Reset interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+#endif /* defined(TARGET_PPCEMB) */
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) /* PowerPC 64 */
+        case POWERPC_EXCP_DSEG:     /* Data segment exception                */
+            cpu_abort(env, "Data segment exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_ISEG:     /* Instruction segment exception         */
+            cpu_abort(env, "Instruction segment exception "
+                      "while in user mode. Aborting\n");
+            break;
+#endif /* defined(TARGET_PPC64) && !defined(TARGET_ABI32) */
+#if defined(TARGET_PPC64H) && !defined(TARGET_ABI32)
+        /* PowerPC 64 with hypervisor mode support */
+        case POWERPC_EXCP_HDECR:    /* Hypervisor decrementer exception      */
+            cpu_abort(env, "Hypervisor decrementer interrupt "
+                      "while in user mode. Aborting\n");
+            break;
+#endif /* defined(TARGET_PPC64H) && !defined(TARGET_ABI32) */
+        case POWERPC_EXCP_TRACE:    /* Trace exception                       */
+            /* Nothing to do:
+             * we use this exception to emulate step-by-step execution mode.
+             */
+            break;
+#if defined(TARGET_PPC64H) && !defined(TARGET_ABI32)
+        /* PowerPC 64 with hypervisor mode support */
+        case POWERPC_EXCP_HDSI:     /* Hypervisor data storage exception     */
+            cpu_abort(env, "Hypervisor data storage exception "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_HISI:     /* Hypervisor instruction storage excp   */
+            cpu_abort(env, "Hypervisor instruction storage exception "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_HDSEG:    /* Hypervisor data segment exception     */
+            cpu_abort(env, "Hypervisor data segment exception "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_HISEG:    /* Hypervisor instruction segment excp   */
+            cpu_abort(env, "Hypervisor instruction segment exception "
+                      "while in user mode. Aborting\n");
+            break;
+#endif /* defined(TARGET_PPC64H) && !defined(TARGET_ABI32) */
+        case POWERPC_EXCP_VPU:      /* Vector unavailable exception          */
+            EXCP_DUMP(env, "No Altivec instructions allowed\n");
+            info.si_signo = TARGET_SIGILL;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_COPROC;
+            info._sifields._sigfault._addr = env->nip - 4;
+            queue_signal(info.si_signo, &info);
+            break;
+        case POWERPC_EXCP_PIT:      /* Programmable interval timer IRQ       */
+            cpu_abort(env, "Programable interval timer interrupt "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_IO:       /* IO error exception                    */
+            cpu_abort(env, "IO error exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_RUNM:     /* Run mode exception                    */
+            cpu_abort(env, "Run mode exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_EMUL:     /* Emulation trap exception              */
+            cpu_abort(env, "Emulation trap exception not handled\n");
+            break;
+        case POWERPC_EXCP_IFTLB:    /* Instruction fetch TLB error           */
+            cpu_abort(env, "Instruction fetch TLB exception "
+                      "while in user-mode. Aborting");
+            break;
+        case POWERPC_EXCP_DLTLB:    /* Data load TLB miss                    */
+            cpu_abort(env, "Data load TLB exception while in user-mode. "
+                      "Aborting");
+            break;
+        case POWERPC_EXCP_DSTLB:    /* Data store TLB miss                   */
+            cpu_abort(env, "Data store TLB exception while in user-mode. "
+                      "Aborting");
+            break;
+        case POWERPC_EXCP_FPA:      /* Floating-point assist exception       */
+            cpu_abort(env, "Floating-point assist exception not handled\n");
+            break;
+        case POWERPC_EXCP_IABR:     /* Instruction address breakpoint        */
+            cpu_abort(env, "Instruction address breakpoint exception "
+                      "not handled\n");
+            break;
+        case POWERPC_EXCP_SMI:      /* System management interrupt           */
+            cpu_abort(env, "System management interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_THERM:    /* Thermal interrupt                     */
+            cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_PERFM:   /* Embedded performance monitor IRQ      */
+            cpu_abort(env, "Performance monitor exception not handled\n");
+            break;
+        case POWERPC_EXCP_VPUA:     /* Vector assist exception               */
+            cpu_abort(env, "Vector assist exception not handled\n");
+            break;
+        case POWERPC_EXCP_SOFTP:    /* Soft patch exception                  */
+            cpu_abort(env, "Soft patch exception not handled\n");
+            break;
+        case POWERPC_EXCP_MAINT:    /* Maintenance exception                 */
+            cpu_abort(env, "Maintenance exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_STOP:     /* stop translation                      */
+            /* We did invalidate the instruction cache. Go on */
+            break;
+        case POWERPC_EXCP_BRANCH:   /* branch instruction:                   */
+            /* We just stopped because of a branch. Go on */
+            break;
+        case POWERPC_EXCP_SYSCALL_USER:
+            /* system call in user-mode emulation */
+            /* WARNING:
+             * PPC ABI uses overflow flag in cr0 to signal an error
+             * in syscalls.
+             */
+#if 0
+            printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
+                   env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
+#endif
+            env->crf[0] &= ~0x1;
+            ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+                             env->gpr[5], env->gpr[6], env->gpr[7],
+                             env->gpr[8]);
+            if (ret > (uint32_t)(-515)) {
+                env->crf[0] |= 0x1;
+                ret = -ret;
+            }
+            env->gpr[3] = ret;
+#if 0
+            printf("syscall returned 0x%08x (%d)\n", ret, ret);
+#endif
+            break;
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            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();
+            cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
+            break;
         }
         process_pending_signals(env);
     }
@@ -1380,8 +1488,8 @@
                 ret = -ENOSYS;
             } else {
                 int nb_args;
-                target_ulong sp_reg;
-                target_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
+                abi_ulong sp_reg;
+                abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
 
                 nb_args = mips_syscall_args[syscall_num];
                 sp_reg = env->gpr[29][env->current_tc];
@@ -1493,6 +1601,61 @@
 }
 #endif
 
+#ifdef TARGET_CRIS
+void cpu_loop (CPUState *env)
+{
+    int trapnr, ret;
+    target_siginfo_t info;
+    
+    while (1) {
+        trapnr = cpu_cris_exec (env);
+        switch (trapnr) {
+        case 0xaa:
+            {
+                info.si_signo = SIGSEGV;
+                info.si_errno = 0;
+                /* XXX: check env->error_code */
+                info.si_code = TARGET_SEGV_MAPERR;
+                info._sifields._sigfault._addr = env->debug1;
+                queue_signal(info.si_signo, &info);
+            }
+            break;
+        case EXCP_BREAK:
+            ret = do_syscall(env, 
+                             env->regs[9], 
+                             env->regs[10], 
+                             env->regs[11], 
+                             env->regs[12], 
+                             env->regs[13], 
+                             env->pregs[7], 
+                             env->pregs[11]);
+            env->regs[10] = ret;
+            env->pc += 2;
+            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
+
 #ifdef TARGET_M68K
 
 void cpu_loop(CPUM68KState *env)
@@ -1781,14 +1944,9 @@
         } 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);
+/* XXX: implement xxx_cpu_list for targets that still miss it */
+#if defined(cpu_list)
+                    cpu_list(stdout, &fprintf);
 #endif
                 _exit(1);
             }
@@ -1850,14 +2008,17 @@
     if (loglevel) {
         page_dump(logfile);
 
-        fprintf(logfile, "start_brk   0x%08lx\n" , info->start_brk);
-        fprintf(logfile, "end_code    0x%08lx\n" , info->end_code);
-        fprintf(logfile, "start_code  0x%08lx\n" , info->start_code);
-        fprintf(logfile, "start_data  0x%08lx\n" , info->start_data);
-        fprintf(logfile, "end_data    0x%08lx\n" , info->end_data);
-        fprintf(logfile, "start_stack 0x%08lx\n" , info->start_stack);
-        fprintf(logfile, "brk         0x%08lx\n" , info->brk);
-        fprintf(logfile, "entry       0x%08lx\n" , info->entry);
+        fprintf(logfile, "start_brk   0x" TARGET_FMT_lx "\n", info->start_brk);
+        fprintf(logfile, "end_code    0x" TARGET_FMT_lx "\n", info->end_code);
+        fprintf(logfile, "start_code  0x" TARGET_FMT_lx "\n",
+                info->start_code);
+        fprintf(logfile, "start_data  0x" TARGET_FMT_lx "\n",
+                info->start_data);
+        fprintf(logfile, "end_data    0x" TARGET_FMT_lx "\n", info->end_data);
+        fprintf(logfile, "start_stack 0x" TARGET_FMT_lx "\n",
+                info->start_stack);
+        fprintf(logfile, "brk         0x" TARGET_FMT_lx "\n", info->brk);
+        fprintf(logfile, "entry       0x" TARGET_FMT_lx "\n", info->entry);
     }
 
     target_set_brk(info->brk);
@@ -1977,7 +2138,7 @@
             fprintf(stderr, "Unable to find Sparc CPU definition\n");
             exit(1);
         }
-        cpu_sparc_register(env, def);
+        cpu_sparc_register(env, def, 0);
 	env->pc = regs->pc;
 	env->npc = regs->npc;
         env->y = regs->y;
@@ -2000,14 +2161,14 @@
                       "Unable to find PowerPC CPU definition\n");
         }
         cpu_ppc_register(env, def);
-
-        for (i = 0; i < 32; i++) {
-            if (i != 12 && i != 6 && i != 13)
-                env->msr[i] = (regs->msr >> i) & 1;
-        }
+        cpu_ppc_reset(env);
 #if defined(TARGET_PPC64)
-        msr_sf = 1;
+#if defined(TARGET_ABI32)
+        env->msr &= ~((target_ulong)1 << MSR_SF);
+#else
+        env->msr |= (target_ulong)1 << MSR_SF;
 #endif
+#endif
         env->nip = regs->nip;
         for(i = 0; i < 32; i++) {
             env->gpr[i] = regs->gpr[i];
@@ -2048,7 +2209,11 @@
 
         /* Choose and initialise CPU */
         if (cpu_model == NULL)
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+            cpu_model = "20Kc";
+#else
             cpu_model = "24Kf";
+#endif
         mips_find_by_name(cpu_model, &def);
         if (def == NULL)
             cpu_abort(env, "Unable to find MIPS CPU definition\n");
@@ -2073,13 +2238,33 @@
         int i;
 
         for(i = 0; i < 28; i++) {
-            env->ir[i] = ((target_ulong *)regs)[i];
+            env->ir[i] = ((abi_ulong *)regs)[i];
         }
         env->ipr[IPR_USP] = regs->usp;
         env->ir[30] = regs->usp;
         env->pc = regs->pc;
         env->unique = regs->unique;
     }
+#elif defined(TARGET_CRIS)
+    {
+	    env->regs[0] = regs->r0;
+	    env->regs[1] = regs->r1;
+	    env->regs[2] = regs->r2;
+	    env->regs[3] = regs->r3;
+	    env->regs[4] = regs->r4;
+	    env->regs[5] = regs->r5;
+	    env->regs[6] = regs->r6;
+	    env->regs[7] = regs->r7;
+	    env->regs[8] = regs->r8;
+	    env->regs[9] = regs->r9;
+	    env->regs[10] = regs->r10;
+	    env->regs[11] = regs->r11;
+	    env->regs[12] = regs->r12;
+	    env->regs[13] = regs->r13;
+	    env->regs[14] = info->start_stack;
+	    env->regs[15] = regs->acr;	    
+	    env->pc = regs->erp;
+    }
 #else
 #error unsupported target CPU
 #endif

Modified: trunk/src/host/qemu-neo1973/linux-user/mips/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/mips/syscall.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/mips/syscall.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -3,21 +3,19 @@
    stack during a system call. */
 
 struct target_pt_regs {
-#if 1
 	/* Pad bytes for argument save space on the stack. */
-	target_ulong pad0[6];
-#endif
+	abi_ulong pad0[6];
 
 	/* Saved main processor registers. */
-	target_ulong regs[32];
+	abi_ulong regs[32];
 
 	/* Saved special registers. */
-	target_ulong cp0_status;
-	target_ulong lo;
-	target_ulong hi;
-	target_ulong cp0_badvaddr;
-	target_ulong cp0_cause;
-	target_ulong cp0_epc;
+	abi_ulong cp0_status;
+	abi_ulong lo;
+	abi_ulong hi;
+	abi_ulong cp0_badvaddr;
+	abi_ulong cp0_cause;
+	abi_ulong cp0_epc;
 };
 
 /* Target errno definitions taken from asm-mips/errno.h */

Modified: trunk/src/host/qemu-neo1973/linux-user/mips/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/mips/syscall_nr.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/mips/syscall_nr.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -318,3 +318,8 @@
 #define TARGET_NR_epoll_pwait		(TARGET_NR_Linux + 313)
 #define TARGET_NR_ioprio_set		(TARGET_NR_Linux + 314)
 #define TARGET_NR_ioprio_get		(TARGET_NR_Linux + 315)
+#define TARGET_NR_utimensat		(TARGET_NR_Linux + 316)
+#define TARGET_NR_signalfd		(TARGET_NR_Linux + 317)
+#define TARGET_NR_timerfd		(TARGET_NR_Linux + 318)
+#define TARGET_NR_eventfd		(TARGET_NR_Linux + 319)
+#define TARGET_NR_fallocate		(TARGET_NR_Linux + 320)

Added: trunk/src/host/qemu-neo1973/linux-user/mips/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/mips/target_signal.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/mips/target_signal.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+	abi_long ss_sp;
+	abi_ulong ss_size;
+	abi_long ss_flags;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK     1
+#define TARGET_SS_DISABLE     2
+
+#define TARGET_MINSIGSTKSZ    2048
+#define TARGET_SIGSTKSZ       8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
+{
+    return state->gpr[29][state->current_tc];
+}
+
+#endif /* TARGET_SIGNAL_H */

Modified: trunk/src/host/qemu-neo1973/linux-user/mips/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/mips/termbits.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/mips/termbits.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -26,6 +26,7 @@
 #define TARGET_IXANY   0004000
 #define TARGET_IXOFF   0010000
 #define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8   0040000
 
 /* c_oflag bits */
 #define TARGET_OPOST   0000001
@@ -92,12 +93,25 @@
 #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_BOTHER   0010000
+#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 (not used) */
-#define TARGET_CRTSCTS   020000000000          /* flow control */
+#define TARGET_CMSPAR    010000000000  /* mark or space (stick) parity */
+#define TARGET_CRTSCTS   020000000000  /* flow control */
 
 /* c_lflag bits */
 #define TARGET_ISIG    0000001
@@ -108,32 +122,34 @@
 #define TARGET_ECHOK   0000040
 #define TARGET_ECHONL  0000100
 #define TARGET_NOFLSH  0000200
-#define TARGET_TOSTOP  0000400
+#define TARGET_IEXTEN  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
+#define TARGET_TOSTOP  0100000
+#define TARGET_ITOSTOP TARGET_TOSTOP
 
 /* 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	4
 #define TARGET_VTIME	5
-#define TARGET_VMIN	6
+#define TARGET_VEOL2	6
 #define TARGET_VSWTC	7
 #define TARGET_VSTART	8
 #define TARGET_VSTOP	9
 #define TARGET_VSUSP	10
-#define TARGET_VEOL	11
+/* VDSUSP not supported */
 #define TARGET_VREPRINT	12
 #define TARGET_VDISCARD	13
 #define TARGET_VWERASE	14
 #define TARGET_VLNEXT	15
-#define TARGET_VEOL2	16
+#define TARGET_VEOF	16
+#define TARGET_VEOL	17
 
 /* ioctls */
 
@@ -154,7 +170,7 @@
 #define TARGET_TIOCEXCL	0x740d		/* set exclusive use of tty */
 #define TARGET_TIOCNXCL	0x740e		/* reset exclusive use of tty */
 #define TARGET_TIOCOUTQ	0x7472		/* output queue size */
-#define TARGET_TIOCSTI		0x5472		/* simulate terminal input */
+#define TARGET_TIOCSTI	0x5472		/* simulate terminal input */
 #define TARGET_TIOCMGET	0x741d		/* get all modem bits */
 #define TARGET_TIOCMBIS	0x741b		/* bis modem bits */
 #define TARGET_TIOCMBIC	0x741c		/* bic modem bits */

Modified: trunk/src/host/qemu-neo1973/linux-user/mmap.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/mmap.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/mmap.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -30,13 +30,14 @@
 //#define DEBUG_MMAP
 
 /* NOTE: all the constants are the HOST ones, but addresses are target. */
-int target_mprotect(target_ulong start, target_ulong len, int prot)
+int target_mprotect(abi_ulong start, abi_ulong len, int prot)
 {
-    target_ulong end, host_start, host_end, addr;
+    abi_ulong 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,
+    printf("mprotect: start=0x" TARGET_FMT_lx
+	   "len=0x" TARGET_FMT_lx " prot=%c%c%c\n", start, len,
            prot & PROT_READ ? 'r' : '-',
            prot & PROT_WRITE ? 'w' : '-',
            prot & PROT_EXEC ? 'x' : '-');
@@ -95,11 +96,11 @@
 }
 
 /* map an incomplete host page */
-static int mmap_frag(target_ulong real_start,
-                     target_ulong start, target_ulong end,
-                     int prot, int flags, int fd, target_ulong offset)
+static int mmap_frag(abi_ulong real_start,
+                     abi_ulong start, abi_ulong end,
+                     int prot, int flags, int fd, abi_ulong offset)
 {
-    target_ulong real_end, ret, addr;
+    abi_ulong real_end, ret, addr;
     void *host_start;
     int prot1, prot_new;
 
@@ -151,22 +152,23 @@
 }
 
 /* NOTE: all the constants are the HOST ones */
-long target_mmap(target_ulong start, target_ulong len, int prot,
-                 int flags, int fd, target_ulong offset)
+abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
+                     int flags, int fd, abi_ulong offset)
 {
-    target_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
-    long host_start;
+    abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
+    unsigned long host_start;
 #if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) || \
         defined(__ia64) || defined(__mips__)
-    static target_ulong last_start = 0x40000000;
+    static abi_ulong last_start = 0x40000000;
 #elif defined(__CYGWIN__)
     /* Cygwin doesn't have a whole lot of address space.  */
-    static target_ulong last_start = 0x18000000;
+    static abi_ulong last_start = 0x18000000;
 #endif
 
 #ifdef DEBUG_MMAP
     {
-        printf("mmap: start=0x%lx len=0x%lx prot=%c%c%c flags=",
+        printf("mmap: start=0x" TARGET_FMT_lx
+	       " len=0x" TARGET_FMT_lx " prot=%c%c%c flags=",
                start, len,
                prot & PROT_READ ? 'r' : '-',
                prot & PROT_WRITE ? 'w' : '-',
@@ -186,7 +188,7 @@
             printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE);
             break;
         }
-        printf("fd=%d offset=%lx\n", fd, offset);
+        printf("fd=%d offset=" TARGET_FMT_lx "\n", fd, offset);
     }
 #endif
 
@@ -209,34 +211,59 @@
             last_start += HOST_PAGE_ALIGN(len);
         }
 #endif
-        if (0 && qemu_host_page_size != qemu_real_host_page_size) {
-            /* NOTE: this code is only for debugging with '-p' option */
-            /* ??? Can also occur when TARGET_PAGE_SIZE > host page size.  */
-            /* reserve a memory area */
-            /* ??? This needs fixing for remapping.  */
-abort();
-            host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE;
-            real_start = (long)mmap(g2h(real_start), host_len, PROT_NONE,
-                                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-            if (real_start == -1)
-                return real_start;
-            real_end = real_start + host_len;
-            start = HOST_PAGE_ALIGN(real_start);
-            end = start + HOST_PAGE_ALIGN(len);
-            if (start > real_start)
-                munmap((void *)real_start, start - real_start);
-            if (end < real_end)
-                munmap((void *)end, real_end - end);
-            /* use it as a fixed mapping */
-            flags |= MAP_FIXED;
+            host_offset = offset & qemu_host_page_mask;
+            host_len = len + offset - host_offset;
+
+        if (qemu_host_page_size > qemu_real_host_page_size) {
+            /*
+             * The guest expects to see mmapped areas aligned to it's pagesize.
+             * If the host's real page size is smaller than the guest's, we need
+             * to fixup the maps. It is done by allocating a larger area,
+             * displacing the map (if needed) and finally chopping off the spare
+             * room at the edges.
+             */
+
+            /*
+             * We assume qemu_host_page_size is always the same as
+             * TARGET_PAGE_SIZE, see exec.c. qemu_real_host_page_size is the
+             * hosts real page size.
+             */
+            abi_ulong host_end;
+            unsigned long host_aligned_start;
+
+            host_len = HOST_PAGE_ALIGN(host_len + qemu_host_page_size
+                                       - qemu_real_host_page_size);
+            host_start = (unsigned long) mmap(real_start ?
+					      g2h(real_start) : NULL,
+					      host_len, prot, flags,
+					      fd, host_offset);
+            if (host_start == -1)
+                return -1;
+
+            host_end = host_start + host_len;
+
+            /* Find start and end, aligned to the targets pagesize with-in the
+               large mmaped area.  */
+            host_aligned_start = TARGET_PAGE_ALIGN(host_start);
+            if (!(flags & MAP_ANONYMOUS))
+                host_aligned_start += offset - host_offset;
+
+            start = h2g(host_aligned_start);
+            end = start + TARGET_PAGE_ALIGN(len);
+
+            /* Chop off the leftovers, if any.  */
+            if (host_aligned_start > host_start)
+                munmap((void *)host_start, host_aligned_start - host_start);
+            if (end < host_end)
+                munmap((void *)g2h(end), host_end - end);
+
+            goto the_end1;
         } else {
             /* if not fixed, no need to do anything */
-            host_offset = offset & qemu_host_page_mask;
-            host_len = len + offset - host_offset;
             host_start = (long)mmap(real_start ? g2h(real_start) : NULL,
                                     host_len, prot, flags, fd, host_offset);
             if (host_start == -1)
-                return host_start;
+                return -1;
             /* update start so that it points to the file position at 'offset' */
             if (!(flags & MAP_ANONYMOUS))
                 host_start += offset - host_offset;
@@ -267,7 +294,7 @@
                               MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
                               -1, 0);
         if (retaddr == -1)
-            return retaddr;
+            return -1;
         pread(fd, g2h(start), len, offset);
         if (!(prot & PROT_WRITE)) {
             ret = target_mprotect(start, len, prot);
@@ -300,7 +327,7 @@
                         prot, flags, fd,
                         offset + real_end - qemu_host_page_size - start);
         if (ret == -1)
-            return ret;
+            return -1;
         real_end -= qemu_host_page_size;
     }
 
@@ -314,22 +341,22 @@
         ret = (long)mmap(g2h(real_start), real_end - real_start,
                          prot, flags, fd, offset1);
         if (ret == -1)
-            return ret;
+            return -1;
     }
  the_end1:
     page_set_flags(start, start + len, prot | PAGE_VALID);
  the_end:
 #ifdef DEBUG_MMAP
-    printf("ret=0x%lx\n", (long)start);
+    printf("ret=0x%llx\n", start);
     page_dump(stdout);
     printf("\n");
 #endif
     return start;
 }
 
-int target_munmap(target_ulong start, target_ulong len)
+int target_munmap(abi_ulong start, abi_ulong len)
 {
-    target_ulong end, real_start, real_end, addr;
+    abi_ulong end, real_start, real_end, addr;
     int prot, ret;
 
 #ifdef DEBUG_MMAP
@@ -370,7 +397,7 @@
 
     /* unmap what we can */
     if (real_start < real_end) {
-        ret = munmap((void *)real_start, real_end - real_start);
+        ret = munmap(g2h(real_start), real_end - real_start);
         if (ret != 0)
             return ret;
     }
@@ -381,26 +408,27 @@
 
 /* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED
    blocks which have been allocated starting on a host page */
-long target_mremap(target_ulong old_addr, target_ulong old_size,
-                   target_ulong new_size, unsigned long flags,
-                   target_ulong new_addr)
+abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
+                       abi_ulong new_size, unsigned long flags,
+                       abi_ulong new_addr)
 {
     int prot;
+    unsigned long host_addr;
 
     /* XXX: use 5 args syscall */
-    new_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags);
-    if (new_addr == -1)
-        return new_addr;
-    new_addr = h2g(new_addr);
+    host_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags);
+    if (host_addr == -1)
+        return -1;
+    new_addr = h2g(host_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;
 }
 
-int target_msync(target_ulong start, target_ulong len, int flags)
+int target_msync(abi_ulong start, abi_ulong len, int flags)
 {
-    target_ulong end;
+    abi_ulong end;
 
     if (start & ~TARGET_PAGE_MASK)
         return -EINVAL;

Modified: trunk/src/host/qemu-neo1973/linux-user/ppc/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc/syscall.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc/syscall.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -44,11 +44,15 @@
 
 /* ioctls */
 struct target_revectored_struct {
-	target_ulong __map[8];			/* 256 bits */
+	abi_ulong __map[8];			/* 256 bits */
 };
 
 /*
  * flags masks
  */
 
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+#define UNAME_MACHINE "ppc64"
+#else
 #define UNAME_MACHINE "ppc"
+#endif

Modified: trunk/src/host/qemu-neo1973/linux-user/ppc/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc/syscall_nr.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc/syscall_nr.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -193,19 +193,23 @@
 #define TARGET_NR_vfork                  189
 #define TARGET_NR_ugetrlimit             190     /* SuS compliant getrlimit */
 #define TARGET_NR_readahead              191
+#if !defined(TARGET_PPC64) || defined(TARGET_ABI32)
 #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
+#endif
 #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
+#if !defined(TARGET_PPC64) || defined(TARGET_ABI32)
 #define TARGET_NR_fcntl64                204
+#endif
 #define TARGET_NR_madvise                205
 #define TARGET_NR_mincore                206
 #define TARGET_NR_gettid                 207
@@ -227,7 +231,9 @@
 #define TARGET_NR_sched_getaffinity      223
 /* 224 currently unused */
 #define TARGET_NR_tuxcall                225
+#if !defined(TARGET_PPC64) || defined(TARGET_ABI32)
 #define TARGET_NR_sendfile64             226
+#endif
 #define TARGET_NR_io_setup               227
 #define TARGET_NR_io_destroy             228
 #define TARGET_NR_io_getevents           229
@@ -255,4 +261,65 @@
 #define TARGET_NR_utimes                 251
 #define TARGET_NR_statfs64               252
 #define TARGET_NR_fstatfs64              253
+#if !defined(TARGET_PPC64) || defined(TARGET_ABI32)
 #define TARGET_NR_fadvise64_64           254
+#endif
+#define TARGET_NR_rtas		255
+#define TARGET_NR_sys_debug_setcontext 256
+/* Number 257 is reserved for vserver */
+#define TARGET_NR_migrate_pages	258
+#define TARGET_NR_mbind		259
+#define TARGET_NR_get_mempolicy	260
+#define TARGET_NR_set_mempolicy	261
+#define TARGET_NR_mq_open		262
+#define TARGET_NR_mq_unlink		263
+#define TARGET_NR_mq_timedsend	264
+#define TARGET_NR_mq_timedreceive	265
+#define TARGET_NR_mq_notify		266
+#define TARGET_NR_mq_getsetattr	267
+#define TARGET_NR_kexec_load		268
+#define TARGET_NR_add_key		269
+#define TARGET_NR_request_key	270
+#define TARGET_NR_keyctl		271
+#define TARGET_NR_waitid		272
+#define TARGET_NR_ioprio_set		273
+#define TARGET_NR_ioprio_get		274
+#define TARGET_NR_inotify_init	275
+#define TARGET_NR_inotify_add_watch	276
+#define TARGET_NR_inotify_rm_watch	277
+#define TARGET_NR_spu_run		278
+#define TARGET_NR_spu_create		279
+#define TARGET_NR_pselect6		280
+#define TARGET_NR_ppoll		281
+#define TARGET_NR_unshare		282
+#define TARGET_NR_splice		283
+#define TARGET_NR_tee		284
+#define TARGET_NR_vmsplice		285
+#define TARGET_NR_openat		286
+#define TARGET_NR_mkdirat		287
+#define TARGET_NR_mknodat		288
+#define TARGET_NR_fchownat		289
+#define TARGET_NR_futimesat		290
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+#define TARGET_NR_newfstatat		291
+#else
+#define TARGET_NR_fstatat64		291
+#endif
+#define TARGET_NR_unlinkat		292
+#define TARGET_NR_renameat		293
+#define TARGET_NR_linkat		294
+#define TARGET_NR_symlinkat		295
+#define TARGET_NR_readlinkat		296
+#define TARGET_NR_fchmodat		297
+#define TARGET_NR_faccessat		298
+#define TARGET_NR_get_robust_list	299
+#define TARGET_NR_set_robust_list	300
+#define TARGET_NR_move_pages		301
+#define TARGET_NR_getcpu		302
+#define TARGET_NR_epoll_pwait	303
+#define TARGET_NR_utimensat		304
+#define TARGET_NR_signalfd		305
+#define TARGET_NR_timerfd		306
+#define TARGET_NR_eventfd		307
+#define TARGET_NR_sync_file_range2	308
+#define TARGET_NR_fallocate		309

Added: trunk/src/host/qemu-neo1973/linux-user/ppc/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc/target_signal.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc/target_signal.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+	abi_ulong ss_sp;
+	abi_long ss_flags;
+	abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK     1
+#define TARGET_SS_DISABLE     2
+
+#define TARGET_MINSIGSTKSZ    2048
+#define TARGET_SIGSTKSZ       8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUPPCState *state)
+{
+    return state->gpr[1];
+}
+
+#endif /* TARGET_SIGNAL_H */

Modified: trunk/src/host/qemu-neo1973/linux-user/ppc/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc/termbits.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc/termbits.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -47,6 +47,7 @@
 #define TARGET_IXANY	0004000
 #define TARGET_IUCLC	0010000
 #define TARGET_IMAXBEL	0020000
+#define	TARGET_IUTF8	0040000
 
 /* c_oflag bits */
 #define TARGET_OPOST	0000001
@@ -69,6 +70,7 @@
 #define   TARGET_TAB1	00002000
 #define   TARGET_TAB2	00004000
 #define   TARGET_TAB3	00006000
+#define   TARGET_XTABS	00006000	/* required by POSIX to == TAB3 */
 #define TARGET_CRDLY	00030000
 #define   TARGET_CR0	00000000
 #define   TARGET_CR1	00010000
@@ -83,7 +85,6 @@
 #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
@@ -135,7 +136,8 @@
 #define TARGET_HUPCL	00040000
 
 #define TARGET_CLOCAL	00100000
-#define TARGET_CRTSCTS	  020000000000		/* flow control */
+#define TARGET_CMSPAR	010000000000		/* mark or space (stick) parity */
+#define TARGET_CRTSCTS	020000000000		/* flow control */
 
 /* c_lflag bits */
 #define TARGET_ISIG	0x00000080

Modified: trunk/src/host/qemu-neo1973/linux-user/qemu.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/qemu.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/qemu.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,14 +1,25 @@
 #ifndef QEMU_H
 #define QEMU_H
 
-#include "thunk.h"
-
 #include <signal.h>
 #include <string.h>
-#include "syscall_defs.h"
 
 #include "cpu.h"
+
+#ifdef TARGET_ABI32
+typedef uint32_t abi_ulong;
+typedef int32_t abi_long;
+#define TARGET_ABI_BITS 32
+#else
+typedef target_ulong abi_ulong;
+typedef target_long abi_long;
+#define TARGET_ABI_BITS TARGET_LONG_BITS
+#endif
+
+#include "thunk.h"
+#include "syscall_defs.h"
 #include "syscall.h"
+#include "target_signal.h"
 #include "gdbstub.h"
 
 /* This struct is used to hold certain information about the image.
@@ -16,19 +27,20 @@
  * task_struct fields in the kernel
  */
 struct image_info {
-	unsigned long	start_code;
-	unsigned long	end_code;
-        unsigned long   start_data;
-	unsigned long	end_data;
-	unsigned long	start_brk;
-	unsigned long	brk;
-	unsigned long	start_mmap;
-	unsigned long	mmap;
-	unsigned long	rss;
-	unsigned long	start_stack;
-	unsigned long	entry;
-        target_ulong    code_offset;
-        target_ulong    data_offset;
+        abi_ulong       load_addr;
+        abi_ulong       start_code;
+        abi_ulong       end_code;
+        abi_ulong       start_data;
+        abi_ulong       end_data;
+        abi_ulong       start_brk;
+        abi_ulong       brk;
+        abi_ulong       start_mmap;
+        abi_ulong       mmap;
+        abi_ulong       rss;
+        abi_ulong       start_stack;
+        abi_ulong       entry;
+        abi_ulong       code_offset;
+        abi_ulong       data_offset;
         char            **host_argv;
 	int		personality;
 };
@@ -65,7 +77,7 @@
     int swi_errno;
 #endif
 #if defined(TARGET_I386) && !defined(TARGET_X86_64)
-    target_ulong target_v86;
+    abi_ulong target_v86;
     struct vm86_saved_state vm86_saved_regs;
     struct target_vm86plus_struct vm86plus;
     uint32_t v86flags;
@@ -103,7 +115,7 @@
 struct linux_binprm {
         char buf[128];
         void *page[MAX_ARG_PAGES];
-        unsigned long p;
+        abi_ulong p;
 	int fd;
         int e_uid, e_gid;
         int argc, envc;
@@ -113,8 +125,8 @@
 };
 
 void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
-target_ulong loader_build_argptr(int envc, int argc, target_ulong sp,
-                                 target_ulong stringp, int push_ptr);
+abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
+                              abi_ulong stringp, int push_ptr);
 int loader_exec(const char * filename, char ** argv, char ** envp,
              struct target_pt_regs * regs, struct image_info *infop);
 
@@ -122,14 +134,20 @@
                     struct image_info * info);
 int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                     struct image_info * info);
+#ifdef TARGET_HAS_ELFLOAD32
+int load_elf_binary_multi(struct linux_binprm *bprm,
+                          struct target_pt_regs *regs,
+                          struct image_info *info);
+#endif
 
-void memcpy_to_target(target_ulong dest, const void *src,
+void memcpy_to_target(abi_ulong dest, const void *src,
                       unsigned long len);
-void target_set_brk(target_ulong new_brk);
-long do_brk(target_ulong new_brk);
+void target_set_brk(abi_ulong new_brk);
+abi_long do_brk(abi_ulong new_brk);
 void syscall_init(void);
-long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
-                long arg4, long arg5, long arg6);
+abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
+                    abi_long arg2, abi_long arg3, abi_long arg4,
+                    abi_long arg5, abi_long arg6);
 void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
 extern CPUState *global_env;
 void cpu_loop(CPUState *env);
@@ -147,24 +165,30 @@
 void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
 long do_sigreturn(CPUState *env);
 long do_rt_sigreturn(CPUState *env);
+int do_sigaltstack(const struct target_sigaltstack *uss,
+                   struct target_sigaltstack *uoss,
+                   abi_ulong sp);
 
 #ifdef TARGET_I386
 /* vm86.c */
 void save_v86_state(CPUX86State *env);
 void handle_vm86_trap(CPUX86State *env, int trapno);
 void handle_vm86_fault(CPUX86State *env);
-int do_vm86(CPUX86State *env, long subfunction, target_ulong v86_addr);
+int do_vm86(CPUX86State *env, long subfunction, abi_ulong v86_addr);
+#elif defined(TARGET_SPARC64)
+void sparc64_set_context(CPUSPARCState *env);
+void sparc64_get_context(CPUSPARCState *env);
 #endif
 
 /* mmap.c */
-int target_mprotect(target_ulong start, target_ulong len, int prot);
-long target_mmap(target_ulong start, target_ulong len, int prot,
-                 int flags, int fd, target_ulong offset);
-int target_munmap(target_ulong start, target_ulong len);
-long target_mremap(target_ulong old_addr, target_ulong old_size,
-                   target_ulong new_size, unsigned long flags,
-                   target_ulong new_addr);
-int target_msync(target_ulong start, target_ulong len, int flags);
+int target_mprotect(abi_ulong start, abi_ulong len, int prot);
+abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
+                     int flags, int fd, abi_ulong offset);
+int target_munmap(abi_ulong start, abi_ulong len);
+abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
+                       abi_ulong new_size, unsigned long flags,
+                       abi_ulong new_addr);
+int target_msync(abi_ulong start, abi_ulong len, int flags);
 
 /* user access */
 
@@ -246,7 +270,7 @@
 
 /* Lock an area of guest memory into the host.  If copy is true then the
    host area will have the same contents as the guest.  */
-static inline void *lock_user(target_ulong guest_addr, long len, int copy)
+static inline void *lock_user(abi_ulong guest_addr, long len, int copy)
 {
 #ifdef DEBUG_REMAP
     void *addr;
@@ -263,8 +287,8 @@
 
 /* Unlock an area of guest memory.  The first LEN bytes must be flushed back
    to guest memory.  */
-static inline void unlock_user(void *host_addr, target_ulong guest_addr,
-                                long len)
+static inline void unlock_user(void *host_addr, abi_ulong guest_addr,
+                               long len)
 {
 #ifdef DEBUG_REMAP
     if (host_addr == g2h(guest_addr))
@@ -276,13 +300,13 @@
 }
 
 /* Return the length of a string in target memory.  */
-static inline int target_strlen(target_ulong ptr)
+static inline int target_strlen(abi_ulong ptr)
 {
   return strlen(g2h(ptr));
 }
 
 /* Like lock_user but for null terminated strings.  */
-static inline void *lock_user_string(target_ulong guest_addr)
+static inline void *lock_user_string(abi_ulong guest_addr)
 {
     long len;
     len = target_strlen(guest_addr) + 1;
@@ -303,7 +327,7 @@
 #define tput32(addr, val) stl(addr, val)
 #define tget64(addr) ldq(addr)
 #define tput64(addr, val) stq(addr, val)
-#if TARGET_LONG_BITS == 64
+#if TARGET_ABI_BITS == 64
 #define tgetl(addr) ldq(addr)
 #define tputl(addr, val) stq(addr, val)
 #else

Modified: trunk/src/host/qemu-neo1973/linux-user/sh4/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sh4/syscall_nr.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sh4/syscall_nr.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -226,6 +226,7 @@
 #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
@@ -288,5 +289,40 @@
 #define TARGET_NR_add_key		285
 #define TARGET_NR_request_key	286
 #define TARGET_NR_keyctl		287
-
-#define TARGET_NR_readahead             225        /* XXXXX */
+#define TARGET_NR_ioprio_set		288
+#define TARGET_NR_ioprio_get		289
+#define TARGET_NR_inotify_init	290
+#define TARGET_NR_inotify_add_watch	291
+#define TARGET_NR_inotify_rm_watch	292
+/* 293 is unused */
+#define TARGET_NR_migrate_pages	294
+#define TARGET_NR_openat		295
+#define TARGET_NR_mkdirat		296
+#define TARGET_NR_mknodat		297
+#define TARGET_NR_fchownat		298
+#define TARGET_NR_futimesat		299
+#define TARGET_NR_fstatat64		300
+#define TARGET_NR_unlinkat		301
+#define TARGET_NR_renameat		302
+#define TARGET_NR_linkat		303
+#define TARGET_NR_symlinkat		304
+#define TARGET_NR_readlinkat		305
+#define TARGET_NR_fchmodat		306
+#define TARGET_NR_faccessat		307
+#define TARGET_NR_pselect6		308
+#define TARGET_NR_ppoll		309
+#define TARGET_NR_unshare		310
+#define TARGET_NR_set_robust_list	311
+#define TARGET_NR_get_robust_list	312
+#define TARGET_NR_splice		313
+#define TARGET_NR_sync_file_range	314
+#define TARGET_NR_tee		315
+#define TARGET_NR_vmsplice		316
+#define TARGET_NR_move_pages		317
+#define TARGET_NR_getcpu		318
+#define TARGET_NR_epoll_pwait	319
+#define TARGET_NR_utimensat		320
+#define TARGET_NR_signalfd		321
+#define TARGET_NR_timerfd		322
+#define TARGET_NR_eventfd		323
+#define TARGET_NR_fallocate		324

Added: trunk/src/host/qemu-neo1973/linux-user/sh4/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sh4/target_signal.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sh4/target_signal.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,24 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+	abi_ulong ss_sp;
+	abi_long ss_flags;
+	abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK     1
+#define TARGET_SS_DISABLE     2
+
+#define TARGET_MINSIGSTKSZ    2048
+#define TARGET_SIGSTKSZ       8192
+
+#endif /* TARGET_SIGNAL_H */

Modified: trunk/src/host/qemu-neo1973/linux-user/signal.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/signal.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/signal.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -27,6 +27,7 @@
 #include <sys/ucontext.h>
 
 #include "qemu.h"
+#include "target_signal.h"
 
 //#define DEBUG_SIGNAL
 
@@ -45,6 +46,12 @@
                              first signal, we put it here */
 };
 
+struct target_sigaltstack target_sigaltstack_used = {
+    .ss_sp = 0,
+    .ss_size = 0,
+    .ss_flags = TARGET_SS_DISABLE,
+};
+
 static struct emulated_sigaction sigact_table[TARGET_NSIG];
 static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
 static struct sigqueue *first_free; /* first free siginfo queue entry */
@@ -92,6 +99,18 @@
 };
 static uint8_t target_to_host_signal_table[65];
 
+static inline int on_sig_stack(unsigned long sp)
+{
+    return (sp - target_sigaltstack_used.ss_sp
+            < target_sigaltstack_used.ss_size);
+}
+
+static inline int sas_ss_flags(unsigned long sp)
+{
+    return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
+            : on_sig_stack(sp) ? SS_ONSTACK : 0);
+}
+
 static inline int host_to_target_signal(int sig)
 {
     return host_to_target_signal_table[sig];
@@ -115,12 +134,12 @@
         if (sigmask & (1 << i))
             target_sigmask |= 1 << (host_to_target_signal(i + 1) - 1);
     }
-#if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32
+#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 32
     d->sig[0] = target_sigmask;
     for(i = 1;i < TARGET_NSIG_WORDS; i++) {
         d->sig[i] = ((unsigned long *)s)[i];
     }
-#elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2
+#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2
     d->sig[0] = target_sigmask;
     d->sig[1] = sigmask >> 32;
 #else
@@ -142,7 +161,7 @@
 {
     int i;
     unsigned long sigmask;
-    target_ulong target_sigmask;
+    abi_ulong target_sigmask;
 
     target_sigmask = s->sig[0];
     sigmask = 0;
@@ -150,16 +169,16 @@
         if (target_sigmask & (1 << i))
             sigmask |= 1 << (target_to_host_signal(i + 1) - 1);
     }
-#if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32
+#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 32
     ((unsigned long *)d)[0] = sigmask;
     for(i = 1;i < TARGET_NSIG_WORDS; i++) {
         ((unsigned long *)d)[i] = s->sig[i];
     }
-#elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2
+#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2
     ((unsigned long *)d)[0] = sigmask | ((unsigned long)(s->sig[1]) << 32);
 #else
 #warning target_to_host_sigset
-#endif /* TARGET_LONG_BITS */
+#endif /* TARGET_ABI_BITS */
 }
 
 void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
@@ -172,7 +191,7 @@
     target_to_host_sigset_internal(d, &s1);
 }
 
-void host_to_target_old_sigset(target_ulong *old_sigset,
+void host_to_target_old_sigset(abi_ulong *old_sigset,
                                const sigset_t *sigset)
 {
     target_sigset_t d;
@@ -181,7 +200,7 @@
 }
 
 void target_to_host_old_sigset(sigset_t *sigset,
-                               const target_ulong *old_sigset)
+                               const abi_ulong *old_sigset)
 {
     target_sigset_t d;
     int i;
@@ -214,7 +233,7 @@
         tinfo->_sifields._rt._uid = info->si_uid;
         /* XXX: potential problem if 64 bit */
         tinfo->_sifields._rt._sigval.sival_ptr =
-            (target_ulong)info->si_value.sival_ptr;
+            (abi_ulong)info->si_value.sival_ptr;
     }
 }
 
@@ -336,7 +355,7 @@
 {
     struct emulated_sigaction *k;
     struct sigqueue *q, **pq;
-    target_ulong handler;
+    abi_ulong handler;
 
 #if defined(DEBUG_SIGNAL)
     fprintf(stderr, "queue_signal: sig=%d\n",
@@ -419,12 +438,76 @@
     }
 }
 
+/* do_sigaltstack() returns target values and errnos. */
+int do_sigaltstack(const struct target_sigaltstack *uss,
+                   struct target_sigaltstack *uoss,
+                   abi_ulong sp)
+{
+    int ret;
+    struct target_sigaltstack oss;
+
+    /* XXX: test errors */
+    if(uoss)
+    {
+        __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp);
+        __put_user(target_sigaltstack_used.ss_size, &oss.ss_size);
+        __put_user(sas_ss_flags(sp), &oss.ss_flags);
+    }
+
+    if(uss)
+    {
+	struct target_sigaltstack ss;
+
+	ret = -TARGET_EFAULT;
+	if (!access_ok(VERIFY_READ, uss, sizeof(*uss))
+	    || __get_user(ss.ss_sp, &uss->ss_sp)
+	    || __get_user(ss.ss_size, &uss->ss_size)
+	    || __get_user(ss.ss_flags, &uss->ss_flags))
+            goto out;
+
+	ret = -TARGET_EPERM;
+	if (on_sig_stack(sp))
+            goto out;
+
+	ret = -TARGET_EINVAL;
+	if (ss.ss_flags != TARGET_SS_DISABLE
+            && ss.ss_flags != TARGET_SS_ONSTACK
+            && ss.ss_flags != 0)
+            goto out;
+
+	if (ss.ss_flags == TARGET_SS_DISABLE) {
+            ss.ss_size = 0;
+            ss.ss_sp = 0;
+	} else {
+            ret = -TARGET_ENOMEM;
+            if (ss.ss_size < MINSIGSTKSZ)
+                goto out;
+	}
+
+        target_sigaltstack_used.ss_sp = ss.ss_sp;
+        target_sigaltstack_used.ss_size = ss.ss_size;
+    }
+
+    if (uoss) {
+        ret = -TARGET_EFAULT;
+        if (!access_ok(VERIFY_WRITE, uoss, sizeof(oss)))
+            goto out;
+        memcpy(uoss, &oss, sizeof(oss));
+    }
+
+    ret = 0;
+out:
+    return ret;
+}
+
+/* do_sigaction() return host values and errnos */
 int do_sigaction(int sig, const struct target_sigaction *act,
                  struct target_sigaction *oact)
 {
     struct emulated_sigaction *k;
     struct sigaction act1;
     int host_sig;
+    int ret = 0;
 
     if (sig < 1 || sig > TARGET_NSIG || sig == SIGKILL || sig == SIGSTOP)
         return -EINVAL;
@@ -466,10 +549,10 @@
             } else {
                 act1.sa_sigaction = host_signal_handler;
             }
-            sigaction(host_sig, &act1, NULL);
+            ret = sigaction(host_sig, &act1, NULL);
         }
     }
-    return 0;
+    return ret;
 }
 
 #ifndef offsetof
@@ -499,29 +582,29 @@
 };
 
 struct target_xmmreg {
-	target_ulong element[4];
+	abi_ulong element[4];
 };
 
 struct target_fpstate {
 	/* Regular FPU environment */
-	target_ulong 	cw;
-	target_ulong	sw;
-	target_ulong	tag;
-	target_ulong	ipoff;
-	target_ulong	cssel;
-	target_ulong	dataoff;
-	target_ulong	datasel;
+        abi_ulong       cw;
+        abi_ulong       sw;
+        abi_ulong       tag;
+        abi_ulong       ipoff;
+        abi_ulong       cssel;
+        abi_ulong       dataoff;
+        abi_ulong       datasel;
 	struct target_fpreg	_st[8];
 	uint16_t	status;
 	uint16_t	magic;		/* 0xffff = regular FPU data only */
 
 	/* FXSR FPU environment */
-	target_ulong	_fxsr_env[6];	/* FXSR FPU env is ignored */
-	target_ulong	mxcsr;
-	target_ulong	reserved;
+        abi_ulong       _fxsr_env[6];   /* FXSR FPU env is ignored */
+        abi_ulong       mxcsr;
+        abi_ulong       reserved;
 	struct target_fpxreg	_fxsr_st[8];	/* FXSR FPU reg data is ignored */
 	struct target_xmmreg	_xmm[8];
-	target_ulong	padding[56];
+        abi_ulong       padding[56];
 };
 
 #define X86_FXSR_MAGIC		0x0000
@@ -531,35 +614,29 @@
 	uint16_t fs, __fsh;
 	uint16_t es, __esh;
 	uint16_t ds, __dsh;
-	target_ulong edi;
-	target_ulong esi;
-	target_ulong ebp;
-	target_ulong esp;
-	target_ulong ebx;
-	target_ulong edx;
-	target_ulong ecx;
-	target_ulong eax;
-	target_ulong trapno;
-	target_ulong err;
-	target_ulong eip;
+        abi_ulong edi;
+        abi_ulong esi;
+        abi_ulong ebp;
+        abi_ulong esp;
+        abi_ulong ebx;
+        abi_ulong edx;
+        abi_ulong ecx;
+        abi_ulong eax;
+        abi_ulong trapno;
+        abi_ulong err;
+        abi_ulong eip;
 	uint16_t cs, __csh;
-	target_ulong eflags;
-	target_ulong esp_at_signal;
+        abi_ulong eflags;
+        abi_ulong esp_at_signal;
 	uint16_t ss, __ssh;
-        target_ulong fpstate; /* pointer */
-	target_ulong oldmask;
-	target_ulong cr2;
+        abi_ulong fpstate; /* pointer */
+        abi_ulong oldmask;
+        abi_ulong cr2;
 };
 
-typedef struct target_sigaltstack {
-	target_ulong ss_sp;
-	int ss_flags;
-	target_ulong ss_size;
-} target_stack_t;
-
 struct target_ucontext {
-        target_ulong	  tuc_flags;
-	target_ulong      tuc_link;
+        abi_ulong         tuc_flags;
+        abi_ulong         tuc_link;
 	target_stack_t	  tuc_stack;
 	struct target_sigcontext tuc_mcontext;
 	target_sigset_t	  tuc_sigmask;	/* mask last for extensibility */
@@ -567,20 +644,20 @@
 
 struct sigframe
 {
-    target_ulong pretcode;
+    abi_ulong pretcode;
     int sig;
     struct target_sigcontext sc;
     struct target_fpstate fpstate;
-    target_ulong extramask[TARGET_NSIG_WORDS-1];
+    abi_ulong extramask[TARGET_NSIG_WORDS-1];
     char retcode[8];
 };
 
 struct rt_sigframe
 {
-    target_ulong pretcode;
+    abi_ulong pretcode;
     int sig;
-    target_ulong pinfo;
-    target_ulong puc;
+    abi_ulong pinfo;
+    abi_ulong puc;
     struct target_siginfo info;
     struct target_ucontext uc;
     struct target_fpstate fpstate;
@@ -640,16 +717,14 @@
 
 	/* Default to using normal stack */
 	esp = env->regs[R_ESP];
-#if 0
 	/* This is the X/Open sanctioned signal stack switching.  */
-	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (sas_ss_flags(esp) == 0)
-			esp = current->sas_ss_sp + current->sas_ss_size;
-	}
+        if (ka->sa.sa_flags & TARGET_SA_ONSTACK) {
+            if (sas_ss_flags(esp) == 0)
+                esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+        }
 
 	/* This is the legacy signal stack switching. */
 	else
-#endif
         if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
             !(ka->sa.sa_flags & TARGET_SA_RESTORER) &&
             ka->sa.sa_restorer) {
@@ -741,8 +816,8 @@
 		    	   ? current->exec_domain->signal_invmap[sig]
 			   : */sig),
 			  &frame->sig);
-	err |= __put_user((target_ulong)&frame->info, &frame->pinfo);
-	err |= __put_user((target_ulong)&frame->uc, &frame->puc);
+	err |= __put_user((abi_ulong)&frame->info, &frame->pinfo);
+	err |= __put_user((abi_ulong)&frame->uc, &frame->puc);
 	err |= copy_siginfo_to_user(&frame->info, info);
 	if (err)
 		goto give_sigsegv;
@@ -750,11 +825,11 @@
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->uc.tuc_flags);
 	err |= __put_user(0, &frame->uc.tuc_link);
-	err |= __put_user(/*current->sas_ss_sp*/ 0,
+	err |= __put_user(target_sigaltstack_used.ss_sp,
 			  &frame->uc.tuc_stack.ss_sp);
-	err |= __put_user(/* sas_ss_flags(regs->esp) */ 0,
+	err |= __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
 			  &frame->uc.tuc_stack.ss_flags);
-	err |= __put_user(/* current->sas_ss_size */ 0,
+	err |= __put_user(target_sigaltstack_used.ss_size,
 			  &frame->uc.tuc_stack.ss_size);
 	err |= setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate,
 			        env, set->sig[0]);
@@ -880,7 +955,6 @@
 {
 	struct rt_sigframe *frame = (struct rt_sigframe *)g2h(env->regs[R_ESP] - 4);
         sigset_t set;
-        //	stack_t st;
 	int eax;
 
 #if 0
@@ -893,13 +967,9 @@
 	if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
 		goto badframe;
 
-#if 0
-	if (__copy_from_user(&st, &frame->uc.tuc_stack, sizeof(st)))
+	if (do_sigaltstack(&frame->uc.tuc_stack, NULL, get_sp_from_cpustate(env)) == -EFAULT)
 		goto badframe;
-	/* It is more difficult to avoid calling this function than to
-	   call it and ignore errors.  */
-	do_sigaltstack(&st, NULL, regs->esp);
-#endif
+
 	return eax;
 
 badframe:
@@ -910,38 +980,32 @@
 #elif defined(TARGET_ARM)
 
 struct target_sigcontext {
-	target_ulong trap_no;
-	target_ulong error_code;
-	target_ulong oldmask;
-	target_ulong arm_r0;
-	target_ulong arm_r1;
-	target_ulong arm_r2;
-	target_ulong arm_r3;
-	target_ulong arm_r4;
-	target_ulong arm_r5;
-	target_ulong arm_r6;
-	target_ulong arm_r7;
-	target_ulong arm_r8;
-	target_ulong arm_r9;
-	target_ulong arm_r10;
-	target_ulong arm_fp;
-	target_ulong arm_ip;
-	target_ulong arm_sp;
-	target_ulong arm_lr;
-	target_ulong arm_pc;
-	target_ulong arm_cpsr;
-	target_ulong fault_address;
+	abi_ulong trap_no;
+	abi_ulong error_code;
+	abi_ulong oldmask;
+	abi_ulong arm_r0;
+	abi_ulong arm_r1;
+	abi_ulong arm_r2;
+	abi_ulong arm_r3;
+	abi_ulong arm_r4;
+	abi_ulong arm_r5;
+	abi_ulong arm_r6;
+	abi_ulong arm_r7;
+	abi_ulong arm_r8;
+	abi_ulong arm_r9;
+	abi_ulong arm_r10;
+	abi_ulong arm_fp;
+	abi_ulong arm_ip;
+	abi_ulong arm_sp;
+	abi_ulong arm_lr;
+	abi_ulong arm_pc;
+	abi_ulong arm_cpsr;
+	abi_ulong fault_address;
 };
 
-typedef struct target_sigaltstack {
-	target_ulong ss_sp;
-	int ss_flags;
-	target_ulong ss_size;
-} target_stack_t;
-
 struct target_ucontext {
-    target_ulong tuc_flags;
-    target_ulong tuc_link;
+    abi_ulong tuc_flags;
+    abi_ulong tuc_link;
     target_stack_t tuc_stack;
     struct target_sigcontext tuc_mcontext;
     target_sigset_t  tuc_sigmask;	/* mask last for extensibility */
@@ -950,8 +1014,8 @@
 struct sigframe
 {
     struct target_sigcontext sc;
-    target_ulong extramask[TARGET_NSIG_WORDS-1];
-    target_ulong retcode;
+    abi_ulong extramask[TARGET_NSIG_WORDS-1];
+    abi_ulong retcode;
 };
 
 struct rt_sigframe
@@ -960,7 +1024,7 @@
     void *puc;
     struct target_siginfo info;
     struct target_ucontext uc;
-    target_ulong retcode;
+    abi_ulong retcode;
 };
 
 #define TARGET_CONFIG_CPU_32 1
@@ -978,7 +1042,7 @@
 #define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
 #define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
 
-static const target_ulong retcodes[4] = {
+static const abi_ulong retcodes[4] = {
 	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN,
 	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN
 };
@@ -1031,13 +1095,11 @@
 {
 	unsigned long sp = regs->regs[13];
 
-#if 0
 	/*
 	 * This is the X/Open sanctioned signal stack switching.
 	 */
-	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
-		sp = current->sas_ss_sp + current->sas_ss_size;
-#endif
+	if ((ka->sa.sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
+            sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
 	/*
 	 * ATPCS B01 mandates 8-byte alignment
 	 */
@@ -1046,14 +1108,14 @@
 
 static int
 setup_return(CPUState *env, struct emulated_sigaction *ka,
-	     target_ulong *rc, void *frame, int usig)
+	     abi_ulong *rc, void *frame, int usig)
 {
-	target_ulong handler = (target_ulong)ka->sa._sa_handler;
-	target_ulong retcode;
+	abi_ulong handler = (abi_ulong)ka->sa._sa_handler;
+	abi_ulong retcode;
 	int thumb = 0;
 #if defined(TARGET_CONFIG_CPU_32)
 #if 0
-	target_ulong cpsr = env->cpsr;
+	abi_ulong cpsr = env->cpsr;
 
 	/*
 	 * Maybe we need to deliver a 32-bit signal to a 26-bit task.
@@ -1074,12 +1136,12 @@
 		else
 			cpsr &= ~T_BIT;
 	}
-#endif
-#endif
+#endif /* CONFIG_ARM_THUMB */
+#endif /* 0 */
 #endif /* TARGET_CONFIG_CPU_32 */
 
 	if (ka->sa.sa_flags & TARGET_SA_RESTORER) {
-		retcode = (target_ulong)ka->sa.sa_restorer;
+		retcode = (abi_ulong)ka->sa.sa_restorer;
 	} else {
 		unsigned int idx = thumb;
 
@@ -1089,10 +1151,10 @@
 		if (__put_user(retcodes[idx], rc))
 			return 1;
 #if 0
-		flush_icache_range((target_ulong)rc,
-				   (target_ulong)(rc + 1));
+		flush_icache_range((abi_ulong)rc,
+				   (abi_ulong)(rc + 1));
 #endif
-		retcode = ((target_ulong)rc) + thumb;
+		retcode = ((abi_ulong)rc) + thumb;
 	}
 
 	env->regs[0] = usig;
@@ -1132,18 +1194,28 @@
 			   target_sigset_t *set, CPUState *env)
 {
 	struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame));
+	struct target_sigaltstack stack;
 	int i, err = 0;
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
             return /* 1 */;
 
-	__put_user_error(&frame->info, (target_ulong *)&frame->pinfo, err);
-	__put_user_error(&frame->uc, (target_ulong *)&frame->puc, err);
+	__put_user_error(&frame->info, (abi_ulong *)&frame->pinfo, err);
+	__put_user_error(&frame->uc, (abi_ulong *)&frame->puc, err);
 	err |= copy_siginfo_to_user(&frame->info, info);
 
 	/* Clear all the bits of the ucontext we don't use.  */
 	memset(&frame->uc, 0, offsetof(struct target_ucontext, tuc_mcontext));
 
+        memset(&stack, 0, sizeof(stack));
+        __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
+        __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
+        __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
+        if (!access_ok(VERIFY_WRITE, &frame->uc.tuc_stack, sizeof(stack)))
+            err = 1;
+        else
+            memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
+
 	err |= setup_sigcontext(&frame->uc.tuc_mcontext, /*&frame->fpstate,*/
 				env, set->sig[0]);
         for(i = 0; i < TARGET_NSIG_WORDS; i++) {
@@ -1160,8 +1232,8 @@
 		 * arguments for the signal handler.
 		 *   -- Peter Maydell <pmaydell at chiark.greenend.org.uk> 2000-12-06
 		 */
-            env->regs[1] = (target_ulong)frame->pinfo;
-            env->regs[2] = (target_ulong)frame->puc;
+            env->regs[1] = (abi_ulong)frame->pinfo;
+            env->regs[2] = (abi_ulong)frame->puc;
 	}
 
         //	return err;
@@ -1270,6 +1342,9 @@
 	if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
 		goto badframe;
 
+	if (do_sigaltstack(&frame->uc.tuc_stack, NULL, get_sp_from_cpustate(env)) == -EFAULT)
+		goto badframe;
+
 #if 0
 	/* Send SIGTRAP if we're single-stepping */
 	if (ptrace_cancel_bpt(current))
@@ -1288,48 +1363,48 @@
 
 /* This is what SunOS does, so shall I. */
 struct target_sigcontext {
-        target_ulong sigc_onstack;      /* state to restore */
+        abi_ulong sigc_onstack;      /* state to restore */
 
-        target_ulong sigc_mask;         /* sigmask to restore */
-        target_ulong sigc_sp;           /* stack pointer */
-        target_ulong sigc_pc;           /* program counter */
-        target_ulong sigc_npc;          /* next program counter */
-        target_ulong sigc_psr;          /* for condition codes etc */
-        target_ulong sigc_g1;           /* User uses these two registers */
-        target_ulong sigc_o0;           /* within the trampoline code. */
+        abi_ulong sigc_mask;         /* sigmask to restore */
+        abi_ulong sigc_sp;           /* stack pointer */
+        abi_ulong sigc_pc;           /* program counter */
+        abi_ulong sigc_npc;          /* next program counter */
+        abi_ulong sigc_psr;          /* for condition codes etc */
+        abi_ulong sigc_g1;           /* User uses these two registers */
+        abi_ulong sigc_o0;           /* within the trampoline code. */
 
         /* Now comes information regarding the users window set
          * at the time of the signal.
          */
-        target_ulong sigc_oswins;       /* outstanding windows */
+        abi_ulong sigc_oswins;       /* outstanding windows */
 
         /* stack ptrs for each regwin buf */
         char *sigc_spbuf[__SUNOS_MAXWIN];
 
         /* Windows to restore after signal */
         struct {
-                target_ulong locals[8];
-                target_ulong ins[8];
+                abi_ulong locals[8];
+                abi_ulong ins[8];
         } sigc_wbuf[__SUNOS_MAXWIN];
 };
 /* A Sparc stack frame */
 struct sparc_stackf {
-        target_ulong locals[8];
-        target_ulong ins[6];
+        abi_ulong locals[8];
+        abi_ulong ins[6];
         struct sparc_stackf *fp;
-        target_ulong callers_pc;
+        abi_ulong callers_pc;
         char *structptr;
-        target_ulong xargs[6];
-        target_ulong xxargs[1];
+        abi_ulong xargs[6];
+        abi_ulong xxargs[1];
 };
 
 typedef struct {
         struct {
-                target_ulong psr;
-                target_ulong pc;
-                target_ulong npc;
-                target_ulong y;
-                target_ulong u_regs[16]; /* globals and ins */
+                abi_ulong psr;
+                abi_ulong pc;
+                abi_ulong npc;
+                abi_ulong y;
+                abi_ulong u_regs[16]; /* globals and ins */
         }               si_regs;
         int             si_mask;
 } __siginfo_t;
@@ -1349,15 +1424,15 @@
 	struct sparc_stackf	ss;
 	__siginfo_t		info;
 	qemu_siginfo_fpu_t 	*fpu_save;
-	target_ulong		insns[2] __attribute__ ((aligned (8)));
-	target_ulong		extramask[TARGET_NSIG_WORDS - 1];
-	target_ulong		extra_size; /* Should be 0 */
+	abi_ulong		insns[2] __attribute__ ((aligned (8)));
+	abi_ulong		extramask[TARGET_NSIG_WORDS - 1];
+	abi_ulong		extra_size; /* Should be 0 */
 	qemu_siginfo_fpu_t	fpu_state;
 };
 struct target_rt_signal_frame {
 	struct sparc_stackf	ss;
 	siginfo_t		info;
-	target_ulong		regs[20];
+	abi_ulong		regs[20];
 	sigset_t		mask;
 	qemu_siginfo_fpu_t 	*fpu_save;
 	unsigned int		insns[2];
@@ -1371,6 +1446,9 @@
 #define UREG_I0        0
 #define UREG_I1        1
 #define UREG_I2        2
+#define UREG_I3        3
+#define UREG_I4        4
+#define UREG_I5        5
 #define UREG_I6        6
 #define UREG_I7        7
 #define UREG_L0	       8
@@ -1382,19 +1460,18 @@
 	unsigned long sp;
 
 	sp = env->regwptr[UREG_FP];
-#if 0
 
 	/* This is the X/Open sanctioned signal stack switching.  */
-	if (sa->sa_flags & TARGET_SA_ONSTACK) {
-		if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7))
-			sp = current->sas_ss_sp + current->sas_ss_size;
+	if (sa->sa.sa_flags & TARGET_SA_ONSTACK) {
+            if (!on_sig_stack(sp)
+                && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7))
+                sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
 	}
-#endif
 	return g2h(sp - framesize);
 }
 
 static int
-setup___siginfo(__siginfo_t *si, CPUState *env, target_ulong mask)
+setup___siginfo(__siginfo_t *si, CPUState *env, abi_ulong mask)
 {
 	int err = 0, i;
 
@@ -1560,7 +1637,7 @@
         uint32_t up_psr, pc, npc;
         target_sigset_t set;
         sigset_t host_set;
-        target_ulong fpu_save;
+        abi_ulong fpu_save;
         int err, i;
 
         sf = (struct target_signal_frame *)g2h(env->regwptr[UREG_FP]);
@@ -1602,7 +1679,7 @@
 		err |= __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
 	}
 
-        err |= __get_user(fpu_save, (target_ulong *)&sf->fpu_save);
+        err |= __get_user(fpu_save, (abi_ulong *)&sf->fpu_save);
 
         //if (fpu_save)
         //        err |= restore_fpu_state(env, fpu_save);
@@ -1633,6 +1710,297 @@
     return -ENOSYS;
 }
 
+#ifdef TARGET_SPARC64
+#define MC_TSTATE 0
+#define MC_PC 1
+#define MC_NPC 2
+#define MC_Y 3
+#define MC_G1 4
+#define MC_G2 5
+#define MC_G3 6
+#define MC_G4 7
+#define MC_G5 8
+#define MC_G6 9
+#define MC_G7 10
+#define MC_O0 11
+#define MC_O1 12
+#define MC_O2 13
+#define MC_O3 14
+#define MC_O4 15
+#define MC_O5 16
+#define MC_O6 17
+#define MC_O7 18
+#define MC_NGREG 19
+
+typedef abi_ulong target_mc_greg_t;
+typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
+
+struct target_mc_fq {
+    abi_ulong *mcfq_addr;
+    uint32_t mcfq_insn;
+};
+
+struct target_mc_fpu {
+    union {
+        uint32_t sregs[32];
+        uint64_t dregs[32];
+        //uint128_t qregs[16];
+    } mcfpu_fregs;
+    abi_ulong mcfpu_fsr;
+    abi_ulong mcfpu_fprs;
+    abi_ulong mcfpu_gsr;
+    struct target_mc_fq *mcfpu_fq;
+    unsigned char mcfpu_qcnt;
+    unsigned char mcfpu_qentsz;
+    unsigned char mcfpu_enab;
+};
+typedef struct target_mc_fpu target_mc_fpu_t;
+
+typedef struct {
+    target_mc_gregset_t mc_gregs;
+    target_mc_greg_t mc_fp;
+    target_mc_greg_t mc_i7;
+    target_mc_fpu_t mc_fpregs;
+} target_mcontext_t;
+
+struct target_ucontext {
+    struct target_ucontext *uc_link;
+    abi_ulong uc_flags;
+    target_sigset_t uc_sigmask;
+    target_mcontext_t uc_mcontext;
+};
+
+/* A V9 register window */
+struct target_reg_window {
+    abi_ulong locals[8];
+    abi_ulong ins[8];
+};
+
+#define TARGET_STACK_BIAS 2047
+
+/* {set, get}context() needed for 64-bit SparcLinux userland. */
+void sparc64_set_context(CPUSPARCState *env)
+{
+    struct target_ucontext *ucp = (struct target_ucontext *)
+        env->regwptr[UREG_I0];
+    target_mc_gregset_t *grp;
+    abi_ulong pc, npc, tstate;
+    abi_ulong fp, i7;
+    unsigned char fenab;
+    int err;
+    unsigned int i;
+    abi_ulong *src, *dst;
+
+    grp  = &ucp->uc_mcontext.mc_gregs;
+    err  = get_user(pc, &((*grp)[MC_PC]));
+    err |= get_user(npc, &((*grp)[MC_NPC]));
+    if (err || ((pc | npc) & 3))
+        goto do_sigsegv;
+    if (env->regwptr[UREG_I1]) {
+        target_sigset_t target_set;
+        sigset_t set;
+
+        if (TARGET_NSIG_WORDS == 1) {
+            if (get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0]))
+                goto do_sigsegv;
+        } else {
+            src = &ucp->uc_sigmask;
+            dst = &target_set;
+            for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
+                 i++, dst++, src++)
+                err |= get_user(dst, src);
+            if (err)
+                goto do_sigsegv;
+        }
+        target_to_host_sigset_internal(&set, &target_set);
+        sigprocmask(SIG_SETMASK, &set, NULL);
+    }
+    env->pc = pc;
+    env->npc = npc;
+    err |= get_user(env->y, &((*grp)[MC_Y]));
+    err |= get_user(tstate, &((*grp)[MC_TSTATE]));
+    env->asi = (tstate >> 24) & 0xff;
+    PUT_CCR(env, tstate >> 32);
+    PUT_CWP64(env, tstate & 0x1f);
+    err |= get_user(env->gregs[1], (&(*grp)[MC_G1]));
+    err |= get_user(env->gregs[2], (&(*grp)[MC_G2]));
+    err |= get_user(env->gregs[3], (&(*grp)[MC_G3]));
+    err |= get_user(env->gregs[4], (&(*grp)[MC_G4]));
+    err |= get_user(env->gregs[5], (&(*grp)[MC_G5]));
+    err |= get_user(env->gregs[6], (&(*grp)[MC_G6]));
+    err |= get_user(env->gregs[7], (&(*grp)[MC_G7]));
+    err |= get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
+    err |= get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
+    err |= get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
+    err |= get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
+    err |= get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
+    err |= get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
+    err |= get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
+    err |= get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
+
+    err |= get_user(fp, &(ucp->uc_mcontext.mc_fp));
+    err |= get_user(i7, &(ucp->uc_mcontext.mc_i7));
+    err |= put_user(fp,
+                    (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6])));
+    err |= put_user(i7,
+                    (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7])));
+
+    err |= get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
+    err |= get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
+    src = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs);
+    dst = &env->fpr;
+    for (i = 0; i < 64; i++, dst++, src++)
+        err |= get_user(dst, src);
+    err |= get_user(env->fsr,
+                    &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
+    err |= get_user(env->gsr,
+                    &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
+    if (err)
+        goto do_sigsegv;
+
+    return;
+ do_sigsegv:
+    force_sig(SIGSEGV);
+}
+
+void sparc64_get_context(CPUSPARCState *env)
+{
+    struct target_ucontext *ucp = (struct target_ucontext *)
+        env->regwptr[UREG_I0];
+    target_mc_gregset_t *grp;
+    target_mcontext_t *mcp;
+    abi_ulong fp, i7;
+    int err;
+    unsigned int i;
+    abi_ulong *src, *dst;
+    target_sigset_t target_set;
+    sigset_t set;
+
+    mcp = &ucp->uc_mcontext;
+    grp = &mcp->mc_gregs;
+
+    /* Skip over the trap instruction, first. */
+    env->pc = env->npc;
+    env->npc += 4;
+
+    err = 0;
+
+    sigprocmask(0, NULL, &set);
+    host_to_target_sigset_internal(&target_set, &set);
+    if (TARGET_NSIG_WORDS == 1)
+        err |= put_user(target_set.sig[0],
+                        (abi_ulong *)&ucp->uc_sigmask);
+    else {
+        src = &target_set;
+        dst = &ucp->uc_sigmask;
+        for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong);
+             i++, dst++, src++)
+            err |= put_user(src, dst);
+        if (err)
+            goto do_sigsegv;
+    }
+
+    err |= put_user(env->tstate, &((*grp)[MC_TSTATE]));
+    err |= put_user(env->pc, &((*grp)[MC_PC]));
+    err |= put_user(env->npc, &((*grp)[MC_NPC]));
+    err |= put_user(env->y, &((*grp)[MC_Y]));
+    err |= put_user(env->gregs[1], &((*grp)[MC_G1]));
+    err |= put_user(env->gregs[2], &((*grp)[MC_G2]));
+    err |= put_user(env->gregs[3], &((*grp)[MC_G3]));
+    err |= put_user(env->gregs[4], &((*grp)[MC_G4]));
+    err |= put_user(env->gregs[5], &((*grp)[MC_G5]));
+    err |= put_user(env->gregs[6], &((*grp)[MC_G6]));
+    err |= put_user(env->gregs[7], &((*grp)[MC_G7]));
+    err |= put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
+    err |= put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
+    err |= put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
+    err |= put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
+    err |= put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
+    err |= put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
+    err |= put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
+    err |= put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
+
+    err |= get_user(fp,
+                    (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6])));
+    err |= get_user(i7,
+                    (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7])));
+    err |= put_user(fp, &(mcp->mc_fp));
+    err |= put_user(i7, &(mcp->mc_i7));
+
+    src = &env->fpr;
+    dst = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs);
+    for (i = 0; i < 64; i++, dst++, src++)
+        err |= put_user(src, dst);
+    err |= put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
+    err |= put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
+    err |= put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
+
+    if (err)
+        goto do_sigsegv;
+
+    return;
+ do_sigsegv:
+    force_sig(SIGSEGV);
+}
+#endif
+#elif defined(TARGET_MIPS64)
+
+# warning signal handling not implemented
+
+static void setup_frame(int sig, struct emulated_sigaction *ka,
+			target_sigset_t *set, CPUState *env)
+{
+    fprintf(stderr, "setup_frame: not implemented\n");
+}
+
+static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
+                           target_siginfo_t *info,
+			   target_sigset_t *set, CPUState *env)
+{
+    fprintf(stderr, "setup_rt_frame: not implemented\n");
+}
+
+long do_sigreturn(CPUState *env)
+{
+    fprintf(stderr, "do_sigreturn: not implemented\n");
+    return -ENOSYS;
+}
+
+long do_rt_sigreturn(CPUState *env)
+{
+    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
+    return -ENOSYS;
+}
+
+#elif defined(TARGET_MIPSN32)
+
+# warning signal handling not implemented
+
+static void setup_frame(int sig, struct emulated_sigaction *ka,
+			target_sigset_t *set, CPUState *env)
+{
+    fprintf(stderr, "setup_frame: not implemented\n");
+}
+
+static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
+                           target_siginfo_t *info,
+			   target_sigset_t *set, CPUState *env)
+{
+    fprintf(stderr, "setup_rt_frame: not implemented\n");
+}
+
+long do_sigreturn(CPUState *env)
+{
+    fprintf(stderr, "do_sigreturn: not implemented\n");
+    return -ENOSYS;
+}
+
+long do_rt_sigreturn(CPUState *env)
+{
+    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
+    return -ENOSYS;
+}
+
 #elif defined(TARGET_MIPS)
 
 struct target_sigcontext {
@@ -1842,11 +2210,10 @@
      */
     sp -= 32;
 
-#if 0
     /* This is the X/Open sanctioned signal stack switching.  */
-    if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
-	sp = current->sas_ss_sp + current->sas_ss_size;
-#endif
+    if ((ka->sa.sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
+        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+    }
 
     return g2h((sp - frame_size) & ~7);
 }
@@ -1990,7 +2357,7 @@
 void process_pending_signals(void *cpu_env)
 {
     int sig;
-    target_ulong handler;
+    abi_ulong handler;
     sigset_t set, old_set;
     target_sigset_t target_old_set;
     struct emulated_sigaction *k;

Modified: trunk/src/host/qemu-neo1973/linux-user/sparc/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc/syscall.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc/syscall.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,9 +1,9 @@
 struct target_pt_regs {
-	target_ulong psr;
-	target_ulong pc;
-	target_ulong npc;
-	target_ulong y;
-	target_ulong u_regs[16];
+	abi_ulong psr;
+	abi_ulong pc;
+	abi_ulong npc;
+	abi_ulong y;
+	abi_ulong u_regs[16];
 };
 
 #define UNAME_MACHINE "sun4"

Modified: trunk/src/host/qemu-neo1973/linux-user/sparc/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc/syscall_nr.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc/syscall_nr.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -217,4 +217,62 @@
 #define TARGET_NR_fdatasync          253
 #define TARGET_NR_nfsservctl         254
 #define TARGET_NR_aplib              255
-#define TARGET_NR__exit TARGET_NR_exit
+#define TARGET_NR_clock_settime	256
+#define TARGET_NR_clock_gettime	257
+#define TARGET_NR_clock_getres	258
+#define TARGET_NR_clock_nanosleep	259
+#define TARGET_NR_sched_getaffinity	260
+#define TARGET_NR_sched_setaffinity	261
+#define TARGET_NR_timer_settime	262
+#define TARGET_NR_timer_gettime	263
+#define TARGET_NR_timer_getoverrun	264
+#define TARGET_NR_timer_delete	265
+#define TARGET_NR_timer_create	266
+/* #define TARGET_NR_vserver		267 Reserved for VSERVER */
+#define TARGET_NR_io_setup		268
+#define TARGET_NR_io_destroy		269
+#define TARGET_NR_io_submit		270
+#define TARGET_NR_io_cancel		271
+#define TARGET_NR_io_getevents	272
+#define TARGET_NR_mq_open		273
+#define TARGET_NR_mq_unlink		274
+#define TARGET_NR_mq_timedsend	275
+#define TARGET_NR_mq_timedreceive	276
+#define TARGET_NR_mq_notify		277
+#define TARGET_NR_mq_getsetattr	278
+#define TARGET_NR_waitid		279
+#define TARGET_NR_tee		280
+#define TARGET_NR_add_key		281
+#define TARGET_NR_request_key	282
+#define TARGET_NR_keyctl		283
+#define TARGET_NR_openat		284
+#define TARGET_NR_mkdirat		285
+#define TARGET_NR_mknodat		286
+#define TARGET_NR_fchownat		287
+#define TARGET_NR_futimesat		288
+#define TARGET_NR_fstatat64		289
+#define TARGET_NR_unlinkat		290
+#define TARGET_NR_renameat		291
+#define TARGET_NR_linkat		292
+#define TARGET_NR_symlinkat		293
+#define TARGET_NR_readlinkat		294
+#define TARGET_NR_fchmodat		295
+#define TARGET_NR_faccessat		296
+#define TARGET_NR_pselect6		297
+#define TARGET_NR_ppoll		298
+#define TARGET_NR_unshare		299
+#define TARGET_NR_set_robust_list	300
+#define TARGET_NR_get_robust_list	301
+#define TARGET_NR_migrate_pages	302
+#define TARGET_NR_mbind		303
+#define TARGET_NR_get_mempolicy	304
+#define TARGET_NR_set_mempolicy	305
+#define TARGET_NR_kexec_load		306
+#define TARGET_NR_move_pages		307
+#define TARGET_NR_getcpu		308
+#define TARGET_NR_epoll_pwait	309
+#define TARGET_NR_utimensat		310
+#define TARGET_NR_signalfd		311
+#define TARGET_NR_timerfd		312
+#define TARGET_NR_eventfd		313
+#define TARGET_NR_fallocate		314

Added: trunk/src/host/qemu-neo1973/linux-user/sparc/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc/target_signal.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc/target_signal.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,36 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+	abi_ulong ss_sp;
+	abi_long ss_flags;
+	abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK	1
+#define TARGET_SS_DISABLE	2
+
+#define TARGET_MINSIGSTKSZ	4096
+#define TARGET_SIGSTKSZ		16384
+
+#ifndef UREG_I6
+#define UREG_I6        6
+#endif
+#ifndef UREG_FP
+#define UREG_FP        UREG_I6
+#endif
+
+static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
+{
+    return state->regwptr[UREG_FP];
+}
+
+#endif /* TARGET_SIGNAL_H */

Modified: trunk/src/host/qemu-neo1973/linux-user/sparc/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc/termbits.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc/termbits.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -51,6 +51,7 @@
 #define TARGET_IXANY	0x00000800
 #define TARGET_IXOFF	0x00001000
 #define TARGET_IMAXBEL	0x00002000
+#define TARGET_IUTF8	0x00004000
 
 /* c_oflag bits */
 #define TARGET_OPOST	0x00000001

Modified: trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,10 +1,10 @@
 struct target_pt_regs {
-	target_ulong u_regs[16];
-	target_ulong tstate;
-	target_ulong pc;
-	target_ulong npc;
-	target_ulong y;
-	target_ulong fprs;
+	abi_ulong u_regs[16];
+	abi_ulong tstate;
+	abi_ulong pc;
+	abi_ulong npc;
+	abi_ulong y;
+	abi_ulong fprs;
 };
 
 #define UNAME_MACHINE "sun4u"

Modified: trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall_nr.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc64/syscall_nr.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -29,11 +29,11 @@
 #define TARGET_NR_sigaltstack	 28 /* Common					   */
 #define TARGET_NR_pause               29 /* Is sigblock(0)->sigpause() in SunOS         */
 #define TARGET_NR_utime               30 /* Implemented via utimes() under SunOS        */
-/* #define TARGET_NR_lchown32         31    Linux sparc32 specific                      */
-/* #define TARGET_NR_fchown32         32    Linux sparc32 specific                      */
+#define TARGET_NR_lchown32            31 /* Linux sparc32 specific                      */
+#define TARGET_NR_fchown32            32 /* Linux sparc32 specific                      */
 #define TARGET_NR_access              33 /* Common                                      */
 #define TARGET_NR_nice                34 /* Implemented via get/setpriority() in SunOS  */
-/* #define TARGET_NR_chown32          35    Linux sparc32 specific                      */
+#define TARGET_NR_chown32             35 /*  Linux sparc32 specific                     */
 #define TARGET_NR_sync                36 /* Common                                      */
 #define TARGET_NR_kill                37 /* Common                                      */
 #define TARGET_NR_stat                38 /* Common                                      */
@@ -42,7 +42,7 @@
 #define TARGET_NR_dup                 41 /* Common                                      */
 #define TARGET_NR_pipe                42 /* Common                                      */
 #define TARGET_NR_times               43 /* Implemented via getrusage() in SunOS        */
-/* #define TARGET_NR_getuid32         44    Linux sparc32 specific                      */
+#define TARGET_NR_getuid32            44 /* Linux sparc32 specific                      */
 #define TARGET_NR_umount2             45 /* Linux Specific                              */
 #define TARGET_NR_setgid              46 /* Implemented via setregid() in SunOS         */
 #define TARGET_NR_getgid              47 /* Common                                      */
@@ -51,48 +51,48 @@
 #define TARGET_NR_getegid             50 /* SunOS calls getgid()                        */
 #define TARGET_NR_acct                51 /* Common                                      */
 #define TARGET_NR_memory_ordering	 52 /* Linux Specific				   */
-/* #define TARGET_NR_getgid32         53    Linux sparc32 specific                      */
+#define TARGET_NR_getgid32            53 /* Linux sparc32 specific                      */
 #define TARGET_NR_ioctl               54 /* Common                                      */
 #define TARGET_NR_reboot              55 /* Common                                      */
-/* #define TARGET_NR_mmap2		 56    Linux sparc32 Specific                      */
+#define TARGET_NR_mmap2		      56 /* Linux sparc32 Specific                      */
 #define TARGET_NR_symlink             57 /* Common                                      */
 #define TARGET_NR_readlink            58 /* Common                                      */
 #define TARGET_NR_execve              59 /* Common                                      */
 #define TARGET_NR_umask               60 /* Common                                      */
 #define TARGET_NR_chroot              61 /* Common                                      */
 #define TARGET_NR_fstat               62 /* Common                                      */
-/* #define TARGET_NR_fstat64          63    Linux sparc32 Specific                      */
+#define TARGET_NR_fstat64             63 /* Linux sparc32 Specific                      */
 #define TARGET_NR_getpagesize         64 /* Common                                      */
 #define TARGET_NR_msync               65 /* Common in newer 1.3.x revs...               */
 #define TARGET_NR_vfork               66 /* Common                                      */
 #define TARGET_NR_pread64             67 /* Linux Specific                              */
 #define TARGET_NR_pwrite64            68 /* Linux Specific                              */
-/* #define TARGET_NR_geteuid32        69    Linux sparc32, sbrk under SunOS             */
-/* #define TARGET_NR_getegid32        70    Linux sparc32, sstk under SunOS             */
+#define TARGET_NR_geteuid32           69 /* Linux sparc32, sbrk under SunOS             */
+#define TARGET_NR_getegid32           70 /* Linux sparc32, sstk under SunOS             */
 #define TARGET_NR_mmap                71 /* Common                                      */
-/* #define TARGET_NR_setreuid32       72    Linux sparc32, vadvise under SunOS          */
+#define TARGET_NR_setreuid32          72 /* Linux sparc32, vadvise under SunOS          */
 #define TARGET_NR_munmap              73 /* Common                                      */
 #define TARGET_NR_mprotect            74 /* Common                                      */
 #define TARGET_NR_madvise             75 /* Common                                      */
 #define TARGET_NR_vhangup             76 /* Common                                      */
-/* #define TARGET_NR_truncate64       77    Linux sparc32 Specific			   */
+#define TARGET_NR_truncate64          77 /* Linux sparc32 Specific			*/
 #define TARGET_NR_mincore             78 /* Common                                      */
 #define TARGET_NR_getgroups           79 /* Common                                      */
 #define TARGET_NR_setgroups           80 /* Common                                      */
 #define TARGET_NR_getpgrp             81 /* Common                                      */
-/* #define TARGET_NR_setgroups32      82    Linux sparc32, setpgrp under SunOS          */
+#define TARGET_NR_setgroups32         82 /* Linux sparc32, setpgrp under SunOS          */
 #define TARGET_NR_setitimer           83 /* Common                                      */
-/* #define TARGET_NR_ftruncate64      84    Linux sparc32 Specific			   */
+#define TARGET_NR_ftruncate64         84 /* Linux sparc32 Specific                      */
 #define TARGET_NR_swapon              85 /* Common                                      */
 #define TARGET_NR_getitimer           86 /* Common                                      */
-/* #define TARGET_NR_setuid32         87    Linux sparc32, gethostname under SunOS      */
+#define TARGET_NR_setuid32            87 /* Linux sparc32, gethostname under SunOS      */
 #define TARGET_NR_sethostname         88 /* Common                                      */
-/* #define TARGET_NR_setgid32         89    Linux sparc32, getdtablesize under SunOS    */
+#define TARGET_NR_setgid32            89 /* Linux sparc32, getdtablesize under SunOS    */
 #define TARGET_NR_dup2                90 /* Common                                      */
-/* #define TARGET_NR_setfsuid32       91    Linux sparc32, getdopt under SunOS          */
+#define TARGET_NR_setfsuid32          91 /* Linux sparc32, getdopt under SunOS          */
 #define TARGET_NR_fcntl               92 /* Common                                      */
 #define TARGET_NR_select              93 /* Common                                      */
-/* #define TARGET_NR_setfsgid32       94    Linux sparc32, setdopt under SunOS          */
+#define TARGET_NR_setfsgid32          94 /* Linux sparc32, setdopt under SunOS          */
 #define TARGET_NR_fsync               95 /* Common                                      */
 #define TARGET_NR_setpriority         96 /* Common                                      */
 #define TARGET_NR_socket              97 /* Common                                      */
@@ -110,10 +110,10 @@
 #define TARGET_NR_getresuid          109 /* Linux Specific, sigblock under SunOS	   */
 #define TARGET_NR_setresgid          110 /* Linux Specific, sigsetmask under SunOS	   */
 #define TARGET_NR_getresgid          111 /* Linux Specific, sigpause under SunOS	   */
-/* #define TARGET_NR_setregid32       75    Linux sparc32, sigstack under SunOS         */
+/* #define TARGET_NR_setregid32          75  Linux sparc32, sigstack under SunOS         */
 #define TARGET_NR_recvmsg            113 /* Common                                      */
 #define TARGET_NR_sendmsg            114 /* Common                                      */
-/* #define TARGET_NR_getgroups32     115    Linux sparc32, vtrace under SunOS           */
+#define TARGET_NR_getgroups32        115 /* Linux sparc32, vtrace under SunOS           */
 #define TARGET_NR_gettimeofday       116 /* Common                                      */
 #define TARGET_NR_getrusage          117 /* Common                                      */
 #define TARGET_NR_getsockopt         118 /* Common                                      */
@@ -130,14 +130,14 @@
 #define TARGET_NR_truncate           129 /* Common                                      */
 #define TARGET_NR_ftruncate          130 /* Common                                      */
 #define TARGET_NR_flock              131 /* Common                                      */
-/* #define TARGET_NR_lstat64		132    Linux sparc32 Specific                      */
+#define TARGET_NR_lstat64	     132 /* Linux sparc32 Specific                      */
 #define TARGET_NR_sendto             133 /* Common                                      */
 #define TARGET_NR_shutdown           134 /* Common                                      */
 #define TARGET_NR_socketpair         135 /* Common                                      */
 #define TARGET_NR_mkdir              136 /* Common                                      */
 #define TARGET_NR_rmdir              137 /* Common                                      */
 #define TARGET_NR_utimes             138 /* SunOS Specific                              */
-/* #define TARGET_NR_stat64		139    Linux sparc32 Specific			   */
+#define TARGET_NR_stat64	     139 /* Linux sparc32 Specific			   */
 #define TARGET_NR_sendfile64         140 /* adjtime under SunOS                         */
 #define TARGET_NR_getpeername        141 /* Common                                      */
 #define TARGET_NR_futex              142 /* gethostid under SunOS                       */
@@ -153,7 +153,7 @@
 /* #define TARGET_NR_putmsg          152    SunOS Specific                              */
 #define TARGET_NR_poll               153 /* Common                                      */
 #define TARGET_NR_getdents64		154 /* Linux specific				   */
-/* #define TARGET_NR_fcntl64         155    Linux sparc32 Specific                      */
+#define TARGET_NR_fcntl64            155 /* Linux sparc32 Specific                      */
 /* #define TARGET_NR_getdirentries   156    SunOS Specific                              */
 #define TARGET_NR_statfs             157 /* Common                                      */
 #define TARGET_NR_fstatfs            158 /* Common                                      */
@@ -229,9 +229,7 @@
 #define TARGET_NR_setfsuid           228 /* Linux Specific                              */
 #define TARGET_NR_setfsgid           229 /* Linux Specific                              */
 #define TARGET_NR__newselect         230 /* Linux Specific                              */
-#ifdef __KERNEL__
-#define TARGET_NR_time		231 /* Linux sparc32                               */
-#endif
+#define TARGET_NR_time               231 /* Linux sparc32                               */
 /* #define TARGET_NR_oldstat         232    Linux Specific                              */
 #define TARGET_NR_stime              233 /* Linux Specific                              */
 #define TARGET_NR_statfs64           234 /* Linux Specific                              */
@@ -284,3 +282,34 @@
 #define TARGET_NR_add_key		281
 #define TARGET_NR_request_key	282
 #define TARGET_NR_keyctl		283
+#define TARGET_NR_openat		284
+#define TARGET_NR_mkdirat		285
+#define TARGET_NR_mknodat		286
+#define TARGET_NR_fchownat		287
+#define TARGET_NR_futimesat		288
+#define TARGET_NR_fstatat64		289
+#define TARGET_NR_unlinkat		290
+#define TARGET_NR_renameat		291
+#define TARGET_NR_linkat		292
+#define TARGET_NR_symlinkat		293
+#define TARGET_NR_readlinkat		294
+#define TARGET_NR_fchmodat		295
+#define TARGET_NR_faccessat		296
+#define TARGET_NR_pselect6		297
+#define TARGET_NR_ppoll		298
+#define TARGET_NR_unshare		299
+#define TARGET_NR_set_robust_list	300
+#define TARGET_NR_get_robust_list	301
+#define TARGET_NR_migrate_pages	302
+#define TARGET_NR_mbind		303
+#define TARGET_NR_get_mempolicy	304
+#define TARGET_NR_set_mempolicy	305
+#define TARGET_NR_kexec_load		306
+#define TARGET_NR_move_pages		307
+#define TARGET_NR_getcpu		308
+#define TARGET_NR_epoll_pwait	309
+#define TARGET_NR_utimensat		310
+#define TARGET_NR_signalfd		311
+#define TARGET_NR_timerfd		312
+#define TARGET_NR_eventfd		313
+#define TARGET_NR_fallocate		314

Added: trunk/src/host/qemu-neo1973/linux-user/sparc64/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc64/target_signal.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc64/target_signal.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,36 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+	abi_ulong ss_sp;
+	abi_long ss_flags;
+	abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK	1
+#define TARGET_SS_DISABLE	2
+
+#define TARGET_MINSIGSTKSZ	4096
+#define TARGET_SIGSTKSZ		16384
+
+#ifndef UREG_I6
+#define UREG_I6        6
+#endif
+#ifndef UREG_FP
+#define UREG_FP        UREG_I6
+#endif
+
+static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
+{
+    return state->regwptr[UREG_FP];
+}
+
+#endif /* TARGET_SIGNAL_H */

Modified: trunk/src/host/qemu-neo1973/linux-user/sparc64/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/sparc64/termbits.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/sparc64/termbits.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -51,6 +51,7 @@
 #define TARGET_IXANY	0x00000800
 #define TARGET_IXOFF	0x00001000
 #define TARGET_IMAXBEL	0x00002000
+#define TARGET_IUTF8	0x00004000
 
 /* c_oflag bits */
 #define TARGET_OPOST	0x00000001

Modified: trunk/src/host/qemu-neo1973/linux-user/syscall.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/syscall.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/syscall.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -74,7 +74,7 @@
 //#define DEBUG
 
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
-    || defined(TARGET_M68K) || defined(TARGET_SH4)
+    || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
 /* 16 bit uid wrappers emulation */
 #define USE_UID16
 #endif
@@ -139,13 +139,26 @@
 
 
 #define __NR_sys_uname __NR_uname
+#define __NR_sys_faccessat __NR_faccessat
+#define __NR_sys_fchmodat __NR_fchmodat
+#define __NR_sys_fchownat __NR_fchownat
 #define __NR_sys_getcwd1 __NR_getcwd
 #define __NR_sys_getdents __NR_getdents
 #define __NR_sys_getdents64 __NR_getdents64
+#define __NR_sys_getpriority __NR_getpriority
+#define __NR_sys_linkat __NR_linkat
+#define __NR_sys_mkdirat __NR_mkdirat
+#define __NR_sys_mknodat __NR_mknodat
+#define __NR_sys_openat __NR_openat
+#define __NR_sys_readlinkat __NR_readlinkat
+#define __NR_sys_renameat __NR_renameat
 #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
+#define __NR_sys_symlinkat __NR_symlinkat
 #define __NR_sys_syslog __NR_syslog
 #define __NR_sys_tgkill __NR_tgkill
 #define __NR_sys_tkill __NR_tkill
+#define __NR_sys_unlinkat __NR_unlinkat
+#define __NR_sys_utimensat __NR_utimensat
 
 #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
 #define __NR__llseek __NR_lseek
@@ -154,19 +167,59 @@
 #ifdef __NR_gettid
 _syscall0(int, gettid)
 #else
+/* This is a replacement for the host gettid() and must return a host
+   errno. */
 static int gettid(void) {
     return -ENOSYS;
 }
 #endif
 _syscall1(int,sys_uname,struct new_utsname *,buf)
+#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
+_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
+#endif
+#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
+_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
+          mode_t,mode,int,flags)
+#endif
+#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
+_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
+          uid_t,owner,gid_t,group,int,flags)
+#endif
 _syscall2(int,sys_getcwd1,char *,buf,size_t,size)
 _syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
 #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
 _syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
 #endif
+_syscall2(int, sys_getpriority, int, which, int, who);
 _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
           loff_t *, res, uint, wh);
+#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
+_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
+	  int,newdirfd,const char *,newpath,int,flags)
+#endif
+#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
+_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
+#endif
+#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
+_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
+          mode_t,mode,dev_t,dev)
+#endif
+#if defined(TARGET_NR_openat) && defined(__NR_openat)
+_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
+#endif
+#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
+_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
+          char *,buf,size_t,bufsize)
+#endif
+#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
+_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
+          int,newdirfd,const char *,newpath)
+#endif
 _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
+#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
+_syscall3(int,sys_symlinkat,const char *,oldpath,
+          int,newdirfd,const char *,newpath)
+#endif
 _syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
 #if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
 _syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
@@ -180,6 +233,13 @@
 #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
 _syscall1(int,set_tid_address,int *,tidptr)
 #endif
+#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
+_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
+#endif
+#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
+_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
+          const struct timespec *,tsp,int,flags)
+#endif
 
 extern int personality(int);
 extern int flock(int, int);
@@ -310,7 +370,7 @@
     return err;
 }
 
-static inline long get_errno(long ret)
+static inline abi_long get_errno(abi_long ret)
 {
     if (ret == -1)
         return -host_to_target_errno(errno);
@@ -318,29 +378,30 @@
         return ret;
 }
 
-static inline int is_error(long ret)
+static inline int is_error(abi_long ret)
 {
-    return (unsigned long)ret >= (unsigned long)(-4096);
+    return (abi_ulong)ret >= (abi_ulong)(-4096);
 }
 
-static target_ulong target_brk;
-static target_ulong target_original_brk;
+static abi_ulong target_brk;
+static abi_ulong target_original_brk;
 
-void target_set_brk(target_ulong new_brk)
+void target_set_brk(abi_ulong new_brk)
 {
     target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
 }
 
-long do_brk(target_ulong new_brk)
+/* do_brk() must return target values and target errnos. */
+abi_long do_brk(abi_ulong new_brk)
 {
-    target_ulong brk_page;
-    long mapped_addr;
+    abi_ulong brk_page;
+    abi_long mapped_addr;
     int	new_alloc_size;
 
     if (!new_brk)
         return target_brk;
     if (new_brk < target_original_brk)
-        return -ENOMEM;
+        return -TARGET_ENOMEM;
 
     brk_page = HOST_PAGE_ALIGN(target_brk);
 
@@ -364,7 +425,7 @@
 }
 
 static inline fd_set *target_to_host_fds(fd_set *fds,
-                                         target_long *target_fds, int n)
+                                         abi_long *target_fds, int n)
 {
 #if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)
     return (fd_set *)target_fds;
@@ -373,8 +434,8 @@
     if (target_fds) {
         FD_ZERO(fds);
         for(i = 0;i < n; i++) {
-            b = (tswapl(target_fds[i / TARGET_LONG_BITS]) >>
-                 (i & (TARGET_LONG_BITS - 1))) & 1;
+            b = (tswapl(target_fds[i / TARGET_ABI_BITS]) >>
+                 (i & (TARGET_ABI_BITS - 1))) & 1;
             if (b)
                 FD_SET(i, fds);
         }
@@ -385,21 +446,21 @@
 #endif
 }
 
-static inline void host_to_target_fds(target_long *target_fds,
+static inline void host_to_target_fds(abi_long *target_fds,
                                       fd_set *fds, int n)
 {
 #if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)
     /* nothing to do */
 #else
     int i, nw, j, k;
-    target_long v;
+    abi_long v;
 
     if (target_fds) {
-        nw = (n + TARGET_LONG_BITS - 1) / TARGET_LONG_BITS;
+        nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
         k = 0;
         for(i = 0;i < nw; i++) {
             v = 0;
-            for(j = 0; j < TARGET_LONG_BITS; j++) {
+            for(j = 0; j < TARGET_ABI_BITS; j++) {
                 v |= ((FD_ISSET(k, fds) != 0) << j);
                 k++;
             }
@@ -415,7 +476,7 @@
 #define HOST_HZ 100
 #endif
 
-static inline long host_to_target_clock_t(long ticks)
+static inline abi_long host_to_target_clock_t(long ticks)
 {
 #if HOST_HZ == TARGET_HZ
     return ticks;
@@ -424,7 +485,7 @@
 #endif
 }
 
-static inline void host_to_target_rusage(target_ulong target_addr,
+static inline void host_to_target_rusage(abi_ulong target_addr,
                                          const struct rusage *rusage)
 {
     struct target_rusage *target_rusage;
@@ -452,7 +513,7 @@
 }
 
 static inline void target_to_host_timeval(struct timeval *tv,
-                                          target_ulong target_addr)
+                                          abi_ulong target_addr)
 {
     struct target_timeval *target_tv;
 
@@ -462,7 +523,7 @@
     unlock_user_struct(target_tv, target_addr, 0);
 }
 
-static inline void host_to_target_timeval(target_ulong target_addr,
+static inline void host_to_target_timeval(abi_ulong target_addr,
                                           const struct timeval *tv)
 {
     struct target_timeval *target_tv;
@@ -474,33 +535,34 @@
 }
 
 
-static long do_select(long n,
-                      target_ulong rfd_p, target_ulong wfd_p,
-                      target_ulong efd_p, target_ulong target_tv)
+/* do_select() must return target values and target errnos. */
+static abi_long do_select(int n,
+                          abi_ulong rfd_p, abi_ulong wfd_p,
+                          abi_ulong efd_p, abi_ulong target_tv)
 {
     fd_set rfds, wfds, efds;
     fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
-    target_long *target_rfds, *target_wfds, *target_efds;
+    abi_long *target_rfds, *target_wfds, *target_efds;
     struct timeval tv, *tv_ptr;
-    long ret;
+    abi_long ret;
     int ok;
 
     if (rfd_p) {
-        target_rfds = lock_user(rfd_p, sizeof(target_long) * n, 1);
+        target_rfds = lock_user(rfd_p, sizeof(abi_long) * n, 1);
         rfds_ptr = target_to_host_fds(&rfds, target_rfds, n);
     } else {
         target_rfds = NULL;
         rfds_ptr = NULL;
     }
     if (wfd_p) {
-        target_wfds = lock_user(wfd_p, sizeof(target_long) * n, 1);
+        target_wfds = lock_user(wfd_p, sizeof(abi_long) * n, 1);
         wfds_ptr = target_to_host_fds(&wfds, target_wfds, n);
     } else {
         target_wfds = NULL;
         wfds_ptr = NULL;
     }
     if (efd_p) {
-        target_efds = lock_user(efd_p, sizeof(target_long) * n, 1);
+        target_efds = lock_user(efd_p, sizeof(abi_long) * n, 1);
         efds_ptr = target_to_host_fds(&efds, target_efds, n);
     } else {
         target_efds = NULL;
@@ -526,17 +588,17 @@
         }
     }
     if (target_rfds)
-        unlock_user(target_rfds, rfd_p, ok ? sizeof(target_long) * n : 0);
+        unlock_user(target_rfds, rfd_p, ok ? sizeof(abi_long) * n : 0);
     if (target_wfds)
-        unlock_user(target_wfds, wfd_p, ok ? sizeof(target_long) * n : 0);
+        unlock_user(target_wfds, wfd_p, ok ? sizeof(abi_long) * n : 0);
     if (target_efds)
-        unlock_user(target_efds, efd_p, ok ? sizeof(target_long) * n : 0);
+        unlock_user(target_efds, efd_p, ok ? sizeof(abi_long) * n : 0);
 
     return ret;
 }
 
 static inline void target_to_host_sockaddr(struct sockaddr *addr,
-                                           target_ulong target_addr,
+                                           abi_ulong target_addr,
                                            socklen_t len)
 {
     struct target_sockaddr *target_saddr;
@@ -547,7 +609,7 @@
     unlock_user(target_saddr, target_addr, 0);
 }
 
-static inline void host_to_target_sockaddr(target_ulong target_addr,
+static inline void host_to_target_sockaddr(abi_ulong target_addr,
                                            struct sockaddr *addr,
                                            socklen_t len)
 {
@@ -648,16 +710,18 @@
     msgh->msg_controllen = tswapl(space);
 }
 
-static long do_setsockopt(int sockfd, int level, int optname,
-                          target_ulong optval, socklen_t optlen)
+/* do_setsockopt() Must return target values and target errnos. */
+static abi_long do_setsockopt(int sockfd, int level, int optname,
+                              abi_ulong optval, socklen_t optlen)
 {
-    int val, ret;
+    abi_long ret;
+    int val;
 
     switch(level) {
     case SOL_TCP:
         /* TCP options all take an 'int' value.  */
         if (optlen < sizeof(uint32_t))
-            return -EINVAL;
+            return -TARGET_EINVAL;
 
         val = tget32(optval);
         ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
@@ -755,7 +819,7 @@
             goto unimplemented;
         }
 	if (optlen < sizeof(uint32_t))
-	return -EINVAL;
+	return -TARGET_EINVAL;
 
 	val = tget32(optval);
 	ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
@@ -763,15 +827,17 @@
     default:
     unimplemented:
         gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
-        ret = -ENOSYS;
+        ret = -TARGET_ENOSYS;
     }
     return ret;
 }
 
-static long do_getsockopt(int sockfd, int level, int optname,
-                          target_ulong optval, target_ulong optlen)
+/* do_getsockopt() Must return target values and target errnos. */
+static abi_long do_getsockopt(int sockfd, int level, int optname,
+                              abi_ulong optval, abi_ulong optlen)
 {
-    int len, lv, val, ret;
+    abi_long ret;
+    int len, lv, val;
 
     switch(level) {
     case TARGET_SOL_SOCKET:
@@ -793,7 +859,7 @@
     int_case:
         len = tget32(optlen);
         if (len < 0)
-            return -EINVAL;
+            return -TARGET_EINVAL;
         lv = sizeof(int);
         ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
         if (ret < 0)
@@ -826,7 +892,7 @@
         case IP_MULTICAST_LOOP:
             len = tget32(optlen);
             if (len < 0)
-                return -EINVAL;
+                return -TARGET_EINVAL;
             lv = sizeof(int);
             ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
             if (ret < 0)
@@ -850,17 +916,17 @@
     unimplemented:
         gemu_log("getsockopt level=%d optname=%d not yet supported\n",
                  level, optname);
-        ret = -ENOSYS;
+        ret = -TARGET_ENOSYS;
         break;
     }
     return ret;
 }
 
-static void lock_iovec(struct iovec *vec, target_ulong target_addr,
+static void lock_iovec(struct iovec *vec, abi_ulong target_addr,
                        int count, int copy)
 {
     struct target_iovec *target_vec;
-    target_ulong base;
+    abi_ulong base;
     int i;
 
     target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1);
@@ -872,11 +938,11 @@
     unlock_user (target_vec, target_addr, 0);
 }
 
-static void unlock_iovec(struct iovec *vec, target_ulong target_addr,
+static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
                          int count, int copy)
 {
     struct target_iovec *target_vec;
-    target_ulong base;
+    abi_ulong base;
     int i;
 
     target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1);
@@ -887,7 +953,8 @@
     unlock_user (target_vec, target_addr, 0);
 }
 
-static long do_socket(int domain, int type, int protocol)
+/* do_socket() Must return target values and target errnos. */
+static abi_long do_socket(int domain, int type, int protocol)
 {
 #if defined(TARGET_MIPS)
     switch(type) {
@@ -914,8 +981,9 @@
     return get_errno(socket(domain, type, protocol));
 }
 
-static long do_bind(int sockfd, target_ulong target_addr,
-                    socklen_t addrlen)
+/* do_bind() Must return target values and target errnos. */
+static abi_long do_bind(int sockfd, abi_ulong target_addr,
+                        socklen_t addrlen)
 {
     void *addr = alloca(addrlen);
 
@@ -923,8 +991,9 @@
     return get_errno(bind(sockfd, addr, addrlen));
 }
 
-static long do_connect(int sockfd, target_ulong target_addr,
-                    socklen_t addrlen)
+/* do_connect() Must return target values and target errnos. */
+static abi_long do_connect(int sockfd, abi_ulong target_addr,
+                           socklen_t addrlen)
 {
     void *addr = alloca(addrlen);
 
@@ -932,15 +1001,16 @@
     return get_errno(connect(sockfd, addr, addrlen));
 }
 
-static long do_sendrecvmsg(int fd, target_ulong target_msg,
-                           int flags, int send)
+/* do_sendrecvmsg() Must return target values and target errnos. */
+static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
+                               int flags, int send)
 {
-    long ret;
+    abi_long ret;
     struct target_msghdr *msgp;
     struct msghdr msg;
     int count;
     struct iovec *vec;
-    target_ulong target_vec;
+    abi_ulong target_vec;
 
     lock_user_struct(msgp, target_msg, 1);
     if (msgp->msg_name) {
@@ -975,12 +1045,13 @@
     return ret;
 }
 
-static long do_accept(int fd, target_ulong target_addr,
-                      target_ulong target_addrlen)
+/* do_accept() Must return target values and target errnos. */
+static abi_long do_accept(int fd, abi_ulong target_addr,
+                          abi_ulong target_addrlen)
 {
     socklen_t addrlen = tget32(target_addrlen);
     void *addr = alloca(addrlen);
-    long ret;
+    abi_long ret;
 
     ret = get_errno(accept(fd, addr, &addrlen));
     if (!is_error(ret)) {
@@ -990,12 +1061,13 @@
     return ret;
 }
 
-static long do_getpeername(int fd, target_ulong target_addr,
-                           target_ulong target_addrlen)
+/* do_getpeername() Must return target values and target errnos. */
+static abi_long do_getpeername(int fd, abi_ulong target_addr,
+                               abi_ulong target_addrlen)
 {
     socklen_t addrlen = tget32(target_addrlen);
     void *addr = alloca(addrlen);
-    long ret;
+    abi_long ret;
 
     ret = get_errno(getpeername(fd, addr, &addrlen));
     if (!is_error(ret)) {
@@ -1005,12 +1077,13 @@
     return ret;
 }
 
-static long do_getsockname(int fd, target_ulong target_addr,
-                           target_ulong target_addrlen)
+/* do_getsockname() Must return target values and target errnos. */
+static abi_long do_getsockname(int fd, abi_ulong target_addr,
+                               abi_ulong target_addrlen)
 {
     socklen_t addrlen = tget32(target_addrlen);
     void *addr = alloca(addrlen);
-    long ret;
+    abi_long ret;
 
     ret = get_errno(getsockname(fd, addr, &addrlen));
     if (!is_error(ret)) {
@@ -1020,11 +1093,12 @@
     return ret;
 }
 
-static long do_socketpair(int domain, int type, int protocol,
-                          target_ulong target_tab)
+/* do_socketpair() Must return target values and target errnos. */
+static abi_long do_socketpair(int domain, int type, int protocol,
+                              abi_ulong target_tab)
 {
     int tab[2];
-    long ret;
+    abi_long ret;
 
     ret = get_errno(socketpair(domain, type, protocol, tab));
     if (!is_error(ret)) {
@@ -1034,12 +1108,13 @@
     return ret;
 }
 
-static long do_sendto(int fd, target_ulong msg, size_t len, int flags,
-                      target_ulong target_addr, socklen_t addrlen)
+/* do_sendto() Must return target values and target errnos. */
+static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
+                          abi_ulong target_addr, socklen_t addrlen)
 {
     void *addr;
     void *host_msg;
-    long ret;
+    abi_long ret;
 
     host_msg = lock_user(msg, len, 1);
     if (target_addr) {
@@ -1053,13 +1128,15 @@
     return ret;
 }
 
-static long do_recvfrom(int fd, target_ulong msg, size_t len, int flags,
-                        target_ulong target_addr, target_ulong target_addrlen)
+/* do_recvfrom() Must return target values and target errnos. */
+static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
+                            abi_ulong target_addr,
+                            abi_ulong target_addrlen)
 {
     socklen_t addrlen;
     void *addr;
     void *host_msg;
-    long ret;
+    abi_long ret;
 
     host_msg = lock_user(msg, len, 0);
     if (target_addr) {
@@ -1082,10 +1159,12 @@
     return ret;
 }
 
-static long do_socketcall(int num, target_ulong vptr)
+#ifdef TARGET_NR_socketcall
+/* do_socketcall() Must return target values and target errnos. */
+static abi_long do_socketcall(int num, abi_ulong vptr)
 {
-    long ret;
-    const int n = sizeof(target_ulong);
+    abi_long ret;
+    const int n = sizeof(abi_ulong);
 
     switch(num) {
     case SOCKOP_socket:
@@ -1099,7 +1178,7 @@
     case SOCKOP_bind:
 	{
             int sockfd = tgetl(vptr);
-            target_ulong target_addr = tgetl(vptr + n);
+            abi_ulong target_addr = tgetl(vptr + n);
             socklen_t addrlen = tgetl(vptr + 2 * n);
             ret = do_bind(sockfd, target_addr, addrlen);
         }
@@ -1107,7 +1186,7 @@
     case SOCKOP_connect:
         {
             int sockfd = tgetl(vptr);
-            target_ulong target_addr = tgetl(vptr + n);
+            abi_ulong target_addr = tgetl(vptr + n);
             socklen_t addrlen = tgetl(vptr + 2 * n);
             ret = do_connect(sockfd, target_addr, addrlen);
         }
@@ -1122,24 +1201,24 @@
     case SOCKOP_accept:
         {
             int sockfd = tgetl(vptr);
-            target_ulong target_addr = tgetl(vptr + n);
-            target_ulong target_addrlen = tgetl(vptr + 2 * n);
+            abi_ulong target_addr = tgetl(vptr + n);
+            abi_ulong target_addrlen = tgetl(vptr + 2 * n);
             ret = do_accept(sockfd, target_addr, target_addrlen);
         }
         break;
     case SOCKOP_getsockname:
         {
             int sockfd = tgetl(vptr);
-            target_ulong target_addr = tgetl(vptr + n);
-            target_ulong target_addrlen = tgetl(vptr + 2 * n);
+            abi_ulong target_addr = tgetl(vptr + n);
+            abi_ulong target_addrlen = tgetl(vptr + 2 * n);
             ret = do_getsockname(sockfd, target_addr, target_addrlen);
         }
         break;
     case SOCKOP_getpeername:
         {
             int sockfd = tgetl(vptr);
-            target_ulong target_addr = tgetl(vptr + n);
-            target_ulong target_addrlen = tgetl(vptr + 2 * n);
+            abi_ulong target_addr = tgetl(vptr + n);
+            abi_ulong target_addrlen = tgetl(vptr + 2 * n);
             ret = do_getpeername(sockfd, target_addr, target_addrlen);
         }
         break;
@@ -1148,14 +1227,14 @@
             int domain = tgetl(vptr);
             int type = tgetl(vptr + n);
             int protocol = tgetl(vptr + 2 * n);
-            target_ulong tab = tgetl(vptr + 3 * n);
+            abi_ulong tab = tgetl(vptr + 3 * n);
             ret = do_socketpair(domain, type, protocol, tab);
         }
         break;
     case SOCKOP_send:
         {
             int sockfd = tgetl(vptr);
-            target_ulong msg = tgetl(vptr + n);
+            abi_ulong msg = tgetl(vptr + n);
             size_t len = tgetl(vptr + 2 * n);
             int flags = tgetl(vptr + 3 * n);
             ret = do_sendto(sockfd, msg, len, flags, 0, 0);
@@ -1164,7 +1243,7 @@
     case SOCKOP_recv:
         {
             int sockfd = tgetl(vptr);
-            target_ulong msg = tgetl(vptr + n);
+            abi_ulong msg = tgetl(vptr + n);
             size_t len = tgetl(vptr + 2 * n);
             int flags = tgetl(vptr + 3 * n);
             ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
@@ -1173,10 +1252,10 @@
     case SOCKOP_sendto:
         {
             int sockfd = tgetl(vptr);
-            target_ulong msg = tgetl(vptr + n);
+            abi_ulong msg = tgetl(vptr + n);
             size_t len = tgetl(vptr + 2 * n);
             int flags = tgetl(vptr + 3 * n);
-            target_ulong addr = tgetl(vptr + 4 * n);
+            abi_ulong addr = tgetl(vptr + 4 * n);
             socklen_t addrlen = tgetl(vptr + 5 * n);
             ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
         }
@@ -1184,11 +1263,11 @@
     case SOCKOP_recvfrom:
         {
             int sockfd = tgetl(vptr);
-            target_ulong msg = tgetl(vptr + n);
+            abi_ulong msg = tgetl(vptr + n);
             size_t len = tgetl(vptr + 2 * n);
             int flags = tgetl(vptr + 3 * n);
-            target_ulong addr = tgetl(vptr + 4 * n);
-            target_ulong addrlen = tgetl(vptr + 5 * n);
+            abi_ulong addr = tgetl(vptr + 4 * n);
+            abi_ulong addrlen = tgetl(vptr + 5 * n);
             ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
         }
         break;
@@ -1204,7 +1283,7 @@
     case SOCKOP_recvmsg:
         {
             int fd;
-            target_ulong target_msg;
+            abi_ulong target_msg;
             int flags;
 
             fd = tgetl(vptr);
@@ -1220,7 +1299,7 @@
             int sockfd = tgetl(vptr);
             int level = tgetl(vptr + n);
             int optname = tgetl(vptr + 2 * n);
-            target_ulong optval = tgetl(vptr + 3 * n);
+            abi_ulong optval = tgetl(vptr + 3 * n);
             socklen_t optlen = tgetl(vptr + 4 * n);
 
             ret = do_setsockopt(sockfd, level, optname, optval, optlen);
@@ -1231,20 +1310,22 @@
             int sockfd = tgetl(vptr);
             int level = tgetl(vptr + n);
             int optname = tgetl(vptr + 2 * n);
-            target_ulong optval = tgetl(vptr + 3 * n);
-            target_ulong poptlen = tgetl(vptr + 4 * n);
+            abi_ulong optval = tgetl(vptr + 3 * n);
+            abi_ulong poptlen = tgetl(vptr + 4 * n);
 
             ret = do_getsockopt(sockfd, level, optname, optval, poptlen);
         }
         break;
     default:
         gemu_log("Unsupported socketcall: %d\n", num);
-        ret = -ENOSYS;
+        ret = -TARGET_ENOSYS;
         break;
     }
     return ret;
 }
+#endif
 
+#ifdef TARGET_NR_ipc
 #define N_SHM_REGIONS	32
 
 static struct shm_region {
@@ -1254,33 +1335,33 @@
 
 struct target_ipc_perm
 {
-    target_long __key;
-    target_ulong uid;
-    target_ulong gid;
-    target_ulong cuid;
-    target_ulong cgid;
+    abi_long __key;
+    abi_ulong uid;
+    abi_ulong gid;
+    abi_ulong cuid;
+    abi_ulong cgid;
     unsigned short int mode;
     unsigned short int __pad1;
     unsigned short int __seq;
     unsigned short int __pad2;
-    target_ulong __unused1;
-    target_ulong __unused2;
+    abi_ulong __unused1;
+    abi_ulong __unused2;
 };
 
 struct target_semid_ds
 {
   struct target_ipc_perm sem_perm;
-  target_ulong sem_otime;
-  target_ulong __unused1;
-  target_ulong sem_ctime;
-  target_ulong __unused2;
-  target_ulong sem_nsems;
-  target_ulong __unused3;
-  target_ulong __unused4;
+  abi_ulong sem_otime;
+  abi_ulong __unused1;
+  abi_ulong sem_ctime;
+  abi_ulong __unused2;
+  abi_ulong sem_nsems;
+  abi_ulong __unused3;
+  abi_ulong __unused4;
 };
 
 static inline void target_to_host_ipc_perm(struct ipc_perm *host_ip,
-                                           target_ulong target_addr)
+                                           abi_ulong target_addr)
 {
     struct target_ipc_perm *target_ip;
     struct target_semid_ds *target_sd;
@@ -1296,7 +1377,7 @@
     unlock_user_struct(target_sd, target_addr, 0);
 }
 
-static inline void host_to_target_ipc_perm(target_ulong target_addr,
+static inline void host_to_target_ipc_perm(abi_ulong target_addr,
                                            struct ipc_perm *host_ip)
 {
     struct target_ipc_perm *target_ip;
@@ -1314,7 +1395,7 @@
 }
 
 static inline void target_to_host_semid_ds(struct semid_ds *host_sd,
-                                          target_ulong target_addr)
+                                          abi_ulong target_addr)
 {
     struct target_semid_ds *target_sd;
 
@@ -1326,7 +1407,7 @@
     unlock_user_struct(target_sd, target_addr, 0);
 }
 
-static inline void host_to_target_semid_ds(target_ulong target_addr,
+static inline void host_to_target_semid_ds(abi_ulong target_addr,
                                            struct semid_ds *host_sd)
 {
     struct target_semid_ds *target_sd;
@@ -1347,13 +1428,13 @@
 
 union target_semun {
 	int val;
-	target_long buf;
+	abi_long buf;
 	unsigned short int *array;
 };
 
-static inline void target_to_host_semun(unsigned long cmd,
+static inline void target_to_host_semun(int cmd,
                                         union semun *host_su,
-                                        target_ulong target_addr,
+                                        abi_ulong target_addr,
                                         struct semid_ds *ds)
 {
     union target_semun *target_su;
@@ -1383,8 +1464,8 @@
     }
 }
 
-static inline void host_to_target_semun(unsigned long cmd,
-                                        target_ulong target_addr,
+static inline void host_to_target_semun(int cmd,
+                                        abi_ulong target_addr,
                                         union semun *host_su,
                                         struct semid_ds *ds)
 {
@@ -1414,12 +1495,13 @@
     }
 }
 
-static inline long do_semctl(long first, long second, long third, long ptr)
+static inline abi_long do_semctl(int first, int second, int third,
+                                 abi_long ptr)
 {
     union semun arg;
     struct semid_ds dsarg;
     int cmd = third&0xff;
-    long ret = 0;
+    abi_long ret = 0;
 
     switch( cmd ) {
 	case GETVAL:
@@ -1462,23 +1544,23 @@
 struct target_msqid_ds
 {
   struct target_ipc_perm msg_perm;
-  target_ulong msg_stime;
-  target_ulong __unused1;
-  target_ulong msg_rtime;
-  target_ulong __unused2;
-  target_ulong msg_ctime;
-  target_ulong __unused3;
-  target_ulong __msg_cbytes;
-  target_ulong msg_qnum;
-  target_ulong msg_qbytes;
-  target_ulong msg_lspid;
-  target_ulong msg_lrpid;
-  target_ulong __unused4;
-  target_ulong __unused5;
+  abi_ulong msg_stime;
+  abi_ulong __unused1;
+  abi_ulong msg_rtime;
+  abi_ulong __unused2;
+  abi_ulong msg_ctime;
+  abi_ulong __unused3;
+  abi_ulong __msg_cbytes;
+  abi_ulong msg_qnum;
+  abi_ulong msg_qbytes;
+  abi_ulong msg_lspid;
+  abi_ulong msg_lrpid;
+  abi_ulong __unused4;
+  abi_ulong __unused5;
 };
 
 static inline void target_to_host_msqid_ds(struct msqid_ds *host_md,
-                                          target_ulong target_addr)
+                                           abi_ulong target_addr)
 {
     struct target_msqid_ds *target_md;
 
@@ -1495,7 +1577,7 @@
     unlock_user_struct(target_md, target_addr, 0);
 }
 
-static inline void host_to_target_msqid_ds(target_ulong target_addr,
+static inline void host_to_target_msqid_ds(abi_ulong target_addr,
                                            struct msqid_ds *host_md)
 {
     struct target_msqid_ds *target_md;
@@ -1513,11 +1595,11 @@
     unlock_user_struct(target_md, target_addr, 1);
 }
 
-static inline long do_msgctl(long first, long second, long ptr)
+static inline abi_long do_msgctl(int first, int second, abi_long ptr)
 {
     struct msqid_ds dsarg;
     int cmd = second&0xff;
-    long ret = 0;
+    abi_long ret = 0;
     switch( cmd ) {
     case IPC_STAT:
     case IPC_SET:
@@ -1531,15 +1613,16 @@
 }
 
 struct target_msgbuf {
-	target_ulong mtype;
+	abi_ulong mtype;
 	char	mtext[1];
 };
 
-static inline long do_msgsnd(long msqid, long msgp, long msgsz, long msgflg)
+static inline abi_long do_msgsnd(int msqid, abi_long msgp,
+                                 unsigned int msgsz, int msgflg)
 {
     struct target_msgbuf *target_mb;
     struct msgbuf *host_mb;
-    long ret = 0;
+    abi_long ret = 0;
 
     lock_user_struct(target_mb,msgp,0);
     host_mb = malloc(msgsz+sizeof(long));
@@ -1552,11 +1635,13 @@
     return ret;
 }
 
-static inline long do_msgrcv(long msqid, long msgp, long msgsz, long msgtype, long msgflg)
+static inline abi_long do_msgrcv(int msqid, abi_long msgp,
+                                 unsigned int msgsz, int msgtype,
+                                 int msgflg)
 {
     struct target_msgbuf *target_mb;
     struct msgbuf *host_mb;
-    long ret = 0;
+    abi_long ret = 0;
 
     lock_user_struct(target_mb, msgp, 0);
     host_mb = malloc(msgsz+sizeof(long));
@@ -1571,11 +1656,13 @@
 }
 
 /* ??? This only works with linear mappings.  */
-static long do_ipc(long call, long first, long second, long third,
-		   long ptr, long fifth)
+/* do_ipc() must return target values and target errnos. */
+static abi_long do_ipc(unsigned int call, int first,
+                       int second, int third,
+                       abi_long ptr, abi_long fifth)
 {
     int version;
-    long ret = 0;
+    abi_long ret = 0;
     unsigned long raddr;
     struct shmid_ds shm_info;
     int i;
@@ -1597,8 +1684,8 @@
         break;
 
     case IPCOP_semtimedop:
-        gemu_log("Unsupported ipc call: %ld (version %d)\n", call, version);
-        ret = -ENOSYS;
+        gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
+        ret = -TARGET_ENOSYS;
         break;
 
 	case IPCOP_msgget:
@@ -1653,8 +1740,8 @@
                 break;
 	    }
 	}
-	if (put_user(raddr, (uint32_t *)third))
-            return -EFAULT;
+	if (put_user(raddr, (abi_ulong *)third))
+            return -TARGET_EFAULT;
         ret = 0;
 	break;
     case IPCOP_shmdt:
@@ -1687,12 +1774,13 @@
         break;
     default:
     unimplemented:
-	gemu_log("Unsupported ipc call: %ld (version %d)\n", call, version);
-	ret = -ENOSYS;
+	gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
+	ret = -TARGET_ENOSYS;
 	break;
     }
     return ret;
 }
+#endif
 
 /* kernel structure types definitions */
 #define IFNAMSIZ        16
@@ -1733,11 +1821,12 @@
 };
 
 /* ??? Implement proper locking for ioctls.  */
-static long do_ioctl(long fd, long cmd, long arg)
+/* do_ioctl() Must return target values and target errnos. */
+static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
 {
     const IOCTLEntry *ie;
     const argtype *arg_type;
-    long ret;
+    abi_long ret;
     uint8_t buf_temp[MAX_STRUCT_SIZE];
     int target_size;
     void *argptr;
@@ -1745,8 +1834,8 @@
     ie = ioctl_entries;
     for(;;) {
         if (ie->target_cmd == 0) {
-            gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd);
-            return -ENOSYS;
+            gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
+            return -TARGET_ENOSYS;
         }
         if (ie->target_cmd == cmd)
             break;
@@ -1754,7 +1843,7 @@
     }
     arg_type = ie->arg_type;
 #if defined(DEBUG)
-    gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name);
+    gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
 #endif
     switch(arg_type[0]) {
     case TYPE_NULL:
@@ -1799,8 +1888,9 @@
         }
         break;
     default:
-        gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]);
-        ret = -ENOSYS;
+        gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
+                 (long)cmd, arg_type[0]);
+        ret = -TARGET_ENOSYS;
         break;
     }
     return ret;
@@ -2017,7 +2107,7 @@
 /* NOTE: there is really one LDT for all the threads */
 uint8_t *ldt_table;
 
-static int read_ldt(target_ulong ptr, unsigned long bytecount)
+static int read_ldt(abi_ulong ptr, unsigned long bytecount)
 {
     int size;
     void *p;
@@ -2035,8 +2125,9 @@
 }
 
 /* XXX: add locking support */
+/* write_ldt() returns host errnos */
 static int write_ldt(CPUX86State *env,
-                     target_ulong ptr, unsigned long bytecount, int oldmode)
+                     abi_ulong ptr, unsigned long bytecount, int oldmode)
 {
     struct target_modify_ldt_ldt_s ldt_info;
     struct target_modify_ldt_ldt_s *target_ldt_info;
@@ -2117,7 +2208,9 @@
 }
 
 /* specific and weird i386 syscalls */
-int do_modify_ldt(CPUX86State *env, int func, target_ulong ptr, unsigned long bytecount)
+/* do_modify_ldt() returns host errnos (it is inconsistent with the
+   other do_*() functions which return target errnos). */
+int do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr, unsigned long bytecount)
 {
     int ret = -ENOSYS;
 
@@ -2149,7 +2242,9 @@
     return 0;
 }
 
-int do_fork(CPUState *env, unsigned int flags, unsigned long newsp)
+/* do_fork() Must return host values and target errnos (unlike most
+   do_*() functions). */
+int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp)
 {
     int ret;
     TaskState *ts;
@@ -2217,6 +2312,10 @@
             for (i = 7; i < 30; i++)
                 new_env->ir[i] = 0;
         }
+#elif defined(TARGET_CRIS)
+	if (!newsp)
+	  newsp = env->regs[14];
+	new_env->regs[14] = newsp;
 #else
 #error unsupported target CPU
 #endif
@@ -2235,13 +2334,13 @@
     return ret;
 }
 
-static long do_fcntl(int fd, int cmd, target_ulong arg)
+static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
 {
     struct flock fl;
     struct target_flock *target_fl;
     struct flock64 fl64;
     struct target_flock64 *target_fl64;
-    long ret;
+    abi_long ret;
 
     switch(cmd) {
     case TARGET_F_GETLK:
@@ -2400,6 +2499,7 @@
     }
 }
 
+#if TARGET_ABI_BITS == 32
 static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
 {
 #ifdef TARGET_WORDS_BIG_ENDIAN
@@ -2408,10 +2508,18 @@
     return ((uint64_t)word1 << 32) | word0;
 #endif
 }
+#else /* TARGET_ABI_BITS == 32 */
+static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
+{
+    return word0;
+}
+#endif /* TARGET_ABI_BITS != 32 */
 
 #ifdef TARGET_NR_truncate64
-static inline long target_truncate64(void *cpu_env, const char *arg1,
-                                     long arg2, long arg3, long arg4)
+static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
+                                         abi_long arg2,
+                                         abi_long arg3,
+                                         abi_long arg4)
 {
 #ifdef TARGET_ARM
     if (((CPUARMState *)cpu_env)->eabi)
@@ -2425,8 +2533,10 @@
 #endif
 
 #ifdef TARGET_NR_ftruncate64
-static inline long target_ftruncate64(void *cpu_env, long arg1, long arg2,
-                                      long arg3, long arg4)
+static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
+                                          abi_long arg2,
+                                          abi_long arg3,
+                                          abi_long arg4)
 {
 #ifdef TARGET_ARM
     if (((CPUARMState *)cpu_env)->eabi)
@@ -2440,7 +2550,7 @@
 #endif
 
 static inline void target_to_host_timespec(struct timespec *host_ts,
-                                           target_ulong target_addr)
+                                           abi_ulong target_addr)
 {
     struct target_timespec *target_ts;
 
@@ -2450,7 +2560,7 @@
     unlock_user_struct(target_ts, target_addr, 0);
 }
 
-static inline void host_to_target_timespec(target_ulong target_addr,
+static inline void host_to_target_timespec(abi_ulong target_addr,
                                            struct timespec *host_ts)
 {
     struct target_timespec *target_ts;
@@ -2461,10 +2571,14 @@
     unlock_user_struct(target_ts, target_addr, 1);
 }
 
-long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
-                long arg4, long arg5, long arg6)
+/* do_syscall() should always have a single exit point at the end so
+   that actions, such as logging of syscall results, can be performed.
+   All errnos that do_syscall() returns must be -TARGET_<errcode>. */
+abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
+                    abi_long arg2, abi_long arg3, abi_long arg4,
+                    abi_long arg5, abi_long arg6)
 {
-    long ret;
+    abi_long ret;
     struct stat st;
     struct statfs stfs;
     void *p;
@@ -2500,6 +2614,25 @@
                              arg3));
         unlock_user(p, arg1, 0);
         break;
+#if defined(TARGET_NR_openat) && defined(__NR_openat)
+    case TARGET_NR_openat:
+        if (!arg2) {
+            ret = -TARGET_EFAULT;
+            goto fail;
+        }
+        p = lock_user_string(arg2);
+        if (!access_ok(VERIFY_READ, p, 1))
+            /* Don't "goto fail" so that cleanup can happen. */
+            ret = -TARGET_EFAULT;
+        else
+            ret = get_errno(sys_openat(arg1,
+                                       path(p),
+                                       target_to_host_bitmask(arg3, fcntl_flags_tbl),
+                                       arg4));
+        if (p)
+            unlock_user(p, arg2, 0);
+        break;
+#endif
     case TARGET_NR_close:
         ret = get_errno(close(arg1));
         break;
@@ -2536,19 +2669,58 @@
             unlock_user(p, arg1, 0);
         }
         break;
+#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
+    case TARGET_NR_linkat:
+        if (!arg2 || !arg4) {
+            ret = -TARGET_EFAULT;
+            goto fail;
+        }
+        {
+            void * p2 = NULL;
+            p  = lock_user_string(arg2);
+            p2 = lock_user_string(arg4);
+            if (!access_ok(VERIFY_READ, p, 1)
+                || !access_ok(VERIFY_READ, p2, 1))
+                /* Don't "goto fail" so that cleanup can happen. */
+                ret = -TARGET_EFAULT;
+            else
+                ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
+            if (p2)
+                unlock_user(p, arg2, 0);
+            if (p)
+                unlock_user(p2, arg4, 0);
+        }
+        break;
+#endif
     case TARGET_NR_unlink:
         p = lock_user_string(arg1);
         ret = get_errno(unlink(p));
         unlock_user(p, arg1, 0);
         break;
+#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
+    case TARGET_NR_unlinkat:
+        if (!arg2) {
+            ret = -TARGET_EFAULT;
+            goto fail;
+        }
+        p = lock_user_string(arg2);
+        if (!access_ok(VERIFY_READ, p, 1))
+            /* Don't "goto fail" so that cleanup can happen. */
+            ret = -TARGET_EFAULT;
+        else
+            ret = get_errno(sys_unlinkat(arg1, p, arg3));
+        if (p)
+            unlock_user(p, arg2, 0);
+        break;
+#endif
     case TARGET_NR_execve:
         {
             char **argp, **envp;
             int argc, envc;
-            target_ulong gp;
-            target_ulong guest_argp;
-            target_ulong guest_envp;
-            target_ulong addr;
+            abi_ulong gp;
+            abi_ulong guest_argp;
+            abi_ulong guest_envp;
+            abi_ulong addr;
             char **q;
 
             argc = 0;
@@ -2564,7 +2736,7 @@
             envp = alloca((envc + 1) * sizeof(void *));
 
             for (gp = guest_argp, q = argp; ;
-                  gp += sizeof(target_ulong), q++) {
+                  gp += sizeof(abi_ulong), q++) {
                 addr = tgetl(gp);
                 if (!addr)
                     break;
@@ -2573,7 +2745,7 @@
             *q = NULL;
 
             for (gp = guest_envp, q = envp; ;
-                  gp += sizeof(target_ulong), q++) {
+                  gp += sizeof(abi_ulong), q++) {
                 addr = tgetl(gp);
                 if (!addr)
                     break;
@@ -2586,12 +2758,12 @@
             unlock_user(p, arg1, 0);
 
             for (gp = guest_argp, q = argp; *q;
-                  gp += sizeof(target_ulong), q++) {
+                  gp += sizeof(abi_ulong), q++) {
                 addr = tgetl(gp);
                 unlock_user(*q, addr, 0);
             }
             for (gp = guest_envp, q = envp; *q;
-                  gp += sizeof(target_ulong), q++) {
+                  gp += sizeof(abi_ulong), q++) {
                 addr = tgetl(gp);
                 unlock_user(*q, addr, 0);
             }
@@ -2617,6 +2789,22 @@
         ret = get_errno(mknod(p, arg2, arg3));
         unlock_user(p, arg1, 0);
         break;
+#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
+    case TARGET_NR_mknodat:
+        if (!arg2) {
+            ret = -TARGET_EFAULT;
+            goto fail;
+        }
+        p = lock_user_string(arg2);
+        if (!access_ok(VERIFY_READ, p, 1))
+            /* Don't "goto fail" so that cleanup can happen. */
+            ret = -TARGET_EFAULT;
+        else
+            ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
+        if (p)
+            unlock_user(p, arg2, 0);
+        break;
+#endif
     case TARGET_NR_chmod:
         p = lock_user_string(arg1);
         ret = get_errno(chmod(p, arg2));
@@ -2734,6 +2922,22 @@
         ret = get_errno(access(p, arg2));
         unlock_user(p, arg1, 0);
         break;
+#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
+    case TARGET_NR_faccessat:
+        if (!arg2) {
+            ret = -TARGET_EFAULT;
+            goto fail;
+        }
+        p = lock_user_string(arg2);
+        if (!access_ok(VERIFY_READ, p, 1))
+            /* Don't "goto fail" so that cleanup can happen. */
+    	    ret = -TARGET_EFAULT;
+        else
+            ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
+        if (p)
+            unlock_user(p, arg2, 0);
+        break;
+#endif
 #ifdef TARGET_NR_nice /* not on alpha */
     case TARGET_NR_nice:
         ret = get_errno(nice(arg1));
@@ -2760,11 +2964,50 @@
             unlock_user(p, arg1, 0);
         }
         break;
+#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
+    case TARGET_NR_renameat:
+        if (!arg2 || !arg4) {
+            ret = -TARGET_EFAULT;
+            goto fail;
+        }
+        {
+            void *p2 = NULL;
+            p  = lock_user_string(arg2);
+            p2 = lock_user_string(arg4);
+            if (!access_ok(VERIFY_READ, p, 1)
+                || !access_ok(VERIFY_READ, p2, 1))
+                /* Don't "goto fail" so that cleanup can happen. */
+                ret = -TARGET_EFAULT;
+            else
+                ret = get_errno(sys_renameat(arg1, p, arg3, p2));
+            if (p2)
+                unlock_user(p2, arg4, 0);
+            if (p)
+                unlock_user(p, arg2, 0);
+        }
+        break;
+#endif
     case TARGET_NR_mkdir:
         p = lock_user_string(arg1);
         ret = get_errno(mkdir(p, arg2));
         unlock_user(p, arg1, 0);
         break;
+#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
+    case TARGET_NR_mkdirat:
+        if (!arg2) {
+            ret = -TARGET_EFAULT;
+            goto fail;
+        }
+        p = lock_user_string(arg2);
+        if (!access_ok(VERIFY_READ, p, 1))
+            /* Don't "goto fail" so that cleanup can happen. */
+            ret = -TARGET_EFAULT;
+        else
+            ret = get_errno(sys_mkdirat(arg1, p, arg3));
+        if (p)
+            unlock_user(p, arg2, 0);
+        break;
+#endif
     case TARGET_NR_rmdir:
         p = lock_user_string(arg1);
         ret = get_errno(rmdir(p));
@@ -2954,7 +3197,7 @@
     case TARGET_NR_sgetmask:
         {
             sigset_t cur_set;
-            target_ulong target_set;
+            abi_ulong target_set;
             sigprocmask(0, NULL, &cur_set);
             host_to_target_old_sigset(&target_set, &cur_set);
             ret = target_set;
@@ -2965,7 +3208,7 @@
     case TARGET_NR_ssetmask:
         {
             sigset_t set, oset, cur_set;
-            target_ulong target_set = arg1;
+            abi_ulong target_set = arg1;
             sigprocmask(0, NULL, &cur_set);
             target_to_host_old_sigset(&set, &target_set);
             sigorset(&set, &set, &cur_set);
@@ -2993,7 +3236,7 @@
                     how = SIG_SETMASK;
                     break;
                 default:
-                    ret = -EINVAL;
+                    ret = -TARGET_EINVAL;
                     goto fail;
                 }
                 p = lock_user(arg2, sizeof(target_sigset_t), 1);
@@ -3030,7 +3273,7 @@
                     how = SIG_SETMASK;
                     break;
                 default:
-                    ret = -EINVAL;
+                    ret = -TARGET_EINVAL;
                     goto fail;
                 }
                 p = lock_user(arg2, sizeof(target_sigset_t), 1);
@@ -3198,7 +3441,7 @@
     case TARGET_NR_select:
         {
             struct target_sel_arg_struct *sel;
-            target_ulong inp, outp, exp, tvp;
+            abi_ulong inp, outp, exp, tvp;
             long nsel;
 
             lock_user_struct(sel, arg1, 1);
@@ -3222,6 +3465,29 @@
             unlock_user(p, arg1, 0);
         }
         break;
+#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
+    case TARGET_NR_symlinkat:
+        if (!arg1 || !arg3) {
+            ret = -TARGET_EFAULT;
+            goto fail;
+        }
+        {
+            void *p2 = NULL;
+            p  = lock_user_string(arg1);
+            p2 = lock_user_string(arg3);
+            if (!access_ok(VERIFY_READ, p, 1)
+                || !access_ok(VERIFY_READ, p2, 1))
+                /* Don't "goto fail" so that cleanup can happen. */
+                ret = -TARGET_EFAULT;
+            else
+                ret = get_errno(sys_symlinkat(p, arg2, p2));
+            if (p2)
+                unlock_user(p2, arg3, 0);
+            if (p)
+                unlock_user(p, arg1, 0);
+        }
+        break;
+#endif
 #ifdef TARGET_NR_oldlstat
     case TARGET_NR_oldlstat:
         goto unimplemented;
@@ -3236,6 +3502,29 @@
             unlock_user(p, arg1, 0);
         }
         break;
+#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
+    case TARGET_NR_readlinkat:
+        if (!arg2 || !arg3) {
+            ret = -TARGET_EFAULT;
+            goto fail;
+        }
+        {
+            void *p2 = NULL;
+            p  = lock_user_string(arg2);
+            p2 = lock_user(arg3, arg4, 0);
+            if (!access_ok(VERIFY_READ, p, 1)
+                || !access_ok(VERIFY_READ, p2, 1))
+                /* Don't "goto fail" so that cleanup can happen. */
+        	ret = -TARGET_EFAULT;
+            else
+                ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
+            if (p2)
+                unlock_user(p2, arg3, ret);
+            if (p)
+                unlock_user(p, arg2, 0);
+        }
+        break;
+#endif
 #ifdef TARGET_NR_uselib
     case TARGET_NR_uselib:
         goto unimplemented;
@@ -3255,11 +3544,11 @@
 #endif
 #ifdef TARGET_NR_mmap
     case TARGET_NR_mmap:
-#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_M68K)
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
         {
-            target_ulong *v;
-            target_ulong v1, v2, v3, v4, v5, v6;
-            v = lock_user(arg1, 6 * sizeof(target_ulong), 1);
+            abi_ulong *v;
+            abi_ulong v1, v2, v3, v4, v5, v6;
+            v = lock_user(arg1, 6 * sizeof(abi_ulong), 1);
             v1 = tswapl(v[0]);
             v2 = tswapl(v[1]);
             v3 = tswapl(v[2]);
@@ -3340,8 +3629,27 @@
     case TARGET_NR_fchmod:
         ret = get_errno(fchmod(arg1, arg2));
         break;
+#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
+    case TARGET_NR_fchmodat:
+        if (!arg2) {
+            ret = -TARGET_EFAULT;
+            goto fail;
+        }
+        p = lock_user_string(arg2);
+        if (!access_ok(VERIFY_READ, p, 1))
+            /* Don't "goto fail" so that cleanup can happen. */
+            ret = -TARGET_EFAULT;
+        else
+            ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
+        if (p)
+            unlock_user(p, arg2, 0);
+        break;
+#endif
     case TARGET_NR_getpriority:
-        ret = get_errno(getpriority(arg1, arg2));
+        /* libc does special remapping of the return value of
+         * sys_getpriority() so it's just easiest to call
+         * sys_getpriority() directly rather than through libc. */
+        ret = sys_getpriority(arg1, arg2);
         break;
     case TARGET_NR_setpriority:
         ret = get_errno(setpriority(arg1, arg2, arg3));
@@ -3558,7 +3866,7 @@
                 struct target_stat *target_st;
 
                 lock_user_struct(target_st, arg2, 0);
-#if defined(TARGET_MIPS) || defined(TARGET_SPARC64)
+#if defined(TARGET_MIPS) || (defined(TARGET_SPARC64) && !defined(TARGET_ABI32))
                 target_st->st_dev = tswap32(st.st_dev);
 #else
                 target_st->st_dev = tswap16(st.st_dev);
@@ -3568,7 +3876,7 @@
                 target_st->st_mode = tswapl(st.st_mode); /* XXX: check this */
                 target_st->st_uid = tswap32(st.st_uid);
                 target_st->st_gid = tswap32(st.st_gid);
-#elif defined(TARGET_SPARC64)
+#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
                 target_st->st_mode = tswap32(st.st_mode);
                 target_st->st_uid = tswap32(st.st_uid);
                 target_st->st_gid = tswap32(st.st_gid);
@@ -3581,7 +3889,7 @@
 		/* If this is the same on PPC, then just merge w/ the above ifdef */
                 target_st->st_nlink = tswapl(st.st_nlink);
                 target_st->st_rdev = tswapl(st.st_rdev);
-#elif defined(TARGET_SPARC64)
+#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
                 target_st->st_nlink = tswap32(st.st_nlink);
                 target_st->st_rdev = tswap32(st.st_rdev);
 #else
@@ -3621,9 +3929,9 @@
     case TARGET_NR_wait4:
         {
             int status;
-            target_long status_ptr = arg2;
+            abi_long status_ptr = arg2;
             struct rusage rusage, *rusage_ptr;
-            target_ulong target_rusage = arg4;
+            abi_ulong target_rusage = arg4;
             if (target_rusage)
                 rusage_ptr = &rusage;
             else
@@ -3774,18 +4082,20 @@
         break;
 #endif
     case TARGET_NR_getdents:
-#if TARGET_LONG_SIZE != 4
+#if TARGET_ABI_BITS != 32
         goto unimplemented;
 #warning not supported
-#elif TARGET_LONG_SIZE == 4 && HOST_LONG_SIZE == 8
+#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
         {
             struct target_dirent *target_dirp;
             struct dirent *dirp;
-            long count = arg3;
+            abi_long count = arg3;
 
 	    dirp = malloc(count);
-	    if (!dirp)
-                return -ENOMEM;
+	    if (!dirp) {
+                ret = -TARGET_EFAULT;
+                goto fail;
+            }
 
             ret = get_errno(sys_getdents(arg1, dirp, count));
             if (!is_error(ret)) {
@@ -3801,11 +4111,11 @@
 		tde = target_dirp;
                 while (len > 0) {
                     reclen = de->d_reclen;
-		    treclen = reclen - (2 * (sizeof(long) - sizeof(target_long)));
+		    treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
                     tde->d_reclen = tswap16(treclen);
                     tde->d_ino = tswapl(de->d_ino);
                     tde->d_off = tswapl(de->d_off);
-		    tnamelen = treclen - (2 * sizeof(target_long) + 2);
+		    tnamelen = treclen - (2 * sizeof(abi_long) + 2);
 		    if (tnamelen > 256)
                         tnamelen = 256;
                     /* XXX: may not be correct */
@@ -3823,7 +4133,7 @@
 #else
         {
             struct dirent *dirp;
-            long count = arg3;
+            abi_long count = arg3;
 
             dirp = lock_user(arg2, count, 0);
             ret = get_errno(sys_getdents(arg1, dirp, count));
@@ -3851,7 +4161,7 @@
     case TARGET_NR_getdents64:
         {
             struct dirent64 *dirp;
-            long count = arg3;
+            abi_long count = arg3;
             dirp = lock_user(arg2, count, 0);
             ret = get_errno(sys_getdents64(arg1, dirp, count));
             if (!is_error(ret)) {
@@ -3942,9 +4252,10 @@
         break;
 #endif
     case TARGET_NR__sysctl:
-        /* We don't implement this, but ENODIR is always a safe
+        /* We don't implement this, but ENOTDIR is always a safe
            return value. */
-        return -ENOTDIR;
+        ret = -TARGET_ENOTDIR;
+        break;
     case TARGET_NR_sched_setparam:
         {
             struct sched_param *target_schp;
@@ -4056,7 +4367,15 @@
     case TARGET_NR_capset:
         goto unimplemented;
     case TARGET_NR_sigaltstack:
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
+    defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
+        ret = do_sigaltstack((struct target_sigaltstack *)arg1,
+                             (struct target_sigaltstack *)arg2,
+                             get_sp_from_cpustate((CPUState *)cpu_env));
+        break;
+#else
         goto unimplemented;
+#endif
     case TARGET_NR_sendfile:
         goto unimplemented;
 #ifdef TARGET_NR_getpmsg
@@ -4232,6 +4551,22 @@
     case TARGET_NR_fchown:
         ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
         break;
+#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
+    case TARGET_NR_fchownat:
+        if (!arg2) {
+            ret = -TARGET_EFAULT;
+            goto fail;
+        }
+        p = lock_user_string(arg2);
+        if (!access_ok(VERIFY_READ, p, 1))
+            /* Don't "goto fail" so that cleanup can happen. */
+            ret = -TARGET_EFAULT;
+	else
+            ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
+        if (p)
+            unlock_user(p, arg2, 0);
+        break;
+#endif
 #ifdef TARGET_NR_setresuid
     case TARGET_NR_setresuid:
         ret = get_errno(setresuid(low2highuid(arg1),
@@ -4448,7 +4783,7 @@
         ret = get_errno(0);
         break;
 #endif
-#if TARGET_LONG_BITS == 32
+#if TARGET_ABI_BITS == 32
     case TARGET_NR_fcntl64:
     {
 	int cmd;
@@ -4653,13 +4988,35 @@
 	goto unimplemented_nowarn;
 #endif
 
+#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
+    case TARGET_NR_utimensat:
+        {
+            struct timespec ts[2];
+            target_to_host_timespec(ts, arg3);
+            target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
+            if (!arg2)
+                ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
+            else {
+                p = lock_user_string(arg2);
+                if (!access_ok(VERIFY_READ, p, 1))
+                    /* Don't "goto fail" so that cleanup can happen. */
+                    ret = -TARGET_EFAULT;
+                else
+                    ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
+                if (p)
+                    unlock_user(p, arg2, 0);
+            }
+        }
+	break;
+#endif
+
     default:
     unimplemented:
         gemu_log("qemu: Unsupported syscall: %d\n", num);
 #if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
     unimplemented_nowarn:
 #endif
-        ret = -ENOSYS;
+        ret = -TARGET_ENOSYS;
         break;
     }
  fail:
@@ -4668,4 +5025,3 @@
 #endif
     return ret;
 }
-

Modified: trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -49,7 +49,7 @@
 #define TARGET_IOC_TYPEBITS	8
 
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
-    || defined(TARGET_M68K) || defined(TARGET_ALPHA)
+    || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
 
 #define TARGET_IOC_SIZEBITS	14
 #define TARGET_IOC_DIRBITS	2
@@ -105,13 +105,13 @@
 };
 
 struct target_timeval {
-    target_long tv_sec;
-    target_long tv_usec;
+    abi_long tv_sec;
+    abi_long tv_usec;
 };
 
 struct target_timespec {
-    target_long tv_sec;
-    target_long tv_nsec;
+    abi_long tv_sec;
+    abi_long tv_nsec;
 };
 
 struct target_itimerval {
@@ -119,7 +119,7 @@
     struct target_timeval it_value;
 };
 
-typedef target_long target_clock_t;
+typedef abi_long target_clock_t;
 
 #define TARGET_HZ 100
 
@@ -131,33 +131,33 @@
 };
 
 struct target_utimbuf {
-    target_long actime;
-    target_long modtime;
+    abi_long actime;
+    abi_long modtime;
 };
 
 struct target_sel_arg_struct {
-    target_long n;
-    target_long inp, outp, exp;
-    target_long tvp;
+    abi_long n;
+    abi_long inp, outp, exp;
+    abi_long tvp;
 };
 
 struct target_iovec {
-    target_long iov_base;   /* Starting address */
-    target_long iov_len;   /* Number of bytes */
+    abi_long iov_base;   /* Starting address */
+    abi_long iov_len;   /* Number of bytes */
 };
 
 struct target_msghdr {
-    target_long	 msg_name;	/* Socket name			*/
-    int		 msg_namelen;	/* Length of name		*/
-    target_long	 msg_iov;	/* Data blocks			*/
-    target_long	 msg_iovlen;	/* Number of blocks		*/
-    target_long  msg_control;	/* Per protocol magic (eg BSD file descriptor passing) */
-    target_long	 msg_controllen;	/* Length of cmsg list */
+    abi_long	 msg_name;	 /* Socket name			*/
+    int		 msg_namelen;	 /* Length of name		*/
+    abi_long	 msg_iov;	 /* Data blocks			*/
+    abi_long	 msg_iovlen;	 /* Number of blocks		*/
+    abi_long     msg_control;	 /* Per protocol magic (eg BSD file descriptor passing) */
+    abi_long	 msg_controllen; /* Length of cmsg list */
     unsigned int msg_flags;
 };
 
 struct target_cmsghdr {
-    target_long  cmsg_len;
+    abi_long     cmsg_len;
     int          cmsg_level;
     int          cmsg_type;
 };
@@ -167,8 +167,8 @@
 #define TARGET_CMSG_FIRSTHDR(mhdr) \
   ((size_t) tswapl((mhdr)->msg_controllen) >= sizeof (struct target_cmsghdr) \
    ? (struct target_cmsghdr *) tswapl((mhdr)->msg_control) : (struct target_cmsghdr *) NULL)
-#define TARGET_CMSG_ALIGN(len) (((len) + sizeof (target_long) - 1) \
-                               & (size_t) ~(sizeof (target_long) - 1))
+#define TARGET_CMSG_ALIGN(len) (((len) + sizeof (abi_long) - 1) \
+                               & (size_t) ~(sizeof (abi_long) - 1))
 #define TARGET_CMSG_SPACE(len) (TARGET_CMSG_ALIGN (len) \
                                + TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)))
 #define TARGET_CMSG_LEN(len)   (TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)) + (len))
@@ -191,20 +191,20 @@
 struct  target_rusage {
         struct target_timeval ru_utime;        /* user time used */
         struct target_timeval ru_stime;        /* system time used */
-        target_long    ru_maxrss;              /* maximum resident set size */
-        target_long    ru_ixrss;               /* integral shared memory size */
-        target_long    ru_idrss;               /* integral unshared data size */
-        target_long    ru_isrss;               /* integral unshared stack size */
-        target_long    ru_minflt;              /* page reclaims */
-        target_long    ru_majflt;              /* page faults */
-        target_long    ru_nswap;               /* swaps */
-        target_long    ru_inblock;             /* block input operations */
-        target_long    ru_oublock;             /* block output operations */
-        target_long    ru_msgsnd;              /* messages sent */
-        target_long    ru_msgrcv;              /* messages received */
-        target_long    ru_nsignals;            /* signals received */
-        target_long    ru_nvcsw;               /* voluntary context switches */
-        target_long    ru_nivcsw;              /* involuntary " */
+        abi_long    ru_maxrss;                 /* maximum resident set size */
+        abi_long    ru_ixrss;                  /* integral shared memory size */
+        abi_long    ru_idrss;                  /* integral unshared data size */
+        abi_long    ru_isrss;                  /* integral unshared stack size */
+        abi_long    ru_minflt;                 /* page reclaims */
+        abi_long    ru_majflt;                 /* page faults */
+        abi_long    ru_nswap;                  /* swaps */
+        abi_long    ru_inblock;                /* block input operations */
+        abi_long    ru_oublock;                /* block output operations */
+        abi_long    ru_msgsnd;                 /* messages sent */
+        abi_long    ru_msgrcv;                 /* messages received */
+        abi_long    ru_nsignals;               /* signals received */
+        abi_long    ru_nvcsw;                  /* voluntary context switches */
+        abi_long    ru_nivcsw;                 /* involuntary " */
 };
 
 typedef struct {
@@ -225,8 +225,8 @@
 };
 
 struct target_dirent {
-	target_long	d_ino;
-	target_long	d_off;
+	abi_long	d_ino;
+	abi_long	d_off;
 	unsigned short	d_reclen;
 	char		d_name[256]; /* We must not include limits.h! */
 };
@@ -241,20 +241,20 @@
 
 
 /* mostly generic signal stuff */
-#define TARGET_SIG_DFL	((target_long)0)	/* default signal handling */
-#define TARGET_SIG_IGN	((target_long)1)	/* ignore signal */
-#define TARGET_SIG_ERR	((target_long)-1)	/* error return from signal */
+#define TARGET_SIG_DFL	((abi_long)0)	/* default signal handling */
+#define TARGET_SIG_IGN	((abi_long)1)	/* ignore signal */
+#define TARGET_SIG_ERR	((abi_long)-1)	/* error return from signal */
 
 #ifdef TARGET_MIPS
 #define TARGET_NSIG	   128
 #else
 #define TARGET_NSIG	   64
 #endif
-#define TARGET_NSIG_BPW	   TARGET_LONG_BITS
+#define TARGET_NSIG_BPW	   TARGET_ABI_BITS
 #define TARGET_NSIG_WORDS  (TARGET_NSIG / TARGET_NSIG_BPW)
 
 typedef struct {
-    target_ulong sig[TARGET_NSIG_WORDS];
+    abi_ulong sig[TARGET_NSIG_WORDS];
 } target_sigset_t;
 
 #ifdef BSWAP_NEEDED
@@ -271,7 +271,7 @@
 }
 #endif
 
-static inline void target_siginitset(target_sigset_t *d, target_ulong set)
+static inline void target_siginitset(target_sigset_t *d, abi_ulong set)
 {
     int i;
     d->sig[0] = set;
@@ -281,15 +281,15 @@
 
 void host_to_target_sigset(target_sigset_t *d, const sigset_t *s);
 void target_to_host_sigset(sigset_t *d, const target_sigset_t *s);
-void host_to_target_old_sigset(target_ulong *old_sigset,
+void host_to_target_old_sigset(abi_ulong *old_sigset,
                                const sigset_t *sigset);
 void target_to_host_old_sigset(sigset_t *sigset,
-                               const target_ulong *old_sigset);
+                               const abi_ulong *old_sigset);
 struct target_sigaction;
 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) || defined(TARGET_ALPHA)
+#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) || defined(TARGET_CRIS)
 
 #if defined(TARGET_SPARC)
 #define TARGET_SA_NOCLDSTOP    8u
@@ -307,7 +307,9 @@
 #define TARGET_SA_NODEFER	0x40000000
 #define TARGET_SA_RESTART	0x10000000
 #define TARGET_SA_RESETHAND	0x80000000
+#if !defined(TARGET_MIPSN32) && !defined(TARGET_MIPS64)
 #define TARGET_SA_RESTORER	0x04000000	/* Only for o32 */
+#endif
 #else
 #define TARGET_SA_NOCLDSTOP	0x00000001
 #define TARGET_SA_NOCLDWAIT	0x00000002 /* not supported yet */
@@ -447,40 +449,44 @@
 #if defined(TARGET_MIPS)
 
 struct target_sigaction {
-	target_ulong	sa_flags;
-	target_ulong	_sa_handler;
+	uint32_t	sa_flags;
+#if defined(TARGET_MIPSN32)
+	uint32_t	_sa_handler;
+#else
+	abi_ulong	_sa_handler;
+#endif
 	target_sigset_t	sa_mask;
 };
 
 #else
 struct target_old_sigaction {
-        target_ulong _sa_handler;
-        target_ulong sa_mask;
-        target_ulong sa_flags;
-        target_ulong sa_restorer;
+        abi_ulong _sa_handler;
+        abi_ulong sa_mask;
+        abi_ulong sa_flags;
+        abi_ulong sa_restorer;
 };
 
 struct target_sigaction {
-        target_ulong _sa_handler;
-        target_ulong sa_flags;
-        target_ulong sa_restorer;
+        abi_ulong _sa_handler;
+        abi_ulong sa_flags;
+        abi_ulong sa_restorer;
         target_sigset_t sa_mask;
 };
 #endif
 
 typedef union target_sigval {
 	int sival_int;
-        target_ulong sival_ptr;
+        abi_ulong sival_ptr;
 } target_sigval_t;
 #if 0
 #if defined (TARGET_SPARC)
 typedef struct {
 	struct {
-		target_ulong psr;
-		target_ulong pc;
-		target_ulong npc;
-		target_ulong y;
-		target_ulong u_regs[16]; /* globals and ins */
+		abi_ulong psr;
+		abi_ulong pc;
+		abi_ulong npc;
+		abi_ulong y;
+		abi_ulong u_regs[16]; /* globals and ins */
 	}		si_regs;
 	int		si_mask;
 } __siginfo_t;
@@ -538,7 +544,7 @@
 
 		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
 		struct {
-			target_ulong _addr; /* faulting insn/memory ref. */
+			abi_ulong _addr; /* faulting insn/memory ref. */
 		} _sigfault;
 
 		/* SIGPOLL */
@@ -608,8 +614,8 @@
 #endif /* defined(TARGET_I386) || defined(TARGET_ARM) */
 
 struct target_rlimit {
-        target_ulong   rlim_cur;
-        target_ulong   rlim_max;
+        abi_ulong   rlim_cur;
+        abi_ulong   rlim_max;
 };
 
 struct target_pollfd {
@@ -860,6 +866,8 @@
 #define TARGET_MAP_EXECUTABLE	0x4000		/* mark it as an executable */
 #define TARGET_MAP_LOCKED	0x8000		/* pages are locked */
 #define TARGET_MAP_NORESERVE	0x0400		/* don't check for reservations */
+#define TARGET_MAP_POPULATE	0x10000		/* populate (prefault) pagetables */
+#define TARGET_MAP_NONBLOCK	0x20000		/* do not block on IO */
 #else
 #define TARGET_MAP_ANONYMOUS	0x20		/* don't use a file */
 #define TARGET_MAP_GROWSDOWN	0x0100		/* stack-like segment */
@@ -872,30 +880,32 @@
 #define TARGET_MAP_LOCKED	0x2000		/* pages are locked */
 #define TARGET_MAP_NORESERVE	0x4000		/* don't check for reservations */
 #endif
+#define TARGET_MAP_POPULATE	0x8000		/* populate (prefault) pagetables */
+#define TARGET_MAP_NONBLOCK	0x10000		/* do not block on IO */
 #endif
 
-#if defined(TARGET_I386) || defined(TARGET_ARM)
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_CRIS)
 struct target_stat {
 	unsigned short st_dev;
 	unsigned short __pad1;
-	target_ulong st_ino;
+	abi_ulong st_ino;
 	unsigned short st_mode;
 	unsigned short st_nlink;
 	unsigned short st_uid;
 	unsigned short st_gid;
 	unsigned short st_rdev;
 	unsigned short __pad2;
-	target_ulong  st_size;
-	target_ulong  st_blksize;
-	target_ulong  st_blocks;
-	target_ulong  target_st_atime;
-	target_ulong  __unused1;
-	target_ulong  target_st_mtime;
-	target_ulong  __unused2;
-	target_ulong  target_st_ctime;
-	target_ulong  __unused3;
-	target_ulong  __unused4;
-	target_ulong  __unused5;
+	abi_ulong  st_size;
+	abi_ulong  st_blksize;
+	abi_ulong  st_blocks;
+	abi_ulong  target_st_atime;
+	abi_ulong  __unused1;
+	abi_ulong  target_st_mtime;
+	abi_ulong  __unused2;
+	abi_ulong  target_st_ctime;
+	abi_ulong  __unused3;
+	abi_ulong  __unused4;
+	abi_ulong  __unused5;
 };
 
 /* This matches struct stat64 in glibc2.1, hence the absolutely
@@ -906,31 +916,31 @@
 	unsigned char	__pad0[10];
 
 #define TARGET_STAT64_HAS_BROKEN_ST_INO	1
-	target_ulong	__st_ino;
+	abi_ulong	__st_ino;
 
 	unsigned int	st_mode;
 	unsigned int	st_nlink;
 
-	target_ulong	st_uid;
-	target_ulong	st_gid;
+	abi_ulong	st_uid;
+	abi_ulong	st_gid;
 
 	unsigned short	st_rdev;
 	unsigned char	__pad3[10];
 
 	long long	st_size;
-	target_ulong	st_blksize;
+	abi_ulong	st_blksize;
 
-	target_ulong	st_blocks;	/* Number 512-byte blocks allocated. */
-	target_ulong	__pad4;		/* future possible st_blocks high bits */
+	abi_ulong	st_blocks;	/* Number 512-byte blocks allocated. */
+	abi_ulong	__pad4;		/* future possible st_blocks high bits */
 
-	target_ulong	target_st_atime;
-	target_ulong	__pad5;
+	abi_ulong	target_st_atime;
+	abi_ulong	__pad5;
 
-	target_ulong	target_st_mtime;
-	target_ulong	__pad6;
+	abi_ulong	target_st_mtime;
+	abi_ulong	__pad6;
 
-	target_ulong	target_st_ctime;
-	target_ulong	__pad7;		/* will be high 32 bits of ctime someday */
+	abi_ulong	target_st_ctime;
+	abi_ulong	__pad7;		/* will be high 32 bits of ctime someday */
 
 	unsigned long long	st_ino;
 } __attribute__((packed));
@@ -939,50 +949,50 @@
 struct target_eabi_stat64 {
         unsigned long long st_dev;
         unsigned int    __pad1;
-        target_ulong    __st_ino;
+        abi_ulong    __st_ino;
         unsigned int    st_mode;
         unsigned int    st_nlink;
 
-        target_ulong    st_uid;
-        target_ulong    st_gid;
+        abi_ulong    st_uid;
+        abi_ulong    st_gid;
 
         unsigned long long st_rdev;
         unsigned int    __pad2[2];
 
         long long       st_size;
-        target_ulong    st_blksize;
+        abi_ulong    st_blksize;
         unsigned int    __pad3;
         unsigned long long st_blocks;
 
-        target_ulong    target_st_atime;
-        target_ulong    target_st_atime_nsec;
+        abi_ulong    target_st_atime;
+        abi_ulong    target_st_atime_nsec;
 
-        target_ulong    target_st_mtime;
-        target_ulong    target_st_mtime_nsec;
+        abi_ulong    target_st_mtime;
+        abi_ulong    target_st_mtime_nsec;
 
-        target_ulong    target_st_ctime;
-        target_ulong    target_st_ctime_nsec;
+        abi_ulong    target_st_ctime;
+        abi_ulong    target_st_ctime_nsec;
 
         unsigned long long st_ino;
 } __attribute__ ((packed));
 #endif
 
-#elif defined(TARGET_SPARC64)
+#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
 struct target_stat {
 	unsigned int	st_dev;
-	target_ulong	st_ino;
+	abi_ulong	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_long	target_st_atime;
-	target_long	target_st_mtime;
-	target_long	target_st_ctime;
-	target_long	st_blksize;
-	target_long	st_blocks;
-	target_ulong	__unused4[2];
+	abi_long	st_size;
+	abi_long	target_st_atime;
+	abi_long	target_st_mtime;
+	abi_long	target_st_ctime;
+	abi_long	st_blksize;
+	abi_long	st_blocks;
+	abi_ulong	__unused4[2];
 };
 
 struct target_stat64 {
@@ -1006,38 +1016,38 @@
 	unsigned char	__pad4[4];
 	unsigned int	st_blocks;
 
-	target_ulong	target_st_atime;
-	target_ulong	__unused1;
+	abi_ulong	target_st_atime;
+	abi_ulong	__unused1;
 
-	target_ulong	target_st_mtime;
-	target_ulong	__unused2;
+	abi_ulong	target_st_mtime;
+	abi_ulong	__unused2;
 
-	target_ulong	target_st_ctime;
-	target_ulong	__unused3;
+	abi_ulong	target_st_ctime;
+	abi_ulong	__unused3;
 
-	target_ulong	__unused4[3];
+	abi_ulong	__unused4[3];
 };
 
 #elif defined(TARGET_SPARC)
 
 struct target_stat {
 	unsigned short	st_dev;
-	target_ulong	st_ino;
+	abi_ulong	st_ino;
 	unsigned short	st_mode;
 	short		st_nlink;
 	unsigned short	st_uid;
 	unsigned short	st_gid;
 	unsigned short	st_rdev;
-	target_long	st_size;
-	target_long	target_st_atime;
-	target_ulong	__unused1;
-	target_long	target_st_mtime;
-	target_ulong	__unused2;
-	target_long	target_st_ctime;
-	target_ulong	__unused3;
-	target_long	st_blksize;
-	target_long	st_blocks;
-	target_ulong	__unused4[2];
+	abi_long	st_size;
+	abi_long	target_st_atime;
+	abi_ulong	__unused1;
+	abi_long	target_st_mtime;
+	abi_ulong	__unused2;
+	abi_long	target_st_ctime;
+	abi_ulong	__unused3;
+	abi_long	st_blksize;
+	abi_long	st_blocks;
+	abi_ulong	__unused4[2];
 };
 
 struct target_stat64 {
@@ -1080,23 +1090,23 @@
 
 struct target_stat {
 	unsigned short st_dev;
-	target_ulong st_ino;
+	abi_ulong st_ino;
 	unsigned int st_mode;
 	unsigned short st_nlink;
 	unsigned int st_uid;
 	unsigned int st_gid;
 	unsigned short st_rdev;
-	target_ulong  st_size;
-	target_ulong  st_blksize;
-	target_ulong  st_blocks;
-	target_ulong  target_st_atime;
-	target_ulong  __unused1;
-	target_ulong  target_st_mtime;
-	target_ulong  __unused2;
-	target_ulong  target_st_ctime;
-	target_ulong  __unused3;
-	target_ulong  __unused4;
-	target_ulong  __unused5;
+	abi_ulong  st_size;
+	abi_ulong  st_blksize;
+	abi_ulong  st_blocks;
+	abi_ulong  target_st_atime;
+	abi_ulong  __unused1;
+	abi_ulong  target_st_mtime;
+	abi_ulong  __unused2;
+	abi_ulong  target_st_ctime;
+	abi_ulong  __unused3;
+	abi_ulong  __unused4;
+	abi_ulong  __unused5;
 };
 
 struct target_stat64 {
@@ -1109,17 +1119,17 @@
 	unsigned long long st_rdev;
 	long long pad0;
 	long long st_size;
-	target_ulong	st_blksize;
-	target_ulong	pad1;
+	abi_ulong	st_blksize;
+	abi_ulong	pad1;
 	long long	st_blocks;	/* Number 512-byte blocks allocated. */
-	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_ulong    __unused4;
-        target_ulong    __unused5;
+	abi_ulong	target_st_atime;
+        abi_ulong    target_st_atime_nsec;
+	abi_ulong	target_st_mtime;
+        abi_ulong    target_st_mtime_nsec;
+	abi_ulong	target_st_ctime;
+        abi_ulong    target_st_ctime_nsec;
+        abi_ulong    __unused4;
+        abi_ulong    __unused5;
 };
 
 #elif defined(TARGET_M68K)
@@ -1127,24 +1137,24 @@
 struct target_stat {
 	unsigned short st_dev;
 	unsigned short __pad1;
-	target_ulong st_ino;
+	abi_ulong st_ino;
 	unsigned short st_mode;
 	unsigned short st_nlink;
 	unsigned short st_uid;
 	unsigned short st_gid;
 	unsigned short st_rdev;
 	unsigned short __pad2;
-	target_ulong  st_size;
-	target_ulong  st_blksize;
-	target_ulong  st_blocks;
-	target_ulong  target_st_atime;
-	target_ulong  __unused1;
-	target_ulong  target_st_mtime;
-	target_ulong  __unused2;
-	target_ulong  target_st_ctime;
-	target_ulong  __unused3;
-	target_ulong  __unused4;
-	target_ulong  __unused5;
+	abi_ulong  st_size;
+	abi_ulong  st_blksize;
+	abi_ulong  st_blocks;
+	abi_ulong  target_st_atime;
+	abi_ulong  __unused1;
+	abi_ulong  target_st_mtime;
+	abi_ulong  __unused2;
+	abi_ulong  target_st_ctime;
+	abi_ulong  __unused3;
+	abi_ulong  __unused4;
+	abi_ulong  __unused5;
 };
 
 /* This matches struct stat64 in glibc2.1, hence the absolutely
@@ -1155,62 +1165,172 @@
 	unsigned char	__pad1[2];
 
 #define TARGET_STAT64_HAS_BROKEN_ST_INO	1
-	target_ulong	__st_ino;
+	abi_ulong	__st_ino;
 
 	unsigned int	st_mode;
 	unsigned int	st_nlink;
 
-	target_ulong	st_uid;
-	target_ulong	st_gid;
+	abi_ulong	st_uid;
+	abi_ulong	st_gid;
 
 	unsigned long long	st_rdev;
 	unsigned char	__pad3[2];
 
 	long long	st_size;
-	target_ulong	st_blksize;
+	abi_ulong	st_blksize;
 
-	target_ulong	__pad4;		/* future possible st_blocks high bits */
-	target_ulong	st_blocks;	/* Number 512-byte blocks allocated. */
+	abi_ulong	__pad4;		/* future possible st_blocks high bits */
+	abi_ulong	st_blocks;	/* Number 512-byte blocks allocated. */
 
-	target_ulong	target_st_atime;
-	target_ulong	target_st_atime_nsec;
+	abi_ulong	target_st_atime;
+	abi_ulong	target_st_atime_nsec;
 
-	target_ulong	target_st_mtime;
-	target_ulong	target_st_mtime_nsec;
+	abi_ulong	target_st_mtime;
+	abi_ulong	target_st_mtime_nsec;
 
-	target_ulong	target_st_ctime;
-	target_ulong	target_st_ctime_nsec;
+	abi_ulong	target_st_ctime;
+	abi_ulong	target_st_ctime_nsec;
 
 	unsigned long long	st_ino;
 } __attribute__((packed));
 
+#elif defined(TARGET_MIPS64)
+
+/* The memory layout is the same as of struct stat64 of the 32-bit kernel.  */
+struct target_stat {
+	unsigned int		st_dev;
+	unsigned int		st_pad0[3]; /* Reserved for st_dev expansion */
+
+	abi_ulong		st_ino;
+
+	unsigned int		st_mode;
+	unsigned int		st_nlink;
+
+	int			st_uid;
+	int			st_gid;
+
+	unsigned int		st_rdev;
+	unsigned int		st_pad1[3]; /* Reserved for st_rdev expansion */
+
+	abi_ulong		st_size;
+
+	/*
+	 * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+	 * but we don't have it under Linux.
+	 */
+	unsigned int		target_st_atime;
+	unsigned int		target_st_atime_nsec;
+
+	unsigned int		target_st_mtime;
+	unsigned int		target_st_mtime_nsec;
+
+	unsigned int		target_st_ctime;
+	unsigned int		target_st_ctime_nsec;
+
+	unsigned int		st_blksize;
+	unsigned int		st_pad2;
+
+	abi_ulong		st_blocks;
+};
+
+#elif defined(TARGET_MIPSN32)
+
+struct target_stat {
+	unsigned	st_dev;
+	int		st_pad1[3];		/* Reserved for network id */
+	unsigned int	st_ino;
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+	int		st_uid;
+	int		st_gid;
+	unsigned 	st_rdev;
+	unsigned int	st_pad2[2];
+	unsigned int	st_size;
+	unsigned int	st_pad3;
+	/*
+	 * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+	 * but we don't have it under Linux.
+	 */
+	unsigned int		target_st_atime;
+	unsigned int		target_st_atime_nsec;
+	unsigned int		target_st_mtime;
+	unsigned int		target_st_mtime_nsec;
+	unsigned int		target_st_ctime;
+	unsigned int		target_st_ctime_nsec;
+	unsigned int		st_blksize;
+	unsigned int		st_blocks;
+	unsigned int		st_pad4[14];
+};
+
+/*
+ * This matches struct stat64 in glibc2.1, hence the absolutely insane
+ * amounts of padding around dev_t's.  The memory layout is the same as of
+ * struct stat of the 64-bit kernel.
+ */
+
+struct target_stat64 {
+	unsigned int	st_dev;
+	unsigned int	st_pad0[3];	/* Reserved for st_dev expansion  */
+
+	target_ulong	st_ino;
+
+        unsigned int	st_mode;
+        unsigned int	st_nlink;
+
+	int		st_uid;
+	int		st_gid;
+
+	unsigned int	st_rdev;
+	unsigned int	st_pad1[3];	/* Reserved for st_rdev expansion  */
+
+	int		st_size;
+
+	/*
+	 * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+	 * but we don't have it under Linux.
+	 */
+	int		target_st_atime;
+	unsigned int	target_st_atime_nsec;	/* Reserved for st_atime expansion  */
+
+	int		target_st_mtime;
+	unsigned int	target_st_mtime_nsec;	/* Reserved for st_mtime expansion  */
+
+	int		target_st_ctime;
+	unsigned int	target_st_ctime_nsec;	/* Reserved for st_ctime expansion  */
+
+	unsigned int	st_blksize;
+	unsigned int	st_pad2;
+
+	int		st_blocks;
+};
+
 #elif defined(TARGET_MIPS)
 
 struct target_stat {
 	unsigned	st_dev;
-	target_long	st_pad1[3];		/* Reserved for network id */
-	target_ulong	st_ino;
+	abi_long	st_pad1[3];		/* Reserved for network id */
+	abi_ulong	st_ino;
 	unsigned int	st_mode;
 	unsigned int	st_nlink;
 	int		st_uid;
 	int		st_gid;
 	unsigned 	st_rdev;
-	target_long	st_pad2[2];
-	target_long	st_size;
-	target_long	st_pad3;
+	abi_long	st_pad2[2];
+	abi_long	st_size;
+	abi_long	st_pad3;
 	/*
 	 * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
 	 * but we don't have it under Linux.
 	 */
-	target_long		target_st_atime;
-	target_long		target_st_atime_nsec;
-	target_long		target_st_mtime;
-	target_long		target_st_mtime_nsec;
-	target_long		target_st_ctime;
-	target_long		target_st_ctime_nsec;
-	target_long		st_blksize;
-	target_long		st_blocks;
-	target_long		st_pad4[14];
+	abi_long		target_st_atime;
+	abi_long		target_st_atime_nsec;
+	abi_long		target_st_mtime;
+	abi_long		target_st_mtime_nsec;
+	abi_long		target_st_ctime;
+	abi_long		target_st_ctime_nsec;
+	abi_long		st_blksize;
+	abi_long		st_blocks;
+	abi_long		st_pad4[14];
 };
 
 /*
@@ -1220,8 +1340,8 @@
  */
 
 struct target_stat64 {
-	target_ulong	st_dev;
-	target_ulong	st_pad0[3];	/* Reserved for st_dev expansion  */
+	abi_ulong	st_dev;
+	abi_ulong	st_pad0[3];	/* Reserved for st_dev expansion  */
 
 	uint64_t	st_ino;
 
@@ -1231,8 +1351,8 @@
 	int		st_uid;
 	int		st_gid;
 
-	target_ulong	st_rdev;
-	target_ulong	st_pad1[3];	/* Reserved for st_rdev expansion  */
+	abi_ulong	st_rdev;
+	abi_ulong	st_pad1[3];	/* Reserved for st_rdev expansion  */
 
 	int64_t 	st_size;
 
@@ -1240,17 +1360,17 @@
 	 * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
 	 * but we don't have it under Linux.
 	 */
-	target_long	target_st_atime;
-	target_ulong	target_st_atime_nsec;	/* Reserved for st_atime expansion  */
+	abi_long	target_st_atime;
+	abi_ulong	target_st_atime_nsec;	/* Reserved for st_atime expansion  */
 
-	target_long	target_st_mtime;
-	target_ulong	target_st_mtime_nsec;	/* Reserved for st_mtime expansion  */
+	abi_long	target_st_mtime;
+	abi_ulong	target_st_mtime_nsec;	/* Reserved for st_mtime expansion  */
 
-	target_long	target_st_ctime;
-	target_ulong	target_st_ctime_nsec;	/* Reserved for st_ctime expansion  */
+	abi_long	target_st_ctime;
+	abi_ulong	target_st_ctime_nsec;	/* Reserved for st_ctime expansion  */
 
-	target_ulong	st_blksize;
-	target_ulong	st_pad2;
+	abi_ulong	st_blksize;
+	abi_ulong	st_pad2;
 
 	int64_t  	st_blocks;
 };
@@ -1265,10 +1385,10 @@
        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;
+       abi_long     st_size;
+       abi_ulong    target_st_atime;
+       abi_ulong    target_st_mtime;
+       abi_ulong    target_st_ctime;
        unsigned int    st_blksize;
        unsigned int    st_blocks;
        unsigned int    st_flags;
@@ -1276,11 +1396,11 @@
 };
 
 struct target_stat64 {
-       target_ulong    st_dev;
-       target_ulong    st_ino;
-       target_ulong    st_rdev;
-       target_long     st_size;
-       target_ulong    st_blocks;
+       abi_ulong    st_dev;
+       abi_ulong    st_ino;
+       abi_ulong    st_rdev;
+       abi_long     st_size;
+       abi_ulong    st_blocks;
 
        unsigned int    st_mode;
        unsigned int    st_uid;
@@ -1289,36 +1409,36 @@
        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];
+       abi_ulong    target_st_atime;
+       abi_ulong    target_st_atime_nsec;
+       abi_ulong    target_st_mtime;
+       abi_ulong    target_st_mtime_nsec;
+       abi_ulong    target_st_ctime;
+       abi_ulong    target_st_ctime_nsec;
+       abi_long     __unused[3];
 };
 
 #elif defined(TARGET_SH4)
 
 struct target_stat {
-	target_ulong  st_dev;
-	target_ulong  st_ino;
+	abi_ulong  st_dev;
+	abi_ulong  st_ino;
 	unsigned short st_mode;
 	unsigned short st_nlink;
 	unsigned short st_uid;
 	unsigned short st_gid;
-	target_ulong  st_rdev;
-	target_ulong  st_size;
-	target_ulong  st_blksize;
-	target_ulong  st_blocks;
-	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_ulong  __unused4;
-	target_ulong  __unused5;
+	abi_ulong  st_rdev;
+	abi_ulong  st_size;
+	abi_ulong  st_blksize;
+	abi_ulong  st_blocks;
+	abi_ulong  target_st_atime;
+	abi_ulong  target_st_atime_nsec;
+	abi_ulong  target_st_mtime;
+	abi_ulong  target_st_mtime_nsec;
+	abi_ulong  target_st_ctime;
+	abi_ulong  target_st_ctime_nsec;
+	abi_ulong  __unused4;
+	abi_ulong  __unused5;
 };
 
 /* This matches struct stat64 in glibc2.1, hence the absolutely
@@ -1329,30 +1449,30 @@
 	unsigned char	__pad0[4];
 
 #define TARGET_STAT64_HAS_BROKEN_ST_INO	1
-	target_ulong	__st_ino;
+	abi_ulong	__st_ino;
 
 	unsigned int	st_mode;
 	unsigned int	st_nlink;
 
-	target_ulong	st_uid;
-	target_ulong	st_gid;
+	abi_ulong	st_uid;
+	abi_ulong	st_gid;
 
 	unsigned long long	st_rdev;
 	unsigned char	__pad3[4];
 
 	long long	st_size;
-	target_ulong	st_blksize;
+	abi_ulong	st_blksize;
 
 	unsigned long long	st_blocks;	/* Number 512-byte blocks allocated. */
 
-	target_ulong	target_st_atime;
-	target_ulong	target_st_atime_nsec;
+	abi_ulong	target_st_atime;
+	abi_ulong	target_st_atime_nsec;
 
-	target_ulong	target_st_mtime;
-	target_ulong	target_st_mtime_nsec;
+	abi_ulong	target_st_mtime;
+	abi_ulong	target_st_mtime_nsec;
 
-	target_ulong	target_st_ctime;
-	target_ulong	target_st_ctime_nsec;
+	abi_ulong	target_st_ctime;
+	abi_ulong	target_st_ctime_nsec;
 
 	unsigned long long	st_ino;
 };
@@ -1366,22 +1486,40 @@
 } target_fsid_t;
 
 #ifdef TARGET_MIPS
+#ifdef TARGET_MIPSN32
 struct target_statfs {
-	target_long		f_type;
-	target_long		f_bsize;
-	target_long		f_frsize;	/* Fragment size - unsupported */
-	target_long		f_blocks;
-	target_long		f_bfree;
-	target_long		f_files;
-	target_long		f_ffree;
-	target_long		f_bavail;
+	int32_t			f_type;
+	int32_t			f_bsize;
+	int32_t			f_frsize;	/* Fragment size - unsupported */
+	int32_t			f_blocks;
+	int32_t			f_bfree;
+	int32_t			f_files;
+	int32_t			f_ffree;
+	int32_t			f_bavail;
 
 	/* Linux specials */
 	target_fsid_t		f_fsid;
-	target_long		f_namelen;
-	target_long		f_spare[6];
+	int32_t			f_namelen;
+	int32_t			f_spare[6];
 };
+#else
+struct target_statfs {
+	abi_long		f_type;
+	abi_long		f_bsize;
+	abi_long		f_frsize;	/* Fragment size - unsupported */
+	abi_long		f_blocks;
+	abi_long		f_bfree;
+	abi_long		f_files;
+	abi_long		f_ffree;
+	abi_long		f_bavail;
 
+	/* Linux specials */
+	target_fsid_t		f_fsid;
+	abi_long		f_namelen;
+	abi_long		f_spare[6];
+};
+#endif
+
 struct target_statfs64 {
 	uint32_t	f_type;
 	uint32_t	f_bsize;
@@ -1550,8 +1688,8 @@
 struct target_flock {
 	short l_type;
 	short l_whence;
-	target_ulong l_start;
-	target_ulong l_len;
+	abi_ulong l_start;
+	abi_ulong l_len;
 	int l_pid;
 };
 
@@ -1718,20 +1856,20 @@
 #define TARGET_VFAT_IOCTL_READDIR_SHORT   TARGET_IORU('r', 2)
 
 struct target_sysinfo {
-    target_long uptime;             /* Seconds since boot */
-    target_ulong loads[3];          /* 1, 5, and 15 minute load averages */
-    target_ulong totalram;          /* Total usable main memory size */
-    target_ulong freeram;           /* Available memory size */
-    target_ulong sharedram;         /* Amount of shared memory */
-    target_ulong bufferram;         /* Memory used by buffers */
-    target_ulong totalswap;         /* Total swap space size */
-    target_ulong freeswap;          /* swap space still available */
+    abi_long uptime;                /* Seconds since boot */
+    abi_ulong loads[3];             /* 1, 5, and 15 minute load averages */
+    abi_ulong totalram;             /* Total usable main memory size */
+    abi_ulong freeram;              /* Available memory size */
+    abi_ulong sharedram;            /* Amount of shared memory */
+    abi_ulong bufferram;            /* Memory used by buffers */
+    abi_ulong totalswap;            /* Total swap space size */
+    abi_ulong freeswap;             /* swap space still available */
     unsigned short procs;           /* Number of current processes */
     unsigned short pad;             /* explicit padding for m68k */
-    target_ulong totalhigh;         /* Total high memory size */
-    target_ulong freehigh;          /* Available high memory size */
+    abi_ulong totalhigh;            /* Total high memory size */
+    abi_ulong freehigh;             /* Available high memory size */
     unsigned int mem_unit;          /* Memory unit size in bytes */
-    char _f[20-2*sizeof(target_long)-sizeof(int)]; /* Padding: libc5 uses this.. */
+    char _f[20-2*sizeof(abi_long)-sizeof(int)]; /* Padding: libc5 uses this.. */
 };
 
 #include "socket.h"

Modified: trunk/src/host/qemu-neo1973/linux-user/vm86.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/vm86.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/vm86.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -381,7 +381,7 @@
     }
 }
 
-int do_vm86(CPUX86State *env, long subfunction, target_ulong vm86_addr)
+int do_vm86(CPUX86State *env, long subfunction, abi_ulong vm86_addr)
 {
     TaskState *ts = env->opaque;
     struct target_vm86plus_struct * target_v86;

Modified: trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -2,30 +2,30 @@
 #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;
+	abi_ulong r15;
+	abi_ulong r14;
+	abi_ulong r13;
+	abi_ulong r12;
+	abi_ulong rbp;
+	abi_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;
+ 	abi_ulong r11;
+	abi_ulong r10;
+	abi_ulong r9;
+	abi_ulong r8;
+	abi_ulong rax;
+	abi_ulong rcx;
+	abi_ulong rdx;
+	abi_ulong rsi;
+	abi_ulong rdi;
+	abi_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;
+	abi_ulong rip;
+	abi_ulong cs;
+	abi_ulong eflags;
+	abi_ulong rsp;
+	abi_ulong ss;
 /* top of stack page */
 };
 
@@ -41,7 +41,7 @@
 #if 0 // Redefine this
 struct target_modify_ldt_ldt_s {
 	unsigned int  entry_number;
-	target_ulong  base_addr;
+        abi_ulong     base_addr;
 	unsigned int  limit;
 	unsigned int  seg_32bit:1;
 	unsigned int  contents:2;
@@ -54,7 +54,7 @@
 #else
 struct target_modify_ldt_ldt_s {
 	unsigned int  entry_number;
-	target_ulong  base_addr;
+        abi_ulong     base_addr;
 	unsigned int  limit;
         unsigned int flags;
 };
@@ -71,8 +71,8 @@
 	unsigned short		__pad1;
 	unsigned short		seq;
 	unsigned short		__pad2;
-	target_ulong		__unused1;
-	target_ulong		__unused2;
+	abi_ulong		__unused1;
+	abi_ulong		__unused2;
 };
 
 struct target_msqid64_ds {
@@ -80,13 +80,13 @@
 	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 */
+	abi_ulong  msg_cbytes;	/* current number of bytes on queue */
+	abi_ulong  msg_qnum;	/* number of messages in queue */
+	abi_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;
+	abi_ulong  __unused4;
+	abi_ulong  __unused5;
 };
 
 #define UNAME_MACHINE "x86_64"

Modified: 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-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall_nr.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -278,3 +278,9 @@
 #define TARGET_NR_sync_file_range	277
 #define TARGET_NR_vmsplice		278
 #define TARGET_NR_move_pages		279
+#define TARGET_NR_utimensat		280
+#define TARGET_NR_epoll_pwait	281
+#define TARGET_NR_signalfd		282
+#define TARGET_NR_timerfd		283
+#define TARGET_NR_eventfd		284
+#define TARGET_NR_fallocate		285

Added: trunk/src/host/qemu-neo1973/linux-user/x86_64/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/x86_64/target_signal.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/linux-user/x86_64/target_signal.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#ifndef TARGET_SIGNAL_H
+#define TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+	abi_ulong ss_sp;
+	abi_long ss_flags;
+	abi_ulong ss_size;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK	1
+#define TARGET_SS_DISABLE	2
+
+#define TARGET_MINSIGSTKSZ	2048
+#define TARGET_SIGSTKSZ		8192
+
+static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+{
+    return state->regs[R_ESP];
+}
+
+#endif /* TARGET_SIGNAL_H */

Modified: trunk/src/host/qemu-neo1973/loader.c
===================================================================
--- trunk/src/host/qemu-neo1973/loader.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/loader.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -173,6 +173,7 @@
 
 #define SZ		32
 #define elf_word        uint32_t
+#define elf_sword        int32_t
 #define bswapSZs	bswap32s
 #include "elf_ops.h"
 
@@ -182,6 +183,7 @@
 #undef elf_sym
 #undef elf_note
 #undef elf_word
+#undef elf_sword
 #undef bswapSZs
 #undef SZ
 #define elfhdr		elf64_hdr
@@ -190,6 +192,7 @@
 #define elf_shdr	elf64_shdr
 #define elf_sym		elf64_sym
 #define elf_word        uint64_t
+#define elf_sword        int64_t
 #define bswapSZs	bswap64s
 #define SZ		64
 #include "elf_ops.h"

Modified: trunk/src/host/qemu-neo1973/monitor.c
===================================================================
--- trunk/src/host/qemu-neo1973/monitor.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/monitor.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -509,7 +509,7 @@
 }
 
 static void memory_dump(int count, int format, int wsize,
-                        target_ulong addr, int is_physical)
+                        target_phys_addr_t addr, int is_physical)
 {
     CPUState *env;
     int nb_per_line, l, line_size, i, max_digits, len;
@@ -572,7 +572,10 @@
     }
 
     while (len > 0) {
-        term_printf(TARGET_FMT_lx ":", addr);
+        if (is_physical)
+            term_printf(TARGET_FMT_plx ":", addr);
+        else
+            term_printf(TARGET_FMT_lx ":", (target_ulong)addr);
         l = len;
         if (l > line_size)
             l = line_size;
@@ -640,18 +643,24 @@
     memory_dump(count, format, size, addr, 0);
 }
 
+#if TARGET_PHYS_ADDR_BITS > 32
+#define GET_TPHYSADDR(h, l) (((uint64_t)(h) << 32) | (l))
+#else
+#define GET_TPHYSADDR(h, l) (l)
+#endif
+
 static void do_physical_memory_dump(int count, int format, int size,
                                     uint32_t addrh, uint32_t addrl)
 
 {
-    target_long addr = GET_TLONG(addrh, addrl);
+    target_phys_addr_t addr = GET_TPHYSADDR(addrh, addrl);
     memory_dump(count, format, size, addr, 1);
 }
 
 static void do_print(int count, int format, int size, unsigned int valh, unsigned int vall)
 {
-    target_long val = GET_TLONG(valh, vall);
-#if TARGET_LONG_BITS == 32
+    target_phys_addr_t val = GET_TPHYSADDR(valh, vall);
+#if TARGET_PHYS_ADDR_BITS == 32
     switch(format) {
     case 'o':
         term_printf("%#o", val);
@@ -1386,6 +1395,10 @@
     { "cpustats", "", do_info_cpu_stats,
       "", "show CPU statistics", },
 #endif
+#if defined(CONFIG_SLIRP)
+    { "slirp", "", do_info_slirp,
+      "", "show SLIRP statistics", },
+#endif
     { NULL, NULL, },
 };
 
@@ -1442,7 +1455,7 @@
     CPUState *env = mon_get_cpu();
     if (!env)
         return 0;
-    return do_load_msr(env);
+    return env->msr;
 }
 
 static target_long monitor_get_xer (struct MonitorDef *md, int val)
@@ -1788,11 +1801,11 @@
     }
 }
 
-static target_long expr_sum(void);
+static int64_t expr_sum(void);
 
-static target_long expr_unary(void)
+static int64_t expr_unary(void)
 {
-    target_long n;
+    int64_t n;
     char *p;
     int ret;
 
@@ -1830,6 +1843,7 @@
     case '$':
         {
             char buf[128], *q;
+            target_long reg;
 
             pch++;
             q = buf;
@@ -1844,11 +1858,12 @@
             while (isspace(*pch))
                 pch++;
             *q = 0;
-            ret = get_monitor_def(&n, buf);
+            ret = get_monitor_def(&reg, buf);
             if (ret == -1)
                 expr_error("unknown register");
             else if (ret == -2)
                 expr_error("no cpu defined");
+            n = reg;
         }
         break;
     case '\0':
@@ -1856,7 +1871,7 @@
         n = 0;
         break;
     default:
-#if TARGET_LONG_BITS == 64
+#if TARGET_PHYS_ADDR_BITS > 32
         n = strtoull(pch, &p, 0);
 #else
         n = strtoul(pch, &p, 0);
@@ -1873,9 +1888,9 @@
 }
 
 
-static target_long expr_prod(void)
+static int64_t expr_prod(void)
 {
-    target_long val, val2;
+    int64_t val, val2;
     int op;
 
     val = expr_unary();
@@ -1904,9 +1919,9 @@
     return val;
 }
 
-static target_long expr_logic(void)
+static int64_t expr_logic(void)
 {
-    target_long val, val2;
+    int64_t val, val2;
     int op;
 
     val = expr_prod();
@@ -1932,9 +1947,9 @@
     return val;
 }
 
-static target_long expr_sum(void)
+static int64_t expr_sum(void)
 {
-    target_long val, val2;
+    int64_t val, val2;
     int op;
 
     val = expr_logic();
@@ -1952,7 +1967,7 @@
     return val;
 }
 
-static int get_expr(target_long *pval, const char **pp)
+static int get_expr(int64_t *pval, const char **pp)
 {
     pch = *pp;
     if (setjmp(expr_env)) {
@@ -2215,7 +2230,8 @@
         case 'i':
         case 'l':
             {
-                target_long val;
+                int64_t val;
+
                 while (isspace(*p))
                     p++;
                 if (*typestr == '?' || *typestr == '.') {
@@ -2255,7 +2271,7 @@
                 } else {
                     if ((nb_args + 1) >= MAX_ARGS)
                         goto error_args;
-#if TARGET_LONG_BITS == 64
+#if TARGET_PHYS_ADDR_BITS > 32
                     args[nb_args++] = (void *)(long)((val >> 32) & 0xffffffff);
 #else
                     args[nb_args++] = (void *)0;

Modified: trunk/src/host/qemu-neo1973/pc-bios/README
===================================================================
--- trunk/src/host/qemu-neo1973/pc-bios/README	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/pc-bios/README	2007-10-29 21:14:04 UTC (rev 3303)
@@ -14,7 +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 and Sparc64 images are built from SVN revision 169.
+  The included Sparc32 image is built from SVN revision 171 and
+  Sparc64 image from revision 169.
 
 - The PXE roms come from Rom-o-Matic etherboot 5.4.2.
   pcnet32:pcnet32 -- [0x1022,0x2000]

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

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

Modified: trunk/src/host/qemu-neo1973/qemu-binfmt-conf.sh
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-binfmt-conf.sh	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/qemu-binfmt-conf.sh	2007-10-29 21:14:04 UTC (rev 3303)
@@ -46,10 +46,14 @@
 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
+    echo   ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04:\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
+    echo   ':mipsn32: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-mipsn32:' > /proc/sys/fs/binfmt_misc/register
+    echo   ':mipsn32el: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-mipsn32el:' > /proc/sys/fs/binfmt_misc/register
+    echo   ':mips64:M::\x7fELF\x02\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-mips64:' > /proc/sys/fs/binfmt_misc/register
+    echo   ':mips64el:M::\x7fELF\x02\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-mips64el:' > /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-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/qemu-doc.texi	2007-10-29 21:14:04 UTC (rev 3303)
@@ -242,7 +242,8 @@
 
 @item -smp n
 Simulate an SMP system with @var{n} CPUs. On the PC target, up to 255
-CPUs are supported.
+CPUs are supported. On Sparc32 target, Linux limits the number of usable CPUs
+to 4.
 
 @item -audio-help
 
@@ -1942,6 +1943,8 @@
 
 Use the executable @file{qemu-system-sparc} to simulate a SparcStation 5
 or SparcStation 10 (sun4m architecture). The emulation is somewhat complete.
+SMP up to 16 CPUs is supported, but Linux limits the number of usable CPUs
+to 4.
 
 QEMU emulates the following sun4m peripherals:
 
@@ -1965,7 +1968,8 @@
 CS4231 sound device (only on SS-5, not working yet)
 @end itemize
 
-The number of peripherals is fixed in the architecture.
+The number of peripherals is fixed in the architecture.  Maximum memory size
+depends on the machine type, for SS-5 it is 256MB and for SS-10 2047MB.
 
 Since version 0.8.2, QEMU uses OpenBIOS
 @url{http://www.openbios.org/}. OpenBIOS is a free (GPL v2) portable
@@ -2036,6 +2040,8 @@
 The MIPS Malta prototype board "malta"
 @item
 An ACER Pica "pica61"
+ at item
+MIPS emulator pseudo board "mipssim"
 @end itemize
 
 The generic emulation is supported by Debian 'Etch' and is able to
@@ -2044,7 +2050,7 @@
 
 @itemize @minus
 @item
-MIPS 24Kf CPU
+A range of MIPS CPUs, default is the 24Kf
 @item
 PC style serial port
 @item
@@ -2083,6 +2089,19 @@
 IDE controller
 @end itemize
 
+The mipssim pseudo board emulation provides an environment similiar
+to what the proprietary MIPS emulator uses for running Linux.
+It supports:
+
+ at itemize @minus
+ at item
+A range of MIPS CPUs, default is the 24Kf
+ at item
+PC style serial port
+ at item
+MIPSnet network emulation
+ at end itemize
+
 @node ARM System emulator
 @section ARM System emulator
 
@@ -2367,6 +2386,12 @@
 
 The binary format is detected automatically.
 
+ at command{qemu-sparc32plus} can execute Sparc32 and SPARC32PLUS binaries
+(Sparc64 CPU, 32 bit ABI).
+
+ at command{qemu-sparc64} can execute some Sparc64 (Sparc64 CPU, 64 bit ABI) and
+SPARC32PLUS binaries (Sparc64 CPU, 32 bit ABI).
+
 @node Mac OS X/Darwin User space emulator
 @section Mac OS X/Darwin User space emulator
 

Modified: trunk/src/host/qemu-neo1973/qemu-img.c
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-img.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/qemu-img.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -269,9 +269,9 @@
         case 'e':
             flags |= BLOCK_FLAG_ENCRYPT;
             break;
-		case '6':
+        case '6':
             flags |= BLOCK_FLAG_COMPAT6;
-			break;
+            break;
         }
     }
     if (optind >= argc)
@@ -471,7 +471,7 @@
         error("Compression not supported for this file format");
     if (flags & BLOCK_FLAG_ENCRYPT && drv != &bdrv_qcow && drv != &bdrv_qcow2)
         error("Encryption not supported for this file format");
-    if (flags & BLOCK_FLAG_COMPRESS && drv != &bdrv_vmdk)
+    if (flags & BLOCK_FLAG_COMPAT6 && drv != &bdrv_vmdk)
         error("Alternative compatibility level not supported for this file format");
     if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
         error("Compression and encryption not supported at the same time");

Modified: trunk/src/host/qemu-neo1973/qemu-tech.texi
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-tech.texi	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/qemu-tech.texi	2007-10-29 21:14:04 UTC (rev 3303)
@@ -199,9 +199,10 @@
 
 @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 most VIS instructions.
+and VIS instructions, FPU and I/D MMU. Alignment is fully enforced.
 
- at item Can run most 32-bit SPARC Linux binaries and some handcrafted 64-bit SPARC Linux binaries.
+ at item Can run most 32-bit SPARC Linux binaries, SPARC32PLUS Linux binaries and
+some 64-bit SPARC Linux binaries.
 
 @end itemize
 
@@ -212,11 +213,8 @@
 @item IPC syscalls are missing.
 
 @item 128-bit floating point operations are not supported, though none of the
-real CPUs implement them either. FCMPE[SD] are not correctly
-implemented.  Floating point exception support is untested.
+real CPUs implement them either.  Floating point exception support is untested.
 
- at item Alignment is not enforced at all.
-
 @item Atomic instructions are not correctly implemented.
 
 @item Sparc64 emulators are not usable for anything yet.

Modified: trunk/src/host/qemu-neo1973/readline.c
===================================================================
--- trunk/src/host/qemu-neo1973/readline.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/readline.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -301,7 +301,7 @@
 
 static void term_completion(void)
 {
-    int len, i, j, max_width, nb_cols;
+    int len, i, j, max_width, nb_cols, max_prefix;
     char *cmdline;
 
     nb_completions = 0;
@@ -328,11 +328,26 @@
     } else {
         term_printf("\n");
         max_width = 0;
+        max_prefix = 0;	
         for(i = 0; i < nb_completions; i++) {
             len = strlen(completions[i]);
+            if (i==0) {
+                max_prefix = len;
+            } else {
+                if (len < max_prefix)
+                    max_prefix = len;
+                for(j=0; j<max_prefix; j++) {
+                    if (completions[i][j] != completions[0][j])
+                        max_prefix = j;
+                }
+            }
             if (len > max_width)
                 max_width = len;
         }
+        if (max_prefix > 0) 
+            for(i = completion_index; i < max_prefix; i++) {
+                term_insert_char(completions[0][i]);
+            }
         max_width += 2;
         if (max_width < 10)
             max_width = 10;

Modified: trunk/src/host/qemu-neo1973/slirp/bootp.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/bootp.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/bootp.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -149,7 +149,7 @@
 
     if ((m = m_get()) == NULL)
         return;
-    m->m_data += if_maxlinkhdr;
+    m->m_data += IF_MAXLINKHDR;
     rbp = (struct bootp_t *)m->m_data;
     m->m_data += sizeof(struct udpiphdr);
     memset(rbp, 0, sizeof(struct bootp_t));

Modified: trunk/src/host/qemu-neo1973/slirp/debug.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/debug.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/debug.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -20,6 +20,7 @@
 
 /* Carry over one item from main.c so that the tty's restored.
  * Only done when the tty being used is /dev/tty --RedWolf */
+#ifndef CONFIG_QEMU
 extern struct termios slirp_tty_settings;
 extern int slirp_tty_restore;
 
@@ -70,7 +71,9 @@
 	}
 }
 #endif
+#endif
 
+#ifdef LOG_ENABLED
 #if 0
 /*
  * Statistic routines
@@ -80,7 +83,7 @@
  * the link as well.
  */
 
-void
+static void
 ttystats(ttyp)
 	struct ttys *ttyp;
 {
@@ -89,9 +92,9 @@
 
 	lprint(" \r\n");
 
-	if (if_comp & IF_COMPRESS)
+	if (IF_COMP & IF_COMPRESS)
 	   strcpy(buff, "on");
-	else if (if_comp & IF_NOCOMPRESS)
+	else if (IF_COMP & IF_NOCOMPRESS)
 	   strcpy(buff, "off");
 	else
 	   strcpy(buff, "off (for now)");
@@ -119,8 +122,8 @@
 	lprint("  %6d bad input packets\r\n", is->in_mbad);
 }
 
-void
-allttystats()
+static void
+allttystats(void)
 {
 	struct ttys *ttyp;
 
@@ -129,8 +132,8 @@
 }
 #endif
 
-void
-ipstats()
+static void
+ipstats(void)
 {
 	lprint(" \r\n");
 
@@ -153,9 +156,9 @@
 	lprint("  %6d total packets delivered\r\n", ipstat.ips_delivered);
 }
 
-#if 0
-void
-vjstats()
+#ifndef CONFIG_QEMU
+static void
+vjstats(void)
 {
 	lprint(" \r\n");
 
@@ -172,8 +175,8 @@
 }
 #endif
 
-void
-tcpstats()
+static void
+tcpstats(void)
 {
 	lprint(" \r\n");
 
@@ -240,8 +243,8 @@
 
 }
 
-void
-udpstats()
+static void
+udpstats(void)
 {
         lprint(" \r\n");
 
@@ -254,8 +257,8 @@
 	lprint("  %6d datagrams sent\r\n", udpstat.udps_opackets);
 }
 
-void
-icmpstats()
+static void
+icmpstats(void)
 {
 	lprint(" \r\n");
 	lprint("ICMP stats:\r\n");
@@ -267,8 +270,8 @@
 	lprint("  %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect);
 }
 
-void
-mbufstats()
+static void
+mbufstats(void)
 {
 	struct mbuf *m;
 	int i;
@@ -291,8 +294,8 @@
         lprint("  %6d mbufs queued as packets\r\n\r\n", if_queued);
 }
 
-void
-sockstats()
+static void
+sockstats(void)
 {
 	char buff[256];
 	int n;
@@ -331,8 +334,9 @@
 				so->so_rcv.sb_cc, so->so_snd.sb_cc);
 	}
 }
+#endif
 
-#if 0
+#ifndef CONFIG_QEMU
 void
 slirp_exit(exit_status)
 	int exit_status;
@@ -374,3 +378,18 @@
 	exit(exit_status);
 }
 #endif
+
+void
+slirp_stats(void)
+{
+#ifdef LOG_ENABLED
+    ipstats();
+    tcpstats();
+    udpstats();
+    icmpstats();
+    mbufstats();
+    sockstats();
+#else
+    lprint("SLIRP statistics code not compiled.\n");
+#endif
+}

Modified: trunk/src/host/qemu-neo1973/slirp/debug.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/debug.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/debug.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -37,14 +37,4 @@
 #endif
 
 void debug_init _P((char *, int));
-//void ttystats _P((struct ttys *));
-void allttystats _P((void));
-void ipstats _P((void));
-void vjstats _P((void));
-void tcpstats _P((void));
-void udpstats _P((void));
-void icmpstats _P((void));
-void mbufstats _P((void));
-void sockstats _P((void));
-void slirp_exit _P((int));
 

Modified: trunk/src/host/qemu-neo1973/slirp/icmp_var.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/icmp_var.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/icmp_var.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -64,6 +64,8 @@
 	{ "stats", CTLTYPE_STRUCT }, \
 }
 
+#ifdef LOG_ENABLED
 extern struct icmpstat icmpstat;
+#endif
 
 #endif

Modified: trunk/src/host/qemu-neo1973/slirp/if.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/if.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/if.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -7,12 +7,7 @@
 
 #include <slirp.h>
 
-int if_mtu, if_mru;
-int if_comp;
-int if_maxlinkhdr;
 int     if_queued = 0;                  /* Number of packets queued so far */
-int     if_thresh = 10;                 /* Number of packets queued before we start sending
-					 * (to prevent allocing too many mbufs) */
 
 struct  mbuf if_fastq;                  /* fast queue (for interactive data) */
 struct  mbuf if_batchq;                 /* queue for non-interactive data */
@@ -41,23 +36,6 @@
 void
 if_init()
 {
-#if 0
-	/*
-	 * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP,
-	 * and 8 bytes for PPP, but need to have it on an 8byte boundary
-	 */
-#ifdef USE_PPP
-	if_maxlinkhdr = 48;
-#else
-	if_maxlinkhdr = 40;
-#endif
-#else
-        /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
-        if_maxlinkhdr = 2 + 14 + 40;
-#endif
-	if_mtu = 1500;
-	if_mru = 1500;
-	if_comp = IF_AUTOCOMP;
 	if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
 	if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
         //	sl_compress_init(&comp_s);

Modified: trunk/src/host/qemu-neo1973/slirp/if.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/if.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/if.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -13,15 +13,26 @@
 #define IF_AUTOCOMP	0x04	/* Autodetect (default) */
 #define IF_NOCIDCOMP	0x08	/* CID compression */
 
-/* Needed for FreeBSD */
-#undef if_mtu
-extern int	if_mtu;
-extern int	if_mru;	/* MTU and MRU */
-extern int	if_comp;	/* Flags for compression */
-extern int	if_maxlinkhdr;
+#define IF_MTU 1500
+#define IF_MRU 1500
+#define	IF_COMP IF_AUTOCOMP	/* Flags for compression */
+
+#if 0
+/*
+ * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP,
+ * and 8 bytes for PPP, but need to have it on an 8byte boundary
+ */
+#ifdef USE_PPP
+#define IF_MAXLINKHDR 48
+#else
+#define IF_MAXLINKHDR 40
+#endif
+#else
+        /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
+#define IF_MAXLINKHDR (2 + 14 + 40)
+#endif
+
 extern int	if_queued;	/* Number of packets queued so far */
-extern int	if_thresh;	/* Number of packets queued before we start sending
-				 * (to prevent allocing too many mbufs) */
 
 extern	struct mbuf if_fastq;                  /* fast queue (for interactive data) */
 extern	struct mbuf if_batchq;                 /* queue for non-interactive data */
@@ -29,6 +40,7 @@
 
 #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
 
+#ifdef LOG_ENABLED
 /* Interface statistics */
 struct slirp_ifstats {
 	u_int out_pkts;		/* Output packets */
@@ -46,5 +58,6 @@
 
 	u_int in_mbad;		/* Bad incoming packets */
 };
+#endif
 
 #endif

Modified: trunk/src/host/qemu-neo1973/slirp/ip.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/ip.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/ip.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -272,6 +272,7 @@
 	int8_t	ipopt_list[MAX_IPOPTLEN];	/* options proper */
 };
 
+#ifdef LOG_ENABLED
 /*
  * Structure attached to inpcb.ip_moptions and
  * passed to ip_output when IP multicast options are in use.
@@ -306,8 +307,9 @@
 };
 
 extern struct	ipstat	ipstat;
+#endif
+
 extern struct	ipq	ipq;			/* ip reass. queue */
 extern u_int16_t	ip_id;				/* ip packet ctr, for ids */
-extern int	ip_defttl;			/* default IP ttl */
 
 #endif

Modified: trunk/src/host/qemu-neo1973/slirp/ip_icmp.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/ip_icmp.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/ip_icmp.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -37,14 +37,16 @@
 #include "slirp.h"
 #include "ip_icmp.h"
 
+#ifdef LOG_ENABLED
 struct icmpstat icmpstat;
+#endif
 
 /* The message sent when emulating PING */
-/* Be nice and tell them it's just a psuedo-ping packet */
-char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
+/* Be nice and tell them it's just a pseudo-ping packet */
+const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
 
 /* list of actions for icmp_error() on RX of an icmp message */
-static int icmp_flush[19] = {
+static const int icmp_flush[19] = {
 /*  ECHO REPLY (0)  */   0,
 		         1,
 		         1,
@@ -83,14 +85,14 @@
   DEBUG_ARG("m = %lx", (long )m);
   DEBUG_ARG("m_len = %d", m->m_len);
 
-  icmpstat.icps_received++;
+  STAT(icmpstat.icps_received++);
 
   /*
    * Locate icmp structure in mbuf, and check
    * that its not corrupted and of at least minimum length.
    */
   if (icmplen < ICMP_MINLEN) {          /* min 8 bytes payload */
-    icmpstat.icps_tooshort++;
+    STAT(icmpstat.icps_tooshort++);
   freeit:
     m_freem(m);
     goto end_error;
@@ -100,7 +102,7 @@
   m->m_data += hlen;
   icp = mtod(m, struct icmp *);
   if (cksum(m, icmplen)) {
-    icmpstat.icps_checksum++;
+    STAT(icmpstat.icps_checksum++);
     goto freeit;
   }
   m->m_len += hlen;
@@ -170,12 +172,12 @@
   case ICMP_TSTAMP:
   case ICMP_MASKREQ:
   case ICMP_REDIRECT:
-    icmpstat.icps_notsupp++;
+    STAT(icmpstat.icps_notsupp++);
     m_freem(m);
     break;
 
   default:
-    icmpstat.icps_badtype++;
+    STAT(icmpstat.icps_badtype++);
     m_freem(m);
   } /* swith */
 
@@ -314,7 +316,7 @@
 
   (void ) ip_output((struct socket *)NULL, m);
 
-  icmpstat.icps_reflect++;
+  STAT(icmpstat.icps_reflect++);
 
 end_error:
   return;
@@ -371,5 +373,5 @@
 
   (void ) ip_output((struct socket *)NULL, m);
 
-  icmpstat.icps_reflect++;
+  STAT(icmpstat.icps_reflect++);
 }

Modified: trunk/src/host/qemu-neo1973/slirp/ip_input.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/ip_input.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/ip_input.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -45,10 +45,19 @@
 #include <slirp.h>
 #include "ip_icmp.h"
 
-int ip_defttl;
+#ifdef LOG_ENABLED
 struct ipstat ipstat;
+#endif
+
 struct ipq ipq;
 
+static struct ip *ip_reass(register struct ipasfrag *ip,
+                           register struct ipq *fp);
+static void ip_freef(struct ipq *fp);
+static void ip_enq(register struct ipasfrag *p,
+                   register struct ipasfrag *prev);
+static void ip_deq(register struct ipasfrag *p);
+
 /*
  * IP initialization: fill in IP protocol switch table.
  * All protocols not implemented in kernel go to raw IP protocol handler.
@@ -60,7 +69,6 @@
 	ip_id = tt.tv_sec & 0xffff;
 	udp_init();
 	tcp_init();
-	ip_defttl = IPDEFTTL;
 }
 
 /*
@@ -78,23 +86,23 @@
 	DEBUG_ARG("m = %lx", (long)m);
 	DEBUG_ARG("m_len = %d", m->m_len);
 
-	ipstat.ips_total++;
+	STAT(ipstat.ips_total++);
 
 	if (m->m_len < sizeof (struct ip)) {
-		ipstat.ips_toosmall++;
+		STAT(ipstat.ips_toosmall++);
 		return;
 	}
 
 	ip = mtod(m, struct ip *);
 
 	if (ip->ip_v != IPVERSION) {
-		ipstat.ips_badvers++;
+		STAT(ipstat.ips_badvers++);
 		goto bad;
 	}
 
 	hlen = ip->ip_hl << 2;
 	if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */
-	  ipstat.ips_badhlen++;                     /* or packet too short */
+	  STAT(ipstat.ips_badhlen++);                     /* or packet too short */
 	  goto bad;
 	}
 
@@ -103,7 +111,7 @@
 	 * if (ip->ip_sum) {
 	 */
 	if(cksum(m,hlen)) {
-	  ipstat.ips_badsum++;
+	  STAT(ipstat.ips_badsum++);
 	  goto bad;
 	}
 
@@ -112,7 +120,7 @@
 	 */
 	NTOHS(ip->ip_len);
 	if (ip->ip_len < hlen) {
-		ipstat.ips_badlen++;
+		STAT(ipstat.ips_badlen++);
 		goto bad;
 	}
 	NTOHS(ip->ip_id);
@@ -125,7 +133,7 @@
 	 * Drop packet if shorter than we expect.
 	 */
 	if (m->m_len < ip->ip_len) {
-		ipstat.ips_tooshort++;
+		STAT(ipstat.ips_tooshort++);
 		goto bad;
 	}
 	/* Should drop packet if mbuf too long? hmmm... */
@@ -192,11 +200,11 @@
 		 * attempt reassembly; if it succeeds, proceed.
 		 */
 		if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
-			ipstat.ips_fragments++;
+			STAT(ipstat.ips_fragments++);
 			ip = ip_reass((struct ipasfrag *)ip, fp);
 			if (ip == 0)
 				return;
-			ipstat.ips_reassembled++;
+			STAT(ipstat.ips_reassembled++);
 			m = dtom(ip);
 		} else
 			if (fp)
@@ -208,7 +216,7 @@
 	/*
 	 * Switch out to protocol's input routine.
 	 */
-	ipstat.ips_delivered++;
+	STAT(ipstat.ips_delivered++);
 	switch (ip->ip_p) {
 	 case IPPROTO_TCP:
 		tcp_input(m, hlen, (struct socket *)NULL);
@@ -220,7 +228,7 @@
 		icmp_input(m, hlen);
 		break;
 	 default:
-		ipstat.ips_noproto++;
+		STAT(ipstat.ips_noproto++);
 		m_free(m);
 	}
 	return;
@@ -235,10 +243,8 @@
  * reassembly of this datagram already exists, then it
  * is given as fp; otherwise have to make a chain.
  */
-struct ip *
-ip_reass(ip, fp)
-	register struct ipasfrag *ip;
-	register struct ipq *fp;
+static struct ip *
+ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
 {
 	register struct mbuf *m = dtom(ip);
 	register struct ipasfrag *q;
@@ -385,7 +391,7 @@
 	return ((struct ip *)ip);
 
 dropfrag:
-	ipstat.ips_fragdropped++;
+	STAT(ipstat.ips_fragdropped++);
 	m_freem(m);
 	return (0);
 }
@@ -394,9 +400,8 @@
  * Free a fragment reassembly header and all
  * associated datagrams.
  */
-void
-ip_freef(fp)
-	struct ipq *fp;
+static void
+ip_freef(struct ipq *fp)
 {
 	register struct ipasfrag *q, *p;
 
@@ -414,9 +419,8 @@
  * Put an ip fragment on a reassembly chain.
  * Like insque, but pointers in middle of structure.
  */
-void
-ip_enq(p, prev)
-	register struct ipasfrag *p, *prev;
+static void
+ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev)
 {
 	DEBUG_CALL("ip_enq");
 	DEBUG_ARG("prev = %lx", (long)prev);
@@ -429,9 +433,8 @@
 /*
  * To ip_enq as remque is to insque.
  */
-void
-ip_deq(p)
-	register struct ipasfrag *p;
+static void
+ip_deq(register struct ipasfrag *p)
 {
 	((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
 	((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
@@ -457,7 +460,7 @@
 		--fp->ipq_ttl;
 		fp = (struct ipq *) fp->next;
 		if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
-			ipstat.ips_fragtimeout++;
+			STAT(ipstat.ips_fragtimeout++);
 			ip_freef((struct ipq *) fp->prev);
 		}
 	}
@@ -664,7 +667,7 @@
 /* Not yet */
  	icmp_error(m, type, code, 0, 0);
 
-	ipstat.ips_badoptions++;
+	STAT(ipstat.ips_badoptions++);
 	return (1);
 }
 

Modified: trunk/src/host/qemu-neo1973/slirp/ip_output.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/ip_output.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/ip_output.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -46,6 +46,10 @@
 
 u_int16_t ip_id;
 
+/* Number of packets queued before we start sending
+ * (to prevent allocing too many mbufs) */
+#define IF_THRESH 10
+
 /*
  * IP output.  The packet in mbuf chain m contains a skeletal IP
  * header (with len, off, ttl, proto, tos, src, dst).
@@ -80,14 +84,14 @@
 	ip->ip_off &= IP_DF;
 	ip->ip_id = htons(ip_id++);
 	ip->ip_hl = hlen >> 2;
-	ipstat.ips_localout++;
+	STAT(ipstat.ips_localout++);
 
 	/*
 	 * Verify that we have any chance at all of being able to queue
 	 *      the packet or packet fragments
 	 */
 	/* XXX Hmmm... */
-/*	if (if_queued > if_thresh && towrite <= 0) {
+/*	if (if_queued > IF_THRESH && towrite <= 0) {
  *		error = ENOBUFS;
  *		goto bad;
  *	}
@@ -96,7 +100,7 @@
 	/*
 	 * If small enough for interface, can just send directly.
 	 */
-	if ((u_int16_t)ip->ip_len <= if_mtu) {
+	if ((u_int16_t)ip->ip_len <= IF_MTU) {
 		ip->ip_len = htons((u_int16_t)ip->ip_len);
 		ip->ip_off = htons((u_int16_t)ip->ip_off);
 		ip->ip_sum = 0;
@@ -112,11 +116,11 @@
 	 */
 	if (ip->ip_off & IP_DF) {
 		error = -1;
-		ipstat.ips_cantfrag++;
+		STAT(ipstat.ips_cantfrag++);
 		goto bad;
 	}
 
-	len = (if_mtu - hlen) &~ 7;       /* ip databytes per packet */
+	len = (IF_MTU - hlen) &~ 7;       /* ip databytes per packet */
 	if (len < 8) {
 		error = -1;
 		goto bad;
@@ -137,10 +141,10 @@
 	  m = m_get();
 	  if (m == 0) {
 	    error = -1;
-	    ipstat.ips_odropped++;
+	    STAT(ipstat.ips_odropped++);
 	    goto sendorfree;
 	  }
-	  m->m_data += if_maxlinkhdr;
+	  m->m_data += IF_MAXLINKHDR;
 	  mhip = mtod(m, struct ip *);
 	  *mhip = *ip;
 
@@ -170,7 +174,7 @@
 	  mhip->ip_sum = cksum(m, mhlen);
 	  *mnext = m;
 	  mnext = &m->m_nextpkt;
-	  ipstat.ips_ofragments++;
+	  STAT(ipstat.ips_ofragments++);
 	}
 	/*
 	 * Update first fragment by trimming what's been copied out
@@ -193,7 +197,7 @@
 	}
 
 	if (error == 0)
-		ipstat.ips_fragmented++;
+		STAT(ipstat.ips_fragmented++);
     }
 
 done:

Modified: trunk/src/host/qemu-neo1973/slirp/libslirp.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/libslirp.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/libslirp.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -26,6 +26,8 @@
 extern const char *tftp_prefix;
 extern char slirp_hostname[33];
 
+void slirp_stats(void);
+
 #ifdef __cplusplus
 }
 #endif

Modified: trunk/src/host/qemu-neo1973/slirp/main.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/main.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/main.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -42,7 +42,6 @@
 extern char *socket_path;
 extern int towrite_max;
 extern int ppp_exit;
-extern int so_options;
 extern int tcp_keepintvl;
 extern uint8_t client_ethaddr[6];
 

Modified: trunk/src/host/qemu-neo1973/slirp/mbuf.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/mbuf.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/mbuf.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -21,29 +21,22 @@
 char	*mclrefcnt;
 int mbuf_alloced = 0;
 struct mbuf m_freelist, m_usedlist;
-int mbuf_thresh = 30;
+#define MBUF_THRESH 30
 int mbuf_max = 0;
-int msize;
 
+/*
+ * Find a nice value for msize
+ * XXX if_maxlinkhdr already in mtu
+ */
+#define MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 6)
+
 void
 m_init()
 {
 	m_freelist.m_next = m_freelist.m_prev = &m_freelist;
 	m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
-	msize_init();
 }
 
-void
-msize_init()
-{
-	/*
-	 * Find a nice value for msize
-	 * XXX if_maxlinkhdr already in mtu
-	 */
-	msize = (if_mtu>if_mru?if_mtu:if_mru) +
-			if_maxlinkhdr + sizeof(struct m_hdr ) + 6;
-}
-
 /*
  * Get an mbuf from the free list, if there are none
  * malloc one
@@ -61,10 +54,10 @@
 	DEBUG_CALL("m_get");
 
 	if (m_freelist.m_next == &m_freelist) {
-		m = (struct mbuf *)malloc(msize);
+		m = (struct mbuf *)malloc(MSIZE);
 		if (m == NULL) goto end_error;
 		mbuf_alloced++;
-		if (mbuf_alloced > mbuf_thresh)
+		if (mbuf_alloced > MBUF_THRESH)
 			flags = M_DOFREE;
 		if (mbuf_alloced > mbuf_max)
 			mbuf_max = mbuf_alloced;
@@ -78,7 +71,7 @@
 	m->m_flags = (flags | M_USEDLIST);
 
 	/* Initialise it */
-	m->m_size = msize - sizeof(struct m_hdr);
+	m->m_size = MSIZE - sizeof(struct m_hdr);
 	m->m_data = m->m_dat;
 	m->m_len = 0;
 	m->m_nextpkt = 0;

Modified: trunk/src/host/qemu-neo1973/slirp/mbuf.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/mbuf.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/mbuf.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -135,7 +135,6 @@
 extern int mbuf_max;
 
 void m_init _P((void));
-void msize_init _P((void));
 struct mbuf * m_get _P((void));
 void m_free _P((struct mbuf *));
 void m_cat _P((register struct mbuf *, register struct mbuf *));

Modified: trunk/src/host/qemu-neo1973/slirp/misc.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/misc.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/misc.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -8,8 +8,7 @@
 #define WANT_SYS_IOCTL_H
 #include <slirp.h>
 
-u_int curtime, time_fasttimo, last_slowtimo, detach_time;
-u_int detach_wait = 600000;	/* 10 minutes */
+u_int curtime, time_fasttimo, last_slowtimo;
 
 #if 0
 int x_port = -1;
@@ -214,10 +213,7 @@
 #ifdef _WIN32
 
 int
-fork_exec(so, ex, do_pty)
-	struct socket *so;
-	char *ex;
-	int do_pty;
+fork_exec(struct socket *so, const char *ex, int do_pty)
 {
     /* not implemented */
     return 0;
@@ -225,6 +221,7 @@
 
 #else
 
+#ifndef CONFIG_QEMU
 int
 slirp_openpty(amaster, aslave)
      int *amaster, *aslave;
@@ -289,6 +286,7 @@
 	return (-1);
 #endif
 }
+#endif
 
 /*
  * XXX This is ugly
@@ -302,23 +300,20 @@
  * do_ptr = 2   Fork/exec using pty
  */
 int
-fork_exec(so, ex, do_pty)
-	struct socket *so;
-	char *ex;
-	int do_pty;
+fork_exec(struct socket *so, const char *ex, int do_pty)
 {
 	int s;
 	struct sockaddr_in addr;
 	int addrlen = sizeof(addr);
 	int opt;
-        int master;
+        int master = -1;
 	char *argv[256];
 #if 0
 	char buff[256];
 #endif
 	/* don't want to clobber the original */
 	char *bptr;
-	char *curarg;
+	const char *curarg;
 	int c, i, ret;
 
 	DEBUG_CALL("fork_exec");
@@ -327,10 +322,12 @@
 	DEBUG_ARG("do_pty = %lx", (long)do_pty);
 
 	if (do_pty == 2) {
+#if 0
 		if (slirp_openpty(&master, &s) == -1) {
 			lprint("Error: openpty failed: %s\n", strerror(errno));
 			return 0;
 		}
+#endif
 	} else {
 		addr.sin_family = AF_INET;
 		addr.sin_port = 0;
@@ -390,7 +387,7 @@
 		dup2(s, 0);
 		dup2(s, 1);
 		dup2(s, 2);
-		for (s = 3; s <= 255; s++)
+		for (s = getdtablesize() - 1; s >= 3; s--)
 		   close(s);
 
 		i = 0;
@@ -603,6 +600,16 @@
 }
 #endif
 
+#ifdef CONFIG_QEMU
+void lprint(const char *format, ...)
+{
+    va_list args;
+
+    va_start(args, format);
+    term_vprintf(format, args);
+    va_end(args);
+}
+#else
 int (*lprint_print) _P((void *, const char *, va_list));
 char *lprint_ptr, *lprint_ptr2, **lprint_arg;
 
@@ -754,6 +761,7 @@
 
 	lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
 }
+#endif
 
 #ifdef BAD_SPRINTF
 

Modified: trunk/src/host/qemu-neo1973/slirp/misc.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/misc.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/misc.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -12,12 +12,12 @@
 	int ex_pty;			/* Do we want a pty? */
 	int ex_addr;			/* The last byte of the address */
 	int ex_fport;                   /* Port to telnet to */
-	char *ex_exec;                  /* Command line of what to exec */
+	const char *ex_exec;            /* Command line of what to exec */
 	struct ex_list *ex_next;
 };
 
 extern struct ex_list *exec_list;
-extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait;
+extern u_int curtime, time_fasttimo, last_slowtimo;
 
 extern int (*lprint_print) _P((void *, const char *, va_list));
 extern char *lprint_ptr, *lprint_ptr2, **lprint_arg;
@@ -74,7 +74,7 @@
 inline  void slirp_remque  _P((void *));
 int add_exec _P((struct ex_list **, int, char *, int, int));
 int slirp_openpty _P((int *, int *));
-int fork_exec _P((struct socket *, char *, int));
+int fork_exec(struct socket *so, const char *ex, int do_pty);
 void snooze_hup _P((int));
 void snooze _P((void));
 void relay _P((int));

Modified: trunk/src/host/qemu-neo1973/slirp/sbuf.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/sbuf.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/sbuf.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -7,6 +7,8 @@
 
 #include <slirp.h>
 
+static void sbappendsb(struct sbuf *sb, struct mbuf *m);
+
 /* Done as a macro in socket.h */
 /* int
  * sbspace(struct sockbuff *sb)
@@ -133,10 +135,8 @@
  * Copy the data from m into sb
  * The caller is responsible to make sure there's enough room
  */
-void
-sbappendsb(sb, m)
-	 struct sbuf *sb;
-	 struct mbuf *m;
+static void
+sbappendsb(struct sbuf *sb, struct mbuf *m)
 {
 	int len, n,  nn;
 

Modified: trunk/src/host/qemu-neo1973/slirp/sbuf.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/sbuf.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/sbuf.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -25,7 +25,6 @@
 void sbdrop _P((struct sbuf *, int));
 void sbreserve _P((struct sbuf *, int));
 void sbappend _P((struct socket *, struct mbuf *));
-void sbappendsb _P((struct sbuf *, struct mbuf *));
 void sbcopy _P((struct sbuf *, int, int, char *));
 
 #endif

Modified: trunk/src/host/qemu-neo1973/slirp/slirp.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/slirp.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/slirp.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -12,7 +12,7 @@
 /* virtual address alias for host */
 struct in_addr alias_addr;
 
-const uint8_t special_ethaddr[6] = {
+static const uint8_t special_ethaddr[6] = {
     0x52, 0x54, 0x00, 0x12, 0x35, 0x00
 };
 
@@ -93,7 +93,9 @@
     if (!f)
         return -1;
 
+#ifdef DEBUG
     lprint("IP address of your DNS(s): ");
+#endif
     while (fgets(buff, 512, f) != NULL) {
         if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
             if (!inet_aton(buff2, &tmp_addr))
@@ -103,13 +105,20 @@
             /* If it's the first one, set it to dns_addr */
             if (!found)
                 *pdns_addr = tmp_addr;
+#ifdef DEBUG
             else
                 lprint(", ");
+#endif
             if (++found > 3) {
+#ifdef DEBUG
                 lprint("(more)");
+#endif
                 break;
-            } else
+            }
+#ifdef DEBUG
+            else
                 lprint("%s", inet_ntoa(tmp_addr));
+#endif
         }
     }
     fclose(f);
@@ -121,7 +130,7 @@
 #endif
 
 #ifdef _WIN32
-void slirp_cleanup(void)
+static void slirp_cleanup(void)
 {
     WSACleanup();
 }

Modified: trunk/src/host/qemu-neo1973/slirp/slirp.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/slirp.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/slirp.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -3,8 +3,17 @@
 
 #define CONFIG_QEMU
 
-#define DEBUG 1
+//#define DEBUG 1
 
+// Uncomment the following line to enable SLIRP statistics printing in Qemu
+//#define LOG_ENABLED
+
+#ifdef LOG_ENABLED
+#define STAT(expr) expr
+#else
+#define STAT(expr) do { } while(0)
+#endif
+
 #ifndef CONFIG_QEMU
 #include "version.h"
 #endif
@@ -255,8 +264,6 @@
 
 void lprint _P((const char *, ...));
 
-extern int do_echo;
-
 #if SIZEOF_CHAR_P == 4
 # define insque_32 insque
 # define remque_32 remque
@@ -271,6 +278,9 @@
 
 #define DEFAULT_BAUD 115200
 
+#define SO_OPTIONS DO_KEEPALIVE
+#define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL)
+
 /* cksum.c */
 int cksum(struct mbuf *m, int len);
 
@@ -281,10 +291,6 @@
 /* ip_input.c */
 void ip_init _P((void));
 void ip_input _P((struct mbuf *));
-struct ip * ip_reass _P((register struct ipasfrag *, register struct ipq *));
-void ip_freef _P((struct ipq *));
-void ip_enq _P((register struct ipasfrag *, register struct ipasfrag *));
-void ip_deq _P((register struct ipasfrag *));
 void ip_slowtimo _P((void));
 void ip_stripoptions _P((register struct mbuf *, struct mbuf *));
 
@@ -292,10 +298,7 @@
 int ip_output _P((struct socket *, struct mbuf *));
 
 /* tcp_input.c */
-int tcp_reass _P((register struct tcpcb *, register struct tcpiphdr *, struct mbuf *));
 void tcp_input _P((register struct mbuf *, int, struct socket *));
-void tcp_dooptions _P((struct tcpcb *, u_char *, int, struct tcpiphdr *));
-void tcp_xmit_timer _P((register struct tcpcb *, int));
 int tcp_mss _P((register struct tcpcb *, u_int));
 
 /* tcp_output.c */
@@ -308,7 +311,6 @@
 void tcp_respond _P((struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int));
 struct tcpcb * tcp_newtcpcb _P((struct socket *));
 struct tcpcb * tcp_close _P((register struct tcpcb *));
-void tcp_drain _P((void));
 void tcp_sockclosed _P((struct tcpcb *));
 int tcp_fconnect _P((struct socket *));
 void tcp_connect _P((struct socket *));

Modified: trunk/src/host/qemu-neo1973/slirp/socket.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/socket.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/socket.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -13,13 +13,17 @@
 #include <sys/filio.h>
 #endif
 
-void
+static void sofcantrcvmore(struct socket *so);
+static void sofcantsendmore(struct socket *so);
+
+#if 0
+static void
 so_init()
 {
 	/* Nothing yet */
 }
+#endif
 
-
 struct socket *
 solookup(head, laddr, lport, faddr, fport)
 	struct socket *head;
@@ -421,7 +425,7 @@
 	  int len, n;
 
 	  if (!(m = m_get())) return;
-	  m->m_data += if_maxlinkhdr;
+	  m->m_data += IF_MAXLINKHDR;
 
 	  /*
 	   * XXX Shouldn't FIONREAD packets destined for port 53,
@@ -604,12 +608,13 @@
 	return so;
 }
 
+#if 0
 /*
  * Data is available in so_rcv
  * Just write() the data to the socket
  * XXX not yet...
  */
-void
+static void
 sorwakeup(so)
 	struct socket *so;
 {
@@ -622,12 +627,13 @@
  * We have room for a read() if we want to
  * For now, don't read, it'll be done in the main loop
  */
-void
+static void
 sowwakeup(so)
 	struct socket *so;
 {
 	/* Nothing, yet */
 }
+#endif
 
 /*
  * Various session state calls
@@ -652,9 +658,8 @@
 	so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
 }
 
-void
-sofcantrcvmore(so)
-	struct  socket *so;
+static void
+sofcantrcvmore(struct socket *so)
 {
 	if ((so->so_state & SS_NOFDREF) == 0) {
 		shutdown(so->s,0);
@@ -669,9 +674,8 @@
 	   so->so_state |= SS_FCANTRCVMORE;
 }
 
-void
-sofcantsendmore(so)
-	struct socket *so;
+static void
+sofcantsendmore(struct socket *so)
 {
 	if ((so->so_state & SS_NOFDREF) == 0) {
             shutdown(so->s,1);           /* send FIN to fhost */

Modified: trunk/src/host/qemu-neo1973/slirp/socket.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/socket.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/socket.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -81,7 +81,6 @@
 };
 #endif
 
-void so_init _P((void));
 struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int));
 struct socket * socreate _P((void));
 void sofree _P((struct socket *));
@@ -92,12 +91,8 @@
 void sorecvfrom _P((struct socket *));
 int sosendto _P((struct socket *, struct mbuf *));
 struct socket * solisten _P((u_int, u_int32_t, u_int, int));
-void sorwakeup _P((struct socket *));
-void sowwakeup _P((struct socket *));
 void soisfconnecting _P((register struct socket *));
 void soisfconnected _P((register struct socket *));
-void sofcantrcvmore _P((struct  socket *));
-void sofcantsendmore _P((struct socket *));
 void soisfdisconnected _P((struct socket *));
 void sofwdrain _P((struct socket *));
 

Modified: trunk/src/host/qemu-neo1973/slirp/tcp.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -42,8 +42,6 @@
 #define      PR_SLOWHZ       2               /* 2 slow timeouts per second (approx) */
 #define      PR_FASTHZ       5               /* 5 fast timeouts per second (not important) */
 
-extern int tcp_rcvspace;
-extern int tcp_sndspace;
 extern struct socket *tcp_last_so;
 
 #define TCP_SNDSPACE 8192
@@ -172,6 +170,6 @@
 
 extern tcp_seq tcp_iss;                /* tcp initial send seq # */
 
-extern char *tcpstates[];
+extern const char * const tcpstates[];
 
 #endif

Modified: trunk/src/host/qemu-neo1973/slirp/tcp_input.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp_input.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp_input.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -47,7 +47,7 @@
 
 struct socket tcb;
 
-int	tcprexmtthresh = 3;
+#define	TCPREXMTTHRESH 3
 struct	socket *tcp_last_so = &tcb;
 
 tcp_seq tcp_iss;                /* tcp initial send seq # */
@@ -79,8 +79,8 @@
                        tp->t_flags |= TF_DELACK; \
                (tp)->rcv_nxt += (ti)->ti_len; \
                flags = (ti)->ti_flags & TH_FIN; \
-               tcpstat.tcps_rcvpack++;\
-               tcpstat.tcps_rcvbyte += (ti)->ti_len;\
+               STAT(tcpstat.tcps_rcvpack++);         \
+               STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len);   \
                if (so->so_emu) { \
 		       if (tcp_emu((so),(m))) sbappend((so), (m)); \
 	       } else \
@@ -99,8 +99,8 @@
 		tp->t_flags |= TF_DELACK; \
 		(tp)->rcv_nxt += (ti)->ti_len; \
 		flags = (ti)->ti_flags & TH_FIN; \
-		tcpstat.tcps_rcvpack++;\
-		tcpstat.tcps_rcvbyte += (ti)->ti_len;\
+		STAT(tcpstat.tcps_rcvpack++);        \
+		STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len);  \
 		if (so->so_emu) { \
 			if (tcp_emu((so),(m))) sbappend(so, (m)); \
 		} else \
@@ -112,12 +112,13 @@
 	} \
 }
 #endif
+static void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt,
+                          struct tcpiphdr *ti);
+static void tcp_xmit_timer(register struct tcpcb *tp, int rtt);
 
-int
-tcp_reass(tp, ti, m)
-	register struct tcpcb *tp;
-	register struct tcpiphdr *ti;
-	struct mbuf *m;
+static int
+tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti,
+          struct mbuf *m)
 {
 	register struct tcpiphdr *q;
 	struct socket *so = tp->t_socket;
@@ -150,8 +151,8 @@
 		i = q->ti_seq + q->ti_len - ti->ti_seq;
 		if (i > 0) {
 			if (i >= ti->ti_len) {
-				tcpstat.tcps_rcvduppack++;
-				tcpstat.tcps_rcvdupbyte += ti->ti_len;
+				STAT(tcpstat.tcps_rcvduppack++);
+				STAT(tcpstat.tcps_rcvdupbyte += ti->ti_len);
 				m_freem(m);
 				/*
 				 * Try to present any queued data
@@ -167,8 +168,8 @@
 		}
 		q = (struct tcpiphdr *)(q->ti_next);
 	}
-	tcpstat.tcps_rcvoopack++;
-	tcpstat.tcps_rcvoobyte += ti->ti_len;
+	STAT(tcpstat.tcps_rcvoopack++);
+	STAT(tcpstat.tcps_rcvoobyte += ti->ti_len);
 	REASS_MBUF(ti) = (mbufp_32) m;		/* XXX */
 
 	/*
@@ -275,7 +276,7 @@
 	}
 
 
-	tcpstat.tcps_rcvtotal++;
+	STAT(tcpstat.tcps_rcvtotal++);
 	/*
 	 * Get IP and TCP header together in first mbuf.
 	 * Note: IP leaves IP header in first mbuf.
@@ -308,7 +309,7 @@
 	 * ti->ti_sum = cksum(m, len);
 	 * if (ti->ti_sum) { */
 	if(cksum(m, len)) {
-	  tcpstat.tcps_rcvbadsum++;
+	  STAT(tcpstat.tcps_rcvbadsum++);
 	  goto drop;
 	}
 
@@ -318,7 +319,7 @@
 	 */
 	off = ti->ti_off << 2;
 	if (off < sizeof (struct tcphdr) || off > tlen) {
-	  tcpstat.tcps_rcvbadoff++;
+	  STAT(tcpstat.tcps_rcvbadoff++);
 	  goto drop;
 	}
 	tlen -= off;
@@ -375,7 +376,7 @@
 			       ti->ti_dst, ti->ti_dport);
 		if (so)
 			tcp_last_so = so;
-		++tcpstat.tcps_socachemiss;
+		STAT(tcpstat.tcps_socachemiss++);
 	}
 
 	/*
@@ -402,8 +403,8 @@
 	    goto dropwithreset;
 	  }
 
-	  sbreserve(&so->so_snd, tcp_sndspace);
-	  sbreserve(&so->so_rcv, tcp_rcvspace);
+	  sbreserve(&so->so_snd, TCP_SNDSPACE);
+	  sbreserve(&so->so_rcv, TCP_RCVSPACE);
 
 	  /*		tcp_last_so = so; */  /* XXX ? */
 	  /*		tp = sototcpcb(so);    */
@@ -448,10 +449,10 @@
 	 * Reset idle time and keep-alive timer.
 	 */
 	tp->t_idle = 0;
-	if (so_options)
-	   tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
+	if (SO_OPTIONS)
+	   tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
 	else
-	   tp->t_timer[TCPT_KEEP] = tcp_keepidle;
+	   tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
 
 	/*
 	 * Process options if not in LISTEN state,
@@ -503,7 +504,7 @@
 				/*
 				 * this is a pure ack for outstanding data.
 				 */
-				++tcpstat.tcps_predack;
+				STAT(tcpstat.tcps_predack++);
 /*				if (ts_present)
  *					tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
  *				else
@@ -511,8 +512,8 @@
 					    SEQ_GT(ti->ti_ack, tp->t_rtseq))
 					tcp_xmit_timer(tp, tp->t_rtt);
 				acked = ti->ti_ack - tp->snd_una;
-				tcpstat.tcps_rcvackpack++;
-				tcpstat.tcps_rcvackbyte += acked;
+				STAT(tcpstat.tcps_rcvackpack++);
+				STAT(tcpstat.tcps_rcvackbyte += acked);
 				sbdrop(&so->so_snd, acked);
 				tp->snd_una = ti->ti_ack;
 				m_freem(m);
@@ -556,10 +557,10 @@
 			 * with nothing on the reassembly queue and
 			 * we have enough buffer space to take it.
 			 */
-			++tcpstat.tcps_preddat;
+			STAT(tcpstat.tcps_preddat++);
 			tp->rcv_nxt += ti->ti_len;
-			tcpstat.tcps_rcvpack++;
-			tcpstat.tcps_rcvbyte += ti->ti_len;
+			STAT(tcpstat.tcps_rcvpack++);
+			STAT(tcpstat.tcps_rcvbyte += ti->ti_len);
 			/*
 			 * Add data to socket buffer.
 			 */
@@ -726,7 +727,7 @@
 	  tp->t_flags |= TF_ACKNOW;
 	  tp->t_state = TCPS_SYN_RECEIVED;
 	  tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
-	  tcpstat.tcps_accepts++;
+	  STAT(tcpstat.tcps_accepts++);
 	  goto trimthenstep6;
 	} /* case TCPS_LISTEN */
 
@@ -767,7 +768,7 @@
 		tcp_rcvseqinit(tp);
 		tp->t_flags |= TF_ACKNOW;
 		if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) {
-			tcpstat.tcps_connects++;
+			STAT(tcpstat.tcps_connects++);
 			soisfconnected(so);
 			tp->t_state = TCPS_ESTABLISHED;
 
@@ -801,8 +802,8 @@
 			m_adj(m, -todrop);
 			ti->ti_len = tp->rcv_wnd;
 			tiflags &= ~TH_FIN;
-			tcpstat.tcps_rcvpackafterwin++;
-			tcpstat.tcps_rcvbyteafterwin += todrop;
+			STAT(tcpstat.tcps_rcvpackafterwin++);
+			STAT(tcpstat.tcps_rcvbyteafterwin += todrop);
 		}
 		tp->snd_wl1 = ti->ti_seq - 1;
 		tp->rcv_up = ti->ti_seq;
@@ -873,11 +874,11 @@
 			 */
 			tp->t_flags |= TF_ACKNOW;
 			todrop = ti->ti_len;
-			tcpstat.tcps_rcvduppack++;
-			tcpstat.tcps_rcvdupbyte += todrop;
+			STAT(tcpstat.tcps_rcvduppack++);
+			STAT(tcpstat.tcps_rcvdupbyte += todrop);
 		} else {
-			tcpstat.tcps_rcvpartduppack++;
-			tcpstat.tcps_rcvpartdupbyte += todrop;
+			STAT(tcpstat.tcps_rcvpartduppack++);
+			STAT(tcpstat.tcps_rcvpartdupbyte += todrop);
 		}
 		m_adj(m, todrop);
 		ti->ti_seq += todrop;
@@ -896,7 +897,7 @@
 	if ((so->so_state & SS_NOFDREF) &&
 	    tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {
 		tp = tcp_close(tp);
-		tcpstat.tcps_rcvafterclose++;
+		STAT(tcpstat.tcps_rcvafterclose++);
 		goto dropwithreset;
 	}
 
@@ -906,9 +907,9 @@
 	 */
 	todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
 	if (todrop > 0) {
-		tcpstat.tcps_rcvpackafterwin++;
+		STAT(tcpstat.tcps_rcvpackafterwin++);
 		if (todrop >= ti->ti_len) {
-			tcpstat.tcps_rcvbyteafterwin += ti->ti_len;
+			STAT(tcpstat.tcps_rcvbyteafterwin += ti->ti_len);
 			/*
 			 * If a new connection request is received
 			 * while in TIME_WAIT, drop the old connection
@@ -931,11 +932,11 @@
 			 */
 			if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) {
 				tp->t_flags |= TF_ACKNOW;
-				tcpstat.tcps_rcvwinprobe++;
+				STAT(tcpstat.tcps_rcvwinprobe++);
 			} else
 				goto dropafterack;
 		} else
-			tcpstat.tcps_rcvbyteafterwin += todrop;
+			STAT(tcpstat.tcps_rcvbyteafterwin += todrop);
 		m_adj(m, -todrop);
 		ti->ti_len -= todrop;
 		tiflags &= ~(TH_PUSH|TH_FIN);
@@ -976,7 +977,7 @@
 /*		so->so_error = ECONNRESET; */
 	close:
 		tp->t_state = TCPS_CLOSED;
-		tcpstat.tcps_drops++;
+		STAT(tcpstat.tcps_drops++);
 		tp = tcp_close(tp);
 		goto drop;
 
@@ -1015,7 +1016,7 @@
 		if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
 		    SEQ_GT(ti->ti_ack, tp->snd_max))
 			goto dropwithreset;
-		tcpstat.tcps_connects++;
+		STAT(tcpstat.tcps_connects++);
 		tp->t_state = TCPS_ESTABLISHED;
 		/*
 		 * The sent SYN is ack'ed with our sequence number +1
@@ -1072,7 +1073,7 @@
 
 		if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
 			if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {
-			  tcpstat.tcps_rcvdupack++;
+			  STAT(tcpstat.tcps_rcvdupack++);
 			  DEBUG_MISC((dfd," dup ack  m = %lx  so = %lx \n",
 				      (long )m, (long )so));
 				/*
@@ -1102,7 +1103,7 @@
 				if (tp->t_timer[TCPT_REXMT] == 0 ||
 				    ti->ti_ack != tp->snd_una)
 					tp->t_dupacks = 0;
-				else if (++tp->t_dupacks == tcprexmtthresh) {
+				else if (++tp->t_dupacks == TCPREXMTTHRESH) {
 					tcp_seq onxt = tp->snd_nxt;
 					u_int win =
 					    min(tp->snd_wnd, tp->snd_cwnd) / 2 /
@@ -1121,7 +1122,7 @@
 					if (SEQ_GT(onxt, tp->snd_nxt))
 						tp->snd_nxt = onxt;
 					goto drop;
-				} else if (tp->t_dupacks > tcprexmtthresh) {
+				} else if (tp->t_dupacks > TCPREXMTTHRESH) {
 					tp->snd_cwnd += tp->t_maxseg;
 					(void) tcp_output(tp);
 					goto drop;
@@ -1135,17 +1136,17 @@
 		 * If the congestion window was inflated to account
 		 * for the other side's cached packets, retract it.
 		 */
-		if (tp->t_dupacks > tcprexmtthresh &&
+		if (tp->t_dupacks > TCPREXMTTHRESH &&
 		    tp->snd_cwnd > tp->snd_ssthresh)
 			tp->snd_cwnd = tp->snd_ssthresh;
 		tp->t_dupacks = 0;
 		if (SEQ_GT(ti->ti_ack, tp->snd_max)) {
-			tcpstat.tcps_rcvacktoomuch++;
+			STAT(tcpstat.tcps_rcvacktoomuch++);
 			goto dropafterack;
 		}
 		acked = ti->ti_ack - tp->snd_una;
-		tcpstat.tcps_rcvackpack++;
-		tcpstat.tcps_rcvackbyte += acked;
+		STAT(tcpstat.tcps_rcvackpack++);
+		STAT(tcpstat.tcps_rcvackbyte += acked);
 
 		/*
 		 * If we have a timestamp reply, update smoothed
@@ -1227,7 +1228,7 @@
 				 */
 				if (so->so_state & SS_FCANTRCVMORE) {
 					soisfdisconnected(so);
-					tp->t_timer[TCPT_2MSL] = tcp_maxidle;
+					tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE;
 				}
 				tp->t_state = TCPS_FIN_WAIT_2;
 			}
@@ -1284,7 +1285,7 @@
 		/* keep track of pure window updates */
 		if (ti->ti_len == 0 &&
 		    tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd)
-			tcpstat.tcps_rcvwinupd++;
+			STAT(tcpstat.tcps_rcvwinupd++);
 		tp->snd_wnd = tiwin;
 		tp->snd_wl1 = ti->ti_seq;
 		tp->snd_wl2 = ti->ti_ack;
@@ -1490,12 +1491,8 @@
 /*	int *ts_present;
  *	u_int32_t *ts_val, *ts_ecr;
  */
-void
-tcp_dooptions(tp, cp, cnt, ti)
-	struct tcpcb *tp;
-	u_char *cp;
-	int cnt;
-	struct tcpiphdr *ti;
+static void
+tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)
 {
 	u_int16_t mss;
 	int opt, optlen;
@@ -1605,10 +1602,8 @@
  * and update averages and current timeout.
  */
 
-void
-tcp_xmit_timer(tp, rtt)
-	register struct tcpcb *tp;
-	int rtt;
+static void
+tcp_xmit_timer(register struct tcpcb *tp, int rtt)
 {
 	register short delta;
 
@@ -1616,7 +1611,7 @@
 	DEBUG_ARG("tp = %lx", (long)tp);
 	DEBUG_ARG("rtt = %d", rtt);
 
-	tcpstat.tcps_rttupdated++;
+	STAT(tcpstat.tcps_rttupdated++);
 	if (tp->t_srtt != 0) {
 		/*
 		 * srtt is stored as fixed point with 3 bits after the
@@ -1707,7 +1702,7 @@
 	DEBUG_ARG("tp = %lx", (long)tp);
 	DEBUG_ARG("offer = %d", offer);
 
-	mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr);
+	mss = min(IF_MTU, IF_MRU) - sizeof(struct tcpiphdr);
 	if (offer)
 		mss = min(mss, offer);
 	mss = max(mss, 32);
@@ -1716,8 +1711,12 @@
 
 	tp->snd_cwnd = mss;
 
-	sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0));
-	sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0));
+	sbreserve(&so->so_snd, TCP_SNDSPACE + ((TCP_SNDSPACE % mss) ?
+                                               (mss - (TCP_SNDSPACE % mss)) :
+                                               0));
+	sbreserve(&so->so_rcv, TCP_RCVSPACE + ((TCP_RCVSPACE % mss) ?
+                                               (mss - (TCP_RCVSPACE % mss)) :
+                                               0));
 
 	DEBUG_MISC((dfd, " returning mss = %d\n", mss));
 

Modified: trunk/src/host/qemu-neo1973/slirp/tcp_output.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp_output.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp_output.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -48,14 +48,14 @@
  * Since this is only used in "stats socket", we give meaning
  * names instead of the REAL names
  */
-char *tcpstates[] = {
+const char * const tcpstates[] = {
 /*	"CLOSED",       "LISTEN",       "SYN_SENT",     "SYN_RCVD", */
 	"REDIRECT",	"LISTEN",	"SYN_SENT",     "SYN_RCVD",
 	"ESTABLISHED",  "CLOSE_WAIT",   "FIN_WAIT_1",   "CLOSING",
 	"LAST_ACK",     "FIN_WAIT_2",   "TIME_WAIT",
 };
 
-u_char  tcp_outflags[TCP_NSTATES] = {
+static const u_char  tcp_outflags[TCP_NSTATES] = {
 	TH_RST|TH_ACK, 0,      TH_SYN,        TH_SYN|TH_ACK,
 	TH_ACK,        TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
 	TH_FIN|TH_ACK, TH_ACK, TH_ACK,
@@ -263,7 +263,7 @@
 	/*
 	 * No reason to send a segment, just return.
 	 */
-	tcpstat.tcps_didnuttin++;
+	STAT(tcpstat.tcps_didnuttin++);
 
 	return (0);
 
@@ -339,13 +339,13 @@
 	 */
 	if (len) {
 		if (tp->t_force && len == 1)
-			tcpstat.tcps_sndprobe++;
+			STAT(tcpstat.tcps_sndprobe++);
 		else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
-			tcpstat.tcps_sndrexmitpack++;
-			tcpstat.tcps_sndrexmitbyte += len;
+			STAT(tcpstat.tcps_sndrexmitpack++);
+			STAT(tcpstat.tcps_sndrexmitbyte += len);
 		} else {
-			tcpstat.tcps_sndpack++;
-			tcpstat.tcps_sndbyte += len;
+			STAT(tcpstat.tcps_sndpack++);
+			STAT(tcpstat.tcps_sndbyte += len);
 		}
 
 		m = m_get();
@@ -354,7 +354,7 @@
 			error = 1;
 			goto out;
 		}
-		m->m_data += if_maxlinkhdr;
+		m->m_data += IF_MAXLINKHDR;
 		m->m_len = hdrlen;
 
 		/*
@@ -382,13 +382,13 @@
 			flags |= TH_PUSH;
 	} else {
 		if (tp->t_flags & TF_ACKNOW)
-			tcpstat.tcps_sndacks++;
+			STAT(tcpstat.tcps_sndacks++);
 		else if (flags & (TH_SYN|TH_FIN|TH_RST))
-			tcpstat.tcps_sndctrl++;
+			STAT(tcpstat.tcps_sndctrl++);
 		else if (SEQ_GT(tp->snd_up, tp->snd_una))
-			tcpstat.tcps_sndurg++;
+			STAT(tcpstat.tcps_sndurg++);
 		else
-			tcpstat.tcps_sndwinup++;
+			STAT(tcpstat.tcps_sndwinup++);
 
 		m = m_get();
 		if (m == NULL) {
@@ -396,7 +396,7 @@
 			error = 1;
 			goto out;
 		}
-		m->m_data += if_maxlinkhdr;
+		m->m_data += IF_MAXLINKHDR;
 		m->m_len = hdrlen;
 	}
 
@@ -500,7 +500,7 @@
 			if (tp->t_rtt == 0) {
 				tp->t_rtt = 1;
 				tp->t_rtseq = startseq;
-				tcpstat.tcps_segstimed++;
+				STAT(tcpstat.tcps_segstimed++);
 			}
 		}
 
@@ -536,7 +536,7 @@
 
 	((struct ip *)ti)->ip_len = m->m_len;
 
-	((struct ip *)ti)->ip_ttl = ip_defttl;
+	((struct ip *)ti)->ip_ttl = IPDEFTTL;
 	((struct ip *)ti)->ip_tos = so->so_iptos;
 
 /* #if BSD >= 43 */
@@ -567,7 +567,7 @@
  */
 		return (error);
 	}
-	tcpstat.tcps_sndtotal++;
+	STAT(tcpstat.tcps_sndtotal++);
 
 	/*
 	 * Data sent (as far as we can tell).

Modified: trunk/src/host/qemu-neo1973/slirp/tcp_subr.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp_subr.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp_subr.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -46,11 +46,8 @@
 #include <slirp.h>
 
 /* patchable/settable parameters for tcp */
-int 	tcp_mssdflt = TCP_MSS;
-int 	tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
-int	tcp_do_rfc1323 = 0;	/* Don't do rfc1323 performance enhancements */
-int	tcp_rcvspace;	/* You may want to change this */
-int	tcp_sndspace;	/* Keep small if you have an error prone link */
+/* Don't do rfc1323 performance enhancements */
+#define TCP_DO_RFC1323 0
 
 /*
  * Tcp initialization
@@ -60,14 +57,6 @@
 {
 	tcp_iss = 1;		/* wrong */
 	tcb.so_next = tcb.so_prev = &tcb;
-
-	/* tcp_rcvspace = our Window we advertise to the remote */
-	tcp_rcvspace = TCP_RCVSPACE;
-	tcp_sndspace = TCP_SNDSPACE;
-
-	/* Make sure tcp_sndspace is at least 2*MSS */
-	if (tcp_sndspace < 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr)))
-		tcp_sndspace = 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr));
 }
 
 /*
@@ -145,7 +134,7 @@
 #else
 		tlen = 0;
 #endif
-		m->m_data += if_maxlinkhdr;
+		m->m_data += IF_MAXLINKHDR;
 		*mtod(m, struct tcpiphdr *) = *ti;
 		ti = mtod(m, struct tcpiphdr *);
 		flags = TH_ACK;
@@ -186,7 +175,7 @@
 	if(flags & TH_RST)
 	  ((struct ip *)ti)->ip_ttl = MAXTTL;
 	else
-	  ((struct ip *)ti)->ip_ttl = ip_defttl;
+	  ((struct ip *)ti)->ip_ttl = IPDEFTTL;
 
 	(void) ip_output((struct socket *)0, m);
 }
@@ -208,9 +197,9 @@
 
 	memset((char *) tp, 0, sizeof(struct tcpcb));
 	tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp;
-	tp->t_maxseg = tcp_mssdflt;
+	tp->t_maxseg = TCP_MSS;
 
-	tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
+	tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
 	tp->t_socket = so;
 
 	/*
@@ -219,7 +208,7 @@
 	 * reasonable initial retransmit time.
 	 */
 	tp->t_srtt = TCPTV_SRTTBASE;
-	tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2;
+	tp->t_rttvar = TCPTV_SRTTDFLT << 2;
 	tp->t_rttmin = TCPTV_MIN;
 
 	TCPT_RANGESET(tp->t_rxtcur,
@@ -255,9 +244,9 @@
 	if (TCPS_HAVERCVDSYN(tp->t_state)) {
 		tp->t_state = TCPS_CLOSED;
 		(void) tcp_output(tp);
-		tcpstat.tcps_drops++;
+		STAT(tcpstat.tcps_drops++);
 	} else
-		tcpstat.tcps_conndrops++;
+		STAT(tcpstat.tcps_conndrops++);
 /*	if (errno == ETIMEDOUT && tp->t_softerror)
  *		errno = tp->t_softerror;
  */
@@ -305,10 +294,11 @@
 	sbfree(&so->so_rcv);
 	sbfree(&so->so_snd);
 	sofree(so);
-	tcpstat.tcps_closed++;
+	STAT(tcpstat.tcps_closed++);
 	return ((struct tcpcb *)0);
 }
 
+#ifdef notdef
 void
 tcp_drain()
 {
@@ -319,9 +309,6 @@
  * When a source quench is received, close congestion window
  * to one segment.  We will gradually open it again as we proceed.
  */
-
-#ifdef notdef
-
 void
 tcp_quench(i, errno)
 
@@ -528,7 +515,7 @@
  */
 
 /*	soisconnecting(so); */ /* NOFDREF used instead */
-	tcpstat.tcps_connattempt++;
+	STAT(tcpstat.tcps_connattempt++);
 
 	tp->t_state = TCPS_SYN_SENT;
 	tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
@@ -556,7 +543,7 @@
 /*
  * Set the socket's type of service field
  */
-struct tos_t tcptos[] = {
+static const struct tos_t tcptos[] = {
 	  {0, 20, IPTOS_THROUGHPUT, 0},	/* ftp data */
 	  {21, 21, IPTOS_LOWDELAY,  EMU_FTP},	/* ftp control */
 	  {0, 23, IPTOS_LOWDELAY, 0},	/* telnet */
@@ -572,7 +559,7 @@
 	  {0, 0, 0, 0}
 };
 
-struct emu_t *tcpemu = 0;
+static struct emu_t *tcpemu = 0;
 
 /*
  * Return TOS according to the above table
@@ -605,7 +592,9 @@
 	return 0;
 }
 
+#if 0
 int do_echo = -1;
+#endif
 
 /*
  * Emulate programs that try and connect to us
@@ -665,7 +654,7 @@
 			so_rcv->sb_rptr += m->m_len;
 			m->m_data[m->m_len] = 0; /* NULL terminate */
 			if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) {
-				if (sscanf(so_rcv->sb_data, "%d%*[ ,]%d", &n1, &n2) == 2) {
+				if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) {
 					HTONS(n1);
 					HTONS(n2);
 					/* n2 is the one on our host */
@@ -857,7 +846,7 @@
 
                 /*soisfconnecting(ns);*/
 
-				tcpstat.tcps_connattempt++;
+				STAT(tcpstat.tcps_connattempt++);
 
 				tp->t_state = TCPS_SYN_SENT;
 				tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
@@ -991,7 +980,7 @@
 			/*
 			 * Need to emulate the PORT command
 			 */
-			x = sscanf(bptr, "ORT %d,%d,%d,%d,%d,%d\r\n%256[^\177]",
+			x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]",
 				   &n1, &n2, &n3, &n4, &n5, &n6, buff);
 			if (x < 6)
 			   return 1;
@@ -1022,7 +1011,7 @@
 			/*
 			 * Need to emulate the PASV response
 			 */
-			x = sscanf(bptr, "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%256[^\177]",
+			x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]",
 				   &n1, &n2, &n3, &n4, &n5, &n6, buff);
 			if (x < 6)
 			   return 1;

Modified: trunk/src/host/qemu-neo1973/slirp/tcp_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp_timer.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp_timer.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -36,14 +36,14 @@
 
 #include <slirp.h>
 
-int	tcp_keepidle = TCPTV_KEEP_IDLE;
-int	tcp_keepintvl = TCPTV_KEEPINTVL;
-int	tcp_maxidle;
-int	so_options = DO_KEEPALIVE;
-
+#ifdef LOG_ENABLED
 struct   tcpstat tcpstat;        /* tcp statistics */
+#endif
+
 u_int32_t        tcp_now;                /* for RFC 1323 timestamps */
 
+static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer);
+
 /*
  * Fast timeout routine for processing delayed acks
  */
@@ -62,7 +62,7 @@
 		    (tp->t_flags & TF_DELACK)) {
 			tp->t_flags &= ~TF_DELACK;
 			tp->t_flags |= TF_ACKNOW;
-			tcpstat.tcps_delack++;
+			STAT(tcpstat.tcps_delack++);
 			(void) tcp_output(tp);
 		}
 }
@@ -81,7 +81,6 @@
 
 	DEBUG_CALL("tcp_slowtimo");
 
-	tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl;
 	/*
 	 * Search through tcb's and update active timers.
 	 */
@@ -127,16 +126,14 @@
 		tp->t_timer[i] = 0;
 }
 
-int	tcp_backoff[TCP_MAXRXTSHIFT + 1] =
+const int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
    { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
 
 /*
  * TCP timer processing.
  */
-struct tcpcb *
-tcp_timers(tp, timer)
-	register struct tcpcb *tp;
-	int timer;
+static struct tcpcb *
+tcp_timers(register struct tcpcb *tp, int timer)
 {
 	register int rexmt;
 
@@ -152,8 +149,8 @@
 	 */
 	case TCPT_2MSL:
 		if (tp->t_state != TCPS_TIME_WAIT &&
-		    tp->t_idle <= tcp_maxidle)
-			tp->t_timer[TCPT_2MSL] = tcp_keepintvl;
+		    tp->t_idle <= TCP_MAXIDLE)
+			tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL;
 		else
 			tp = tcp_close(tp);
 		break;
@@ -192,7 +189,7 @@
 				 * We tried our best, now the connection must die!
 				 */
 				tp->t_rxtshift = TCP_MAXRXTSHIFT;
-				tcpstat.tcps_timeoutdrop++;
+				STAT(tcpstat.tcps_timeoutdrop++);
 				tp = tcp_drop(tp, tp->t_softerror);
 				/* tp->t_softerror : ETIMEDOUT); */ /* XXX */
 				return (tp); /* XXX */
@@ -204,7 +201,7 @@
 			 */
 			tp->t_rxtshift = 6;
 		}
-		tcpstat.tcps_rexmttimeo++;
+		STAT(tcpstat.tcps_rexmttimeo++);
 		rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
 		TCPT_RANGESET(tp->t_rxtcur, rexmt,
 		    (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
@@ -267,7 +264,7 @@
 	 * Force a byte to be output, if possible.
 	 */
 	case TCPT_PERSIST:
-		tcpstat.tcps_persisttimeo++;
+		STAT(tcpstat.tcps_persisttimeo++);
 		tcp_setpersist(tp);
 		tp->t_force = 1;
 		(void) tcp_output(tp);
@@ -279,13 +276,13 @@
 	 * or drop connection if idle for too long.
 	 */
 	case TCPT_KEEP:
-		tcpstat.tcps_keeptimeo++;
+		STAT(tcpstat.tcps_keeptimeo++);
 		if (tp->t_state < TCPS_ESTABLISHED)
 			goto dropit;
 
 /*		if (tp->t_socket->so_options & SO_KEEPALIVE && */
-		if ((so_options) && tp->t_state <= TCPS_CLOSE_WAIT) {
-		    	if (tp->t_idle >= tcp_keepidle + tcp_maxidle)
+		if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) {
+		    	if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE)
 				goto dropit;
 			/*
 			 * Send a packet designed to force a response
@@ -299,7 +296,7 @@
 			 * by the protocol spec, this requires the
 			 * correspondent TCP to respond.
 			 */
-			tcpstat.tcps_keepprobe++;
+			STAT(tcpstat.tcps_keepprobe++);
 #ifdef TCP_COMPAT_42
 			/*
 			 * The keepalive packet must have nonzero length
@@ -311,13 +308,13 @@
 			tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
 			    tp->rcv_nxt, tp->snd_una - 1, 0);
 #endif
-			tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
+			tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
 		} else
-			tp->t_timer[TCPT_KEEP] = tcp_keepidle;
+			tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
 		break;
 
 	dropit:
-		tcpstat.tcps_keepdrops++;
+		STAT(tcpstat.tcps_keepdrops++);
 		tp = tcp_drop(tp, 0); /* ETIMEDOUT); */
 		break;
 	}

Modified: trunk/src/host/qemu-neo1973/slirp/tcp_timer.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp_timer.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp_timer.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -126,17 +126,12 @@
 		(tv) = (tvmax); \
 }
 
-extern int tcp_keepidle;		/* time before keepalive probes begin */
-extern int tcp_keepintvl;		/* time between keepalive probes */
-extern int tcp_maxidle;			/* time to drop after starting probes */
-extern int tcp_ttl;			/* time to live for TCP segs */
-extern int tcp_backoff[];
+extern const int tcp_backoff[];
 
 struct tcpcb;
 
 void tcp_fasttimo _P((void));
 void tcp_slowtimo _P((void));
 void tcp_canceltimers _P((struct tcpcb *));
-struct tcpcb * tcp_timers _P((register struct tcpcb *, int));
 
 #endif

Modified: trunk/src/host/qemu-neo1973/slirp/tcp_var.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tcp_var.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tcp_var.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -185,6 +185,7 @@
 #endif
 #define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t))
 
+#ifdef LOG_ENABLED
 /*
  * TCP statistics.
  * Many of these should be kept per connection,
@@ -247,6 +248,8 @@
 };
 
 extern struct	tcpstat tcpstat;	/* tcp statistics */
+#endif
+
 extern u_int32_t	tcp_now;		/* for RFC 1323 timestamps */
 
 #endif

Modified: trunk/src/host/qemu-neo1973/slirp/tftp.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tftp.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/tftp.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -34,7 +34,7 @@
     int timestamp;
 };
 
-struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
+static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
 
 const char *tftp_prefix;
 
@@ -143,7 +143,7 @@
 
     memset(m->m_data, 0, m->m_size);
 
-    m->m_data += if_maxlinkhdr;
+    m->m_data += IF_MAXLINKHDR;
     tp = (void *)m->m_data;
     m->m_data += sizeof(struct udpiphdr);
 
@@ -183,7 +183,7 @@
 
   memset(m->m_data, 0, m->m_size);
 
-  m->m_data += if_maxlinkhdr;
+  m->m_data += IF_MAXLINKHDR;
   tp = (void *)m->m_data;
   m->m_data += sizeof(struct udpiphdr);
 
@@ -230,7 +230,7 @@
 
   memset(m->m_data, 0, m->m_size);
 
-  m->m_data += if_maxlinkhdr;
+  m->m_data += IF_MAXLINKHDR;
   tp = (void *)m->m_data;
   m->m_data += sizeof(struct udpiphdr);
 

Modified: trunk/src/host/qemu-neo1973/slirp/udp.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/udp.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/udp.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -45,18 +45,23 @@
 #include <slirp.h>
 #include "ip_icmp.h"
 
+#ifdef LOG_ENABLED
 struct udpstat udpstat;
+#endif
 
 struct socket udb;
 
+static u_int8_t udp_tos(struct socket *so);
+static void udp_emu(struct socket *so, struct mbuf *m);
+
 /*
  * UDP protocol implementation.
  * Per RFC 768, August, 1980.
  */
 #ifndef	COMPAT_42
-int	udpcksum = 1;
+#define UDPCKSUM 1
 #else
-int	udpcksum = 0;		/* XXX */
+#define UDPCKSUM 0 /* XXX */
 #endif
 
 struct	socket *udp_last_so = &udb;
@@ -86,7 +91,7 @@
 	DEBUG_ARG("m = %lx", (long)m);
 	DEBUG_ARG("iphlen = %d", iphlen);
 
-	udpstat.udps_ipackets++;
+	STAT(udpstat.udps_ipackets++);
 
 	/*
 	 * Strip IP options, if any; should skip this,
@@ -113,7 +118,7 @@
 
 	if (ip->ip_len != len) {
 		if (len > ip->ip_len) {
-			udpstat.udps_badlen++;
+			STAT(udpstat.udps_badlen++);
 			goto bad;
 		}
 		m_adj(m, len - ip->ip_len);
@@ -130,7 +135,7 @@
 	/*
 	 * Checksum extended UDP header and data.
 	 */
-	if (udpcksum && uh->uh_sum) {
+	if (UDPCKSUM && uh->uh_sum) {
 	  ((struct ipovly *)ip)->ih_next = 0;
 	  ((struct ipovly *)ip)->ih_prev = 0;
 	  ((struct ipovly *)ip)->ih_x1 = 0;
@@ -140,7 +145,7 @@
 	   * if (uh->uh_sum) {
 	   */
 	  if(cksum(m, len + sizeof(struct ip))) {
-	    udpstat.udps_badsum++;
+	    STAT(udpstat.udps_badsum++);
 	    goto bad;
 	  }
 	}
@@ -181,7 +186,7 @@
 		if (tmp == &udb) {
 		  so = NULL;
 		} else {
-		  udpstat.udpps_pcbcachemiss++;
+		  STAT(udpstat.udpps_pcbcachemiss++);
 		  udp_last_so = so;
 		}
 	}
@@ -290,16 +295,16 @@
 	 * Stuff checksum and output datagram.
 	 */
 	ui->ui_sum = 0;
-	if (udpcksum) {
+	if (UDPCKSUM) {
 	    if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
 		ui->ui_sum = 0xffff;
 	}
 	((struct ip *)ui)->ip_len = m->m_len;
 
-	((struct ip *)ui)->ip_ttl = ip_defttl;
+	((struct ip *)ui)->ip_ttl = IPDEFTTL;
 	((struct ip *)ui)->ip_tos = iptos;
 
-	udpstat.udps_opackets++;
+	STAT(udpstat.udps_opackets++);
 
 	error = ip_output(so, m);
 
@@ -367,7 +372,7 @@
 	sofree(so);
 }
 
-struct tos_t udptos[] = {
+static const struct tos_t udptos[] = {
 	{0, 53, IPTOS_LOWDELAY, 0},			/* DNS */
 	{517, 517, IPTOS_LOWDELAY, EMU_TALK},	/* talk */
 	{518, 518, IPTOS_LOWDELAY, EMU_NTALK},	/* ntalk */
@@ -375,9 +380,8 @@
 	{0, 0, 0, 0}
 };
 
-u_int8_t
-udp_tos(so)
-	struct socket *so;
+static u_int8_t
+udp_tos(struct socket *so)
 {
 	int i = 0;
 
@@ -400,10 +404,8 @@
 /*
  * Here, talk/ytalk/ntalk requests must be emulated
  */
-void
-udp_emu(so, m)
-	struct socket *so;
-	struct mbuf *m;
+static void
+udp_emu(struct socket *so, struct mbuf *m)
 {
 	struct sockaddr_in addr;
         int addrlen = sizeof(addr);

Modified: trunk/src/host/qemu-neo1973/slirp/udp.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/udp.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/slirp/udp.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -72,6 +72,7 @@
 #define ui_ulen         ui_u.uh_ulen
 #define ui_sum          ui_u.uh_sum
 
+#ifdef LOG_ENABLED
 struct udpstat {
 	                                /* input statistics: */
 	        u_long  udps_ipackets;          /* total input packets */
@@ -85,6 +86,7 @@
 	                                /* output statistics: */
 	        u_long  udps_opackets;          /* total output packets */
 };
+#endif
 
 /*
  * Names for UDP sysctl objects
@@ -92,7 +94,10 @@
 #define UDPCTL_CHECKSUM         1       /* checksum UDP packets */
 #define UDPCTL_MAXID            2
 
+#ifdef LOG_ENABLED
 extern struct udpstat udpstat;
+#endif
+
 extern struct socket udb;
 struct mbuf;
 
@@ -101,8 +106,6 @@
 int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *));
 int udp_attach _P((struct socket *));
 void udp_detach _P((struct socket *));
-u_int8_t udp_tos _P((struct socket *));
-void udp_emu _P((struct socket *, struct mbuf *));
 struct socket * udp_listen _P((u_int, u_int32_t, u_int, int));
 int udp_output2(struct socket *so, struct mbuf *m,
                 struct sockaddr_in *saddr, struct sockaddr_in *daddr,

Modified: trunk/src/host/qemu-neo1973/softmmu_exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/softmmu_exec.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/softmmu_exec.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,10 +1,16 @@
 /* Common softmmu definitions and inline routines.  */
 
-#define ldul_user ldl_user
-#define ldul_kernel ldl_kernel
+/* XXX: find something cleaner.
+ * Furthermore, this is false for 64 bits targets
+ */
+#define ldul_user       ldl_user
+#define ldul_kernel     ldl_kernel
+#define ldul_hypv       ldl_hypv
+#define ldul_executive  ldl_executive
+#define ldul_supervisor ldl_supervisor
 
 #define ACCESS_TYPE 0
-#define MEMSUFFIX _kernel
+#define MEMSUFFIX MMU_MODE0_SUFFIX
 #define DATA_SIZE 1
 #include "softmmu_header.h"
 
@@ -20,7 +26,7 @@
 #undef MEMSUFFIX
 
 #define ACCESS_TYPE 1
-#define MEMSUFFIX _user
+#define MEMSUFFIX MMU_MODE1_SUFFIX
 #define DATA_SIZE 1
 #include "softmmu_header.h"
 
@@ -35,8 +41,50 @@
 #undef ACCESS_TYPE
 #undef MEMSUFFIX
 
+#if (NB_MMU_MODES >= 3)
+
+#define ACCESS_TYPE 2
+#define MEMSUFFIX MMU_MODE2_SUFFIX
+#define DATA_SIZE 1
+#include "softmmu_header.h"
+
+#define DATA_SIZE 2
+#include "softmmu_header.h"
+
+#define DATA_SIZE 4
+#include "softmmu_header.h"
+
+#define DATA_SIZE 8
+#include "softmmu_header.h"
+#undef ACCESS_TYPE
+#undef MEMSUFFIX
+
+#if (NB_MMU_MODES >= 4)
+
+#define ACCESS_TYPE 3
+#define MEMSUFFIX MMU_MODE3_SUFFIX
+#define DATA_SIZE 1
+#include "softmmu_header.h"
+
+#define DATA_SIZE 2
+#include "softmmu_header.h"
+
+#define DATA_SIZE 4
+#include "softmmu_header.h"
+
+#define DATA_SIZE 8
+#include "softmmu_header.h"
+#undef ACCESS_TYPE
+#undef MEMSUFFIX
+
+#if (NB_MMU_MODES > 4)
+#error "NB_MMU_MODES > 4 is not supported for now"
+#endif /* (NB_MMU_MODES > 4) */
+#endif /* (NB_MMU_MODES == 4) */
+#endif /* (NB_MMU_MODES >= 3) */
+
 /* these access are slower, they must be as rare as possible */
-#define ACCESS_TYPE 2
+#define ACCESS_TYPE (NB_MMU_MODES)
 #define MEMSUFFIX _data
 #define DATA_SIZE 1
 #include "softmmu_header.h"

Modified: trunk/src/host/qemu-neo1973/softmmu_header.h
===================================================================
--- trunk/src/host/qemu-neo1973/softmmu_header.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/softmmu_header.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -39,60 +39,19 @@
 #error unsupported data size
 #endif
 
-#if ACCESS_TYPE == 0
+#if ACCESS_TYPE < (NB_MMU_MODES)
 
-#define CPU_MEM_INDEX 0
+#define CPU_MMU_INDEX ACCESS_TYPE
 #define MMUSUFFIX _mmu
 
-#elif ACCESS_TYPE == 1
+#elif ACCESS_TYPE == (NB_MMU_MODES)
 
-#define CPU_MEM_INDEX 1
+#define CPU_MMU_INDEX (cpu_mmu_index(env))
 #define MMUSUFFIX _mmu
 
-#elif ACCESS_TYPE == 2
+#elif ACCESS_TYPE == (NB_MMU_MODES + 1)
 
-#ifdef TARGET_I386
-#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
-#elif defined (TARGET_PPC)
-#define CPU_MEM_INDEX (msr_pr)
-#elif defined (TARGET_MIPS)
-#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
-#elif defined (TARGET_SPARC)
-#define CPU_MEM_INDEX ((env->psrs) == 0)
-#elif defined (TARGET_ARM)
-#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)
-#elif defined (TARGET_M68K)
-#define CPU_MEM_INDEX ((env->sr & SR_S) == 0)
-#else
-#error unsupported CPU
-#endif
-#define MMUSUFFIX _mmu
-
-#elif ACCESS_TYPE == 3
-
-#ifdef TARGET_I386
-#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
-#elif defined (TARGET_PPC)
-#define CPU_MEM_INDEX (msr_pr)
-#elif defined (TARGET_MIPS)
-#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
-#elif defined (TARGET_SPARC)
-#define CPU_MEM_INDEX ((env->psrs) == 0)
-#elif defined (TARGET_ARM)
-#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)
-#elif defined (TARGET_M68K)
-#define CPU_MEM_INDEX ((env->sr & SR_S) == 0)
-#else
-#error unsupported CPU
-#endif
+#define CPU_MMU_INDEX (cpu_mmu_index(env))
 #define MMUSUFFIX _cmmu
 
 #else
@@ -105,18 +64,18 @@
 #define RES_TYPE int
 #endif
 
-#if ACCESS_TYPE == 3
+#if ACCESS_TYPE == (NB_MMU_MODES + 1)
 #define ADDR_READ addr_code
 #else
 #define ADDR_READ addr_read
 #endif
 
 DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
-                                                         int is_user);
-void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int is_user);
+                                                         int mmu_idx);
+void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int mmu_idx);
 
 #if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
-    (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU)
+    (ACCESS_TYPE < NB_MMU_MODES) && defined(ASM_SOFTMMU)
 
 #define CPU_TLB_ENTRY_BITS 4
 
@@ -155,8 +114,8 @@
                   "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
                   "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
                   "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
-                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
-                  "i" (CPU_MEM_INDEX),
+                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)),
+                  "i" (CPU_MMU_INDEX),
                   "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
                   : "%eax", "%ecx", "%edx", "memory", "cc");
     return res;
@@ -202,8 +161,8 @@
                   "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
                   "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
                   "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
-                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
-                  "i" (CPU_MEM_INDEX),
+                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)),
+                  "i" (CPU_MMU_INDEX),
                   "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
                   : "%eax", "%ecx", "%edx", "memory", "cc");
     return res;
@@ -254,8 +213,8 @@
                   "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
                   "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
                   "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
-                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_write)),
-                  "i" (CPU_MEM_INDEX),
+                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_write)),
+                  "i" (CPU_MMU_INDEX),
                   "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
                   : "%eax", "%ecx", "%edx", "memory", "cc");
 }
@@ -270,16 +229,16 @@
     RES_TYPE res;
     target_ulong addr;
     unsigned long physaddr;
-    int is_user;
+    int mmu_idx;
 
     addr = ptr;
     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    is_user = CPU_MEM_INDEX;
-    if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ !=
+    mmu_idx = CPU_MMU_INDEX;
+    if (__builtin_expect(env->tlb_table[mmu_idx][index].ADDR_READ !=
                          (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
-        res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
+        res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
     } else {
-        physaddr = addr + env->tlb_table[is_user][index].addend;
+        physaddr = addr + env->tlb_table[mmu_idx][index].addend;
         res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
     }
     return res;
@@ -291,23 +250,23 @@
     int res, index;
     target_ulong addr;
     unsigned long physaddr;
-    int is_user;
+    int mmu_idx;
 
     addr = ptr;
     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    is_user = CPU_MEM_INDEX;
-    if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ !=
+    mmu_idx = CPU_MMU_INDEX;
+    if (__builtin_expect(env->tlb_table[mmu_idx][index].ADDR_READ !=
                          (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
-        res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
+        res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
     } else {
-        physaddr = addr + env->tlb_table[is_user][index].addend;
+        physaddr = addr + env->tlb_table[mmu_idx][index].addend;
         res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
     }
     return res;
 }
 #endif
 
-#if ACCESS_TYPE != 3
+#if ACCESS_TYPE != (NB_MMU_MODES + 1)
 
 /* generic store macro */
 
@@ -316,25 +275,25 @@
     int index;
     target_ulong addr;
     unsigned long physaddr;
-    int is_user;
+    int mmu_idx;
 
     addr = ptr;
     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    is_user = CPU_MEM_INDEX;
-    if (__builtin_expect(env->tlb_table[is_user][index].addr_write !=
+    mmu_idx = CPU_MMU_INDEX;
+    if (__builtin_expect(env->tlb_table[mmu_idx][index].addr_write !=
                          (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
-        glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, is_user);
+        glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, mmu_idx);
     } else {
-        physaddr = addr + env->tlb_table[is_user][index].addend;
+        physaddr = addr + env->tlb_table[mmu_idx][index].addend;
         glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
     }
 }
 
-#endif /* ACCESS_TYPE != 3 */
+#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
 
 #endif /* !asm */
 
-#if ACCESS_TYPE != 3
+#if ACCESS_TYPE != (NB_MMU_MODES + 1)
 
 #if DATA_SIZE == 8
 static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
@@ -380,7 +339,7 @@
 }
 #endif /* DATA_SIZE == 4 */
 
-#endif /* ACCESS_TYPE != 3 */
+#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
 
 #undef RES_TYPE
 #undef DATA_TYPE
@@ -388,6 +347,6 @@
 #undef SUFFIX
 #undef USUFFIX
 #undef DATA_SIZE
-#undef CPU_MEM_INDEX
+#undef CPU_MMU_INDEX
 #undef MMUSUFFIX
 #undef ADDR_READ

Modified: trunk/src/host/qemu-neo1973/softmmu_template.h
===================================================================
--- trunk/src/host/qemu-neo1973/softmmu_template.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/softmmu_template.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -48,7 +48,7 @@
 #endif
 
 static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
-                                                        int is_user,
+                                                        int mmu_idx,
                                                         void *retaddr);
 static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
                                               target_ulong tlb_addr)
@@ -76,7 +76,7 @@
 
 /* handle all cases except unaligned access which span two pages */
 DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
-                                                         int is_user)
+                                                         int mmu_idx)
 {
     DATA_TYPE res;
     int index;
@@ -88,9 +88,9 @@
     /* XXX: could done more in memory macro in a non portable way */
     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  redo:
-    tlb_addr = env->tlb_table[is_user][index].ADDR_READ;
+    tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
     if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
-        physaddr = addr + env->tlb_table[is_user][index].addend;
+        physaddr = addr + env->tlb_table[mmu_idx][index].addend;
         if (tlb_addr & ~TARGET_PAGE_MASK) {
             /* IO access */
             if ((addr & (DATA_SIZE - 1)) != 0)
@@ -101,16 +101,16 @@
         do_unaligned_access:
             retaddr = GETPC();
 #ifdef ALIGNED_ONLY
-            do_unaligned_access(addr, READ_ACCESS_TYPE, is_user, retaddr);
+            do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
 #endif
             res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr,
-                                                         is_user, retaddr);
+                                                         mmu_idx, retaddr);
         } else {
             /* unaligned/aligned access in the same page */
 #ifdef ALIGNED_ONLY
             if ((addr & (DATA_SIZE - 1)) != 0) {
                 retaddr = GETPC();
-                do_unaligned_access(addr, READ_ACCESS_TYPE, is_user, retaddr);
+                do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
             }
 #endif
             res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)physaddr);
@@ -120,9 +120,9 @@
         retaddr = GETPC();
 #ifdef ALIGNED_ONLY
         if ((addr & (DATA_SIZE - 1)) != 0)
-            do_unaligned_access(addr, READ_ACCESS_TYPE, is_user, retaddr);
+            do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
 #endif
-        tlb_fill(addr, READ_ACCESS_TYPE, is_user, retaddr);
+        tlb_fill(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
         goto redo;
     }
     return res;
@@ -130,7 +130,7 @@
 
 /* handle all unaligned cases */
 static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
-                                                        int is_user,
+                                                        int mmu_idx,
                                                         void *retaddr)
 {
     DATA_TYPE res, res1, res2;
@@ -140,9 +140,9 @@
 
     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  redo:
-    tlb_addr = env->tlb_table[is_user][index].ADDR_READ;
+    tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
     if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
-        physaddr = addr + env->tlb_table[is_user][index].addend;
+        physaddr = addr + env->tlb_table[mmu_idx][index].addend;
         if (tlb_addr & ~TARGET_PAGE_MASK) {
             /* IO access */
             if ((addr & (DATA_SIZE - 1)) != 0)
@@ -154,9 +154,9 @@
             addr1 = addr & ~(DATA_SIZE - 1);
             addr2 = addr1 + DATA_SIZE;
             res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr1,
-                                                          is_user, retaddr);
+                                                          mmu_idx, retaddr);
             res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr2,
-                                                          is_user, retaddr);
+                                                          mmu_idx, retaddr);
             shift = (addr & (DATA_SIZE - 1)) * 8;
 #ifdef TARGET_WORDS_BIGENDIAN
             res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
@@ -170,7 +170,7 @@
         }
     } else {
         /* the page is not in the TLB : fill it */
-        tlb_fill(addr, READ_ACCESS_TYPE, is_user, retaddr);
+        tlb_fill(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
         goto redo;
     }
     return res;
@@ -180,7 +180,7 @@
 
 static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
                                                    DATA_TYPE val,
-                                                   int is_user,
+                                                   int mmu_idx,
                                                    void *retaddr);
 
 static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
@@ -211,7 +211,7 @@
 
 void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
                                                     DATA_TYPE val,
-                                                    int is_user)
+                                                    int mmu_idx)
 {
     target_phys_addr_t physaddr;
     target_ulong tlb_addr;
@@ -220,9 +220,9 @@
 
     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  redo:
-    tlb_addr = env->tlb_table[is_user][index].addr_write;
+    tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
     if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
-        physaddr = addr + env->tlb_table[is_user][index].addend;
+        physaddr = addr + env->tlb_table[mmu_idx][index].addend;
         if (tlb_addr & ~TARGET_PAGE_MASK) {
             /* IO access */
             if ((addr & (DATA_SIZE - 1)) != 0)
@@ -233,16 +233,16 @@
         do_unaligned_access:
             retaddr = GETPC();
 #ifdef ALIGNED_ONLY
-            do_unaligned_access(addr, 1, is_user, retaddr);
+            do_unaligned_access(addr, 1, mmu_idx, retaddr);
 #endif
             glue(glue(slow_st, SUFFIX), MMUSUFFIX)(addr, val,
-                                                   is_user, retaddr);
+                                                   mmu_idx, retaddr);
         } else {
             /* aligned/unaligned access in the same page */
 #ifdef ALIGNED_ONLY
             if ((addr & (DATA_SIZE - 1)) != 0) {
                 retaddr = GETPC();
-                do_unaligned_access(addr, 1, is_user, retaddr);
+                do_unaligned_access(addr, 1, mmu_idx, retaddr);
             }
 #endif
             glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)physaddr, val);
@@ -252,9 +252,9 @@
         retaddr = GETPC();
 #ifdef ALIGNED_ONLY
         if ((addr & (DATA_SIZE - 1)) != 0)
-            do_unaligned_access(addr, 1, is_user, retaddr);
+            do_unaligned_access(addr, 1, mmu_idx, retaddr);
 #endif
-        tlb_fill(addr, 1, is_user, retaddr);
+        tlb_fill(addr, 1, mmu_idx, retaddr);
         goto redo;
     }
 }
@@ -262,7 +262,7 @@
 /* handles all unaligned cases */
 static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
                                                    DATA_TYPE val,
-                                                   int is_user,
+                                                   int mmu_idx,
                                                    void *retaddr)
 {
     target_phys_addr_t physaddr;
@@ -271,9 +271,9 @@
 
     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  redo:
-    tlb_addr = env->tlb_table[is_user][index].addr_write;
+    tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
     if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
-        physaddr = addr + env->tlb_table[is_user][index].addend;
+        physaddr = addr + env->tlb_table[mmu_idx][index].addend;
         if (tlb_addr & ~TARGET_PAGE_MASK) {
             /* IO access */
             if ((addr & (DATA_SIZE - 1)) != 0)
@@ -285,10 +285,10 @@
             for(i = 0;i < DATA_SIZE; i++) {
 #ifdef TARGET_WORDS_BIGENDIAN
                 glue(slow_stb, MMUSUFFIX)(addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
-                                          is_user, retaddr);
+                                          mmu_idx, retaddr);
 #else
                 glue(slow_stb, MMUSUFFIX)(addr + i, val >> (i * 8),
-                                          is_user, retaddr);
+                                          mmu_idx, retaddr);
 #endif
             }
         } else {
@@ -297,7 +297,7 @@
         }
     } else {
         /* the page is not in the TLB : fill it */
-        tlb_fill(addr, 1, is_user, retaddr);
+        tlb_fill(addr, 1, mmu_idx, retaddr);
         goto redo;
     }
 }

Modified: trunk/src/host/qemu-neo1973/sparc-dis.c
===================================================================
--- trunk/src/host/qemu-neo1973/sparc-dis.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/sparc-dis.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -88,21 +88,21 @@
 
 struct sparc_opcode {
   const char *name;
-  unsigned long match;	/* Bits that must be set. */
-  unsigned long lose;	/* Bits that must not be set. */
+  unsigned long match;  /* Bits that must be set. */
+  unsigned long lose;   /* Bits that must not be set. */
   const char *args;
   /* This was called "delayed" in versions before the flags. */
   char flags;
-  short architecture;	/* Bitmask of sparc_opcode_arch_val's.  */
+  short architecture;   /* Bitmask of sparc_opcode_arch_val's.  */
 };
 
-#define	F_DELAYED	1	/* Delayed branch */
-#define	F_ALIAS		2	/* Alias for a "real" instruction */
-#define	F_UNBR		4	/* Unconditional branch */
-#define	F_CONDBR	8	/* Conditional branch */
-#define	F_JSR		16	/* Subroutine call */
-#define F_FLOAT		32	/* Floating point instruction (not a branch) */
-#define F_FBR		64	/* Floating point branch */
+#define F_DELAYED       1       /* Delayed branch */
+#define F_ALIAS         2       /* Alias for a "real" instruction */
+#define F_UNBR          4       /* Unconditional branch */
+#define F_CONDBR        8       /* Conditional branch */
+#define F_JSR           16      /* Subroutine call */
+#define F_FLOAT         32      /* Floating point instruction (not a branch) */
+#define F_FBR           64      /* Floating point branch */
 /* FIXME: Add F_ANACHRONISTIC flag for v9.  */
 
 /*
@@ -117,104 +117,104 @@
 instruction.
 
 Kinds of operands:
-	#	Number used by optimizer.	It is ignored.
-	1	rs1 register.
-	2	rs2 register.
-	d	rd register.
-	e	frs1 floating point register.
-	v	frs1 floating point register (double/even).
-	V	frs1 floating point register (quad/multiple of 4).
-	f	frs2 floating point register.
-	B	frs2 floating point register (double/even).
-	R	frs2 floating point register (quad/multiple of 4).
-	g	frsd floating point register.
-	H	frsd floating point register (double/even).
-	J	frsd floating point register (quad/multiple of 4).
-	b	crs1 coprocessor register
-	c	crs2 coprocessor register
-	D	crsd coprocessor register
-	m	alternate space register (asr) in rd
-	M	alternate space register (asr) in rs1
-	h	22 high bits.
-	X	5 bit unsigned immediate
-	Y	6 bit unsigned immediate
-	3	SIAM mode (3 bits). (v9b)
-	K	MEMBAR mask (7 bits). (v9)
-	j	10 bit Immediate. (v9)
-	I	11 bit Immediate. (v9)
-	i	13 bit Immediate.
-	n	22 bit immediate.
-	k	2+14 bit PC relative immediate. (v9)
-	G	19 bit PC relative immediate. (v9)
-	l	22 bit PC relative immediate.
-	L	30 bit PC relative immediate.
-	a	Annul.	The annul bit is set.
-	A	Alternate address space. Stored as 8 bits.
-	C	Coprocessor state register.
-	F	floating point state register.
-	p	Processor state register.
-	N	Branch predict clear ",pn" (v9)
-	T	Branch predict set ",pt" (v9)
-	z	%icc. (v9)
-	Z	%xcc. (v9)
-	q	Floating point queue.
-	r	Single register that is both rs1 and rd.
-	O	Single register that is both rs2 and rd.
-	Q	Coprocessor queue.
-	S	Special case.
-	t	Trap base register.
-	w	Window invalid mask register.
-	y	Y register.
-	u	sparclet coprocessor registers in rd position
-	U	sparclet coprocessor registers in rs1 position
-	E	%ccr. (v9)
-	s	%fprs. (v9)
-	P	%pc.  (v9)
-	W	%tick.	(v9)
-	o	%asi. (v9)
-	6	%fcc0. (v9)
-	7	%fcc1. (v9)
-	8	%fcc2. (v9)
-	9	%fcc3. (v9)
-	!	Privileged Register in rd (v9)
-	?	Privileged Register in rs1 (v9)
-	*	Prefetch function constant. (v9)
-	x	OPF field (v9 impdep).
-	0	32/64 bit immediate for set or setx (v9) insns
-	_	Ancillary state register in rd (v9a)
-	/	Ancillary state register in rs1 (v9a)
+        #       Number used by optimizer.       It is ignored.
+        1       rs1 register.
+        2       rs2 register.
+        d       rd register.
+        e       frs1 floating point register.
+        v       frs1 floating point register (double/even).
+        V       frs1 floating point register (quad/multiple of 4).
+        f       frs2 floating point register.
+        B       frs2 floating point register (double/even).
+        R       frs2 floating point register (quad/multiple of 4).
+        g       frsd floating point register.
+        H       frsd floating point register (double/even).
+        J       frsd floating point register (quad/multiple of 4).
+        b       crs1 coprocessor register
+        c       crs2 coprocessor register
+        D       crsd coprocessor register
+        m       alternate space register (asr) in rd
+        M       alternate space register (asr) in rs1
+        h       22 high bits.
+        X       5 bit unsigned immediate
+        Y       6 bit unsigned immediate
+        3       SIAM mode (3 bits). (v9b)
+        K       MEMBAR mask (7 bits). (v9)
+        j       10 bit Immediate. (v9)
+        I       11 bit Immediate. (v9)
+        i       13 bit Immediate.
+        n       22 bit immediate.
+        k       2+14 bit PC relative immediate. (v9)
+        G       19 bit PC relative immediate. (v9)
+        l       22 bit PC relative immediate.
+        L       30 bit PC relative immediate.
+        a       Annul.  The annul bit is set.
+        A       Alternate address space. Stored as 8 bits.
+        C       Coprocessor state register.
+        F       floating point state register.
+        p       Processor state register.
+        N       Branch predict clear ",pn" (v9)
+        T       Branch predict set ",pt" (v9)
+        z       %icc. (v9)
+        Z       %xcc. (v9)
+        q       Floating point queue.
+        r       Single register that is both rs1 and rd.
+        O       Single register that is both rs2 and rd.
+        Q       Coprocessor queue.
+        S       Special case.
+        t       Trap base register.
+        w       Window invalid mask register.
+        y       Y register.
+        u       sparclet coprocessor registers in rd position
+        U       sparclet coprocessor registers in rs1 position
+        E       %ccr. (v9)
+        s       %fprs. (v9)
+        P       %pc.  (v9)
+        W       %tick.  (v9)
+        o       %asi. (v9)
+        6       %fcc0. (v9)
+        7       %fcc1. (v9)
+        8       %fcc2. (v9)
+        9       %fcc3. (v9)
+        !       Privileged Register in rd (v9)
+        ?       Privileged Register in rs1 (v9)
+        *       Prefetch function constant. (v9)
+        x       OPF field (v9 impdep).
+        0       32/64 bit immediate for set or setx (v9) insns
+        _       Ancillary state register in rd (v9a)
+        /       Ancillary state register in rs1 (v9a)
 
 The following chars are unused: (note: ,[] are used as punctuation)
 [45]
 
 */
 
-#define OP2(x)		(((x)&0x7) << 22) /* op2 field of format2 insns */
-#define OP3(x)		(((x)&0x3f) << 19) /* op3 field of format3 insns */
-#define OP(x)		((unsigned)((x)&0x3) << 30) /* op field of all insns */
-#define OPF(x)		(((x)&0x1ff) << 5) /* opf field of float insns */
-#define OPF_LOW5(x)	OPF((x)&0x1f) /* v9 */
-#define F3F(x, y, z)	(OP(x) | OP3(y) | OPF(z)) /* format3 float insns */
-#define F3I(x)		(((x)&0x1) << 13) /* immediate field of format 3 insns */
-#define F2(x, y)	(OP(x) | OP2(y)) /* format 2 insns */
-#define F3(x, y, z)	(OP(x) | OP3(y) | F3I(z)) /* format3 insns */
-#define F1(x)		(OP(x))
-#define DISP30(x)	((x)&0x3fffffff)
-#define ASI(x)		(((x)&0xff) << 5) /* asi field of format3 insns */
-#define RS2(x)		((x)&0x1f) /* rs2 field */
-#define SIMM13(x)	((x)&0x1fff) /* simm13 field */
-#define RD(x)		(((x)&0x1f) << 25) /* destination register field */
-#define RS1(x)		(((x)&0x1f) << 14) /* rs1 field */
-#define ASI_RS2(x)	(SIMM13(x))
-#define MEMBAR(x)	((x)&0x7f)
-#define SLCPOP(x)	(((x)&0x7f) << 6) /* sparclet cpop */
+#define OP2(x)          (((x)&0x7) << 22) /* op2 field of format2 insns */
+#define OP3(x)          (((x)&0x3f) << 19) /* op3 field of format3 insns */
+#define OP(x)           ((unsigned)((x)&0x3) << 30) /* op field of all insns */
+#define OPF(x)          (((x)&0x1ff) << 5) /* opf field of float insns */
+#define OPF_LOW5(x)     OPF((x)&0x1f) /* v9 */
+#define F3F(x, y, z)    (OP(x) | OP3(y) | OPF(z)) /* format3 float insns */
+#define F3I(x)          (((x)&0x1) << 13) /* immediate field of format 3 insns */
+#define F2(x, y)        (OP(x) | OP2(y)) /* format 2 insns */
+#define F3(x, y, z)     (OP(x) | OP3(y) | F3I(z)) /* format3 insns */
+#define F1(x)           (OP(x))
+#define DISP30(x)       ((x)&0x3fffffff)
+#define ASI(x)          (((x)&0xff) << 5) /* asi field of format3 insns */
+#define RS2(x)          ((x)&0x1f) /* rs2 field */
+#define SIMM13(x)       ((x)&0x1fff) /* simm13 field */
+#define RD(x)           (((x)&0x1f) << 25) /* destination register field */
+#define RS1(x)          (((x)&0x1f) << 14) /* rs1 field */
+#define ASI_RS2(x)      (SIMM13(x))
+#define MEMBAR(x)       ((x)&0x7f)
+#define SLCPOP(x)       (((x)&0x7f) << 6) /* sparclet cpop */
 
-#define ANNUL	(1<<29)
-#define BPRED	(1<<19)	/* v9 */
-#define	IMMED	F3I(1)
-#define RD_G0	RD(~0)
-#define	RS1_G0	RS1(~0)
-#define	RS2_G0	RS2(~0)
+#define ANNUL   (1<<29)
+#define BPRED   (1<<19) /* v9 */
+#define IMMED   F3I(1)
+#define RD_G0   RD(~0)
+#define RS1_G0  RS1(~0)
+#define RS2_G0  RS2(~0)
 
 extern const struct sparc_opcode sparc_opcodes[];
 extern const int sparc_num_opcodes;
@@ -229,43 +229,43 @@
 extern const char *sparc_decode_sparclet_cpreg PARAMS ((int));
 
 /* Some defines to make life easy.  */
-#define MASK_V6		SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V6)
-#define MASK_V7		SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V7)
-#define MASK_V8		SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8)
-#define MASK_SPARCLET	SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLET)
-#define MASK_SPARCLITE	SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLITE)
-#define MASK_V9		SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9)
-#define MASK_V9A	SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9A)
-#define MASK_V9B	SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9B)
+#define MASK_V6         SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V6)
+#define MASK_V7         SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V7)
+#define MASK_V8         SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8)
+#define MASK_SPARCLET   SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLET)
+#define MASK_SPARCLITE  SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLITE)
+#define MASK_V9         SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9)
+#define MASK_V9A        SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9A)
+#define MASK_V9B        SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9B)
 
 /* Bit masks of architectures supporting the insn.  */
 
-#define v6		(MASK_V6 | MASK_V7 | MASK_V8 | MASK_SPARCLET \
-			 | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B)
+#define v6              (MASK_V6 | MASK_V7 | MASK_V8 | MASK_SPARCLET \
+                         | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B)
 /* v6 insns not supported on the sparclet */
-#define v6notlet	(MASK_V6 | MASK_V7 | MASK_V8 \
-			 | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B)
-#define v7		(MASK_V7 | MASK_V8 | MASK_SPARCLET \
-			 | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B)
+#define v6notlet        (MASK_V6 | MASK_V7 | MASK_V8 \
+                         | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B)
+#define v7              (MASK_V7 | MASK_V8 | MASK_SPARCLET \
+                         | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B)
 /* Although not all insns are implemented in hardware, sparclite is defined
    to be a superset of v8.  Unimplemented insns trap and are then theoretically
    implemented in software.
    It's not clear that the same is true for sparclet, although the docs
    suggest it is.  Rather than complicating things, the sparclet assembler
    recognizes all v8 insns.  */
-#define v8		(MASK_V8 | MASK_SPARCLET | MASK_SPARCLITE \
-			 | MASK_V9 | MASK_V9A | MASK_V9B)
-#define sparclet	(MASK_SPARCLET)
-#define sparclite	(MASK_SPARCLITE)
-#define v9		(MASK_V9 | MASK_V9A | MASK_V9B)
-#define v9a		(MASK_V9A | MASK_V9B)
-#define v9b		(MASK_V9B)
+#define v8              (MASK_V8 | MASK_SPARCLET | MASK_SPARCLITE \
+                         | MASK_V9 | MASK_V9A | MASK_V9B)
+#define sparclet        (MASK_SPARCLET)
+#define sparclite       (MASK_SPARCLITE)
+#define v9              (MASK_V9 | MASK_V9A | MASK_V9B)
+#define v9a             (MASK_V9A | MASK_V9B)
+#define v9b             (MASK_V9B)
 /* v6 insns not supported by v9 */
-#define v6notv9		(MASK_V6 | MASK_V7 | MASK_V8 \
-			 | MASK_SPARCLET | MASK_SPARCLITE)
+#define v6notv9         (MASK_V6 | MASK_V7 | MASK_V8 \
+                         | MASK_SPARCLET | MASK_SPARCLITE)
 /* v9a instructions which would appear to be aliases to v9's impdep's
    otherwise */
-#define v9notv9a	(MASK_V9)
+#define v9notv9a        (MASK_V9)
 
 /* Table of opcode architectures.
    The order is defined in opcode/sparc.h.  */
@@ -296,959 +296,959 @@
   for (p = &sparc_opcode_archs[0]; p->name; ++p)
     {
       if (strcmp (name, p->name) == 0)
-	return (enum sparc_opcode_arch_val) (p - &sparc_opcode_archs[0]);
+        return (enum sparc_opcode_arch_val) (p - &sparc_opcode_archs[0]);
     }
 
   return SPARC_OPCODE_ARCH_BAD;
 }
 
 /* Branch condition field.  */
-#define COND(x)		(((x)&0xf)<<25)
+#define COND(x)         (((x)&0xf)<<25)
 
 /* v9: Move (MOVcc and FMOVcc) condition field.  */
-#define MCOND(x,i_or_f)	((((i_or_f)&1)<<18)|(((x)>>11)&(0xf<<14))) /* v9 */
+#define MCOND(x,i_or_f) ((((i_or_f)&1)<<18)|(((x)>>11)&(0xf<<14))) /* v9 */
 
 /* v9: Move register (MOVRcc and FMOVRcc) condition field.  */
-#define RCOND(x)	(((x)&0x7)<<10)	/* v9 */
+#define RCOND(x)        (((x)&0x7)<<10) /* v9 */
 
-#define CONDA	(COND(0x8))
-#define CONDCC	(COND(0xd))
-#define CONDCS	(COND(0x5))
-#define CONDE	(COND(0x1))
-#define CONDG	(COND(0xa))
-#define CONDGE	(COND(0xb))
-#define CONDGU	(COND(0xc))
-#define CONDL	(COND(0x3))
-#define CONDLE	(COND(0x2))
-#define CONDLEU	(COND(0x4))
-#define CONDN	(COND(0x0))
-#define CONDNE	(COND(0x9))
-#define CONDNEG	(COND(0x6))
-#define CONDPOS	(COND(0xe))
-#define CONDVC	(COND(0xf))
-#define CONDVS	(COND(0x7))
+#define CONDA   (COND(0x8))
+#define CONDCC  (COND(0xd))
+#define CONDCS  (COND(0x5))
+#define CONDE   (COND(0x1))
+#define CONDG   (COND(0xa))
+#define CONDGE  (COND(0xb))
+#define CONDGU  (COND(0xc))
+#define CONDL   (COND(0x3))
+#define CONDLE  (COND(0x2))
+#define CONDLEU (COND(0x4))
+#define CONDN   (COND(0x0))
+#define CONDNE  (COND(0x9))
+#define CONDNEG (COND(0x6))
+#define CONDPOS (COND(0xe))
+#define CONDVC  (COND(0xf))
+#define CONDVS  (COND(0x7))
 
-#define CONDNZ	CONDNE
-#define CONDZ	CONDE
-#define CONDGEU	CONDCC
-#define CONDLU	CONDCS
+#define CONDNZ  CONDNE
+#define CONDZ   CONDE
+#define CONDGEU CONDCC
+#define CONDLU  CONDCS
 
-#define FCONDA		(COND(0x8))
-#define FCONDE		(COND(0x9))
-#define FCONDG		(COND(0x6))
-#define FCONDGE		(COND(0xb))
-#define FCONDL		(COND(0x4))
-#define FCONDLE		(COND(0xd))
-#define FCONDLG		(COND(0x2))
-#define FCONDN		(COND(0x0))
-#define FCONDNE		(COND(0x1))
-#define FCONDO		(COND(0xf))
-#define FCONDU		(COND(0x7))
-#define FCONDUE		(COND(0xa))
-#define FCONDUG		(COND(0x5))
-#define FCONDUGE	(COND(0xc))
-#define FCONDUL		(COND(0x3))
-#define FCONDULE	(COND(0xe))
+#define FCONDA          (COND(0x8))
+#define FCONDE          (COND(0x9))
+#define FCONDG          (COND(0x6))
+#define FCONDGE         (COND(0xb))
+#define FCONDL          (COND(0x4))
+#define FCONDLE         (COND(0xd))
+#define FCONDLG         (COND(0x2))
+#define FCONDN          (COND(0x0))
+#define FCONDNE         (COND(0x1))
+#define FCONDO          (COND(0xf))
+#define FCONDU          (COND(0x7))
+#define FCONDUE         (COND(0xa))
+#define FCONDUG         (COND(0x5))
+#define FCONDUGE        (COND(0xc))
+#define FCONDUL         (COND(0x3))
+#define FCONDULE        (COND(0xe))
 
-#define FCONDNZ	FCONDNE
-#define FCONDZ	FCONDE
+#define FCONDNZ FCONDNE
+#define FCONDZ  FCONDE
 
-#define ICC (0)	/* v9 */
+#define ICC (0) /* v9 */
 #define XCC (1<<12) /* v9 */
-#define FCC(x)	(((x)&0x3)<<11) /* v9 */
-#define FBFCC(x)	(((x)&0x3)<<20)	/* v9 */
+#define FCC(x)  (((x)&0x3)<<11) /* v9 */
+#define FBFCC(x)        (((x)&0x3)<<20) /* v9 */
 
 /* The order of the opcodes in the table is significant:
 
-	* The assembler requires that all instances of the same mnemonic must
-	be consecutive.	If they aren't, the assembler will bomb at runtime.
+        * The assembler requires that all instances of the same mnemonic must
+        be consecutive. If they aren't, the assembler will bomb at runtime.
 
-	* The disassembler should not care about the order of the opcodes.
+        * The disassembler should not care about the order of the opcodes.
 
 */
 
 /* Entries for commutative arithmetic operations.  */
 /* ??? More entries can make use of this.  */
 #define COMMUTEOP(opcode, op3, arch_mask) \
-{ opcode,	F3(2, op3, 0), F3(~2, ~op3, ~0)|ASI(~0),	"1,2,d", 0, arch_mask }, \
-{ opcode,	F3(2, op3, 1), F3(~2, ~op3, ~1),		"1,i,d", 0, arch_mask }, \
-{ opcode,	F3(2, op3, 1), F3(~2, ~op3, ~1),		"i,1,d", 0, arch_mask }
+{ opcode,       F3(2, op3, 0), F3(~2, ~op3, ~0)|ASI(~0),        "1,2,d", 0, arch_mask }, \
+{ opcode,       F3(2, op3, 1), F3(~2, ~op3, ~1),                "1,i,d", 0, arch_mask }, \
+{ opcode,       F3(2, op3, 1), F3(~2, ~op3, ~1),                "i,1,d", 0, arch_mask }
 
 const struct sparc_opcode sparc_opcodes[] = {
 
-{ "ld",	F3(3, 0x00, 0), F3(~3, ~0x00, ~0),		"[1+2],d", 0, v6 },
-{ "ld",	F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0,	"[1],d", 0, v6 }, /* ld [rs1+%g0],d */
-{ "ld",	F3(3, 0x00, 1), F3(~3, ~0x00, ~1),		"[1+i],d", 0, v6 },
-{ "ld",	F3(3, 0x00, 1), F3(~3, ~0x00, ~1),		"[i+1],d", 0, v6 },
-{ "ld",	F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|RS1_G0,	"[i],d", 0, v6 },
-{ "ld",	F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|SIMM13(~0),	"[1],d", 0, v6 }, /* ld [rs1+0],d */
-{ "ld",	F3(3, 0x20, 0), F3(~3, ~0x20, ~0),		"[1+2],g", 0, v6 },
-{ "ld",	F3(3, 0x20, 0), F3(~3, ~0x20, ~0)|RS2_G0,	"[1],g", 0, v6 }, /* ld [rs1+%g0],d */
-{ "ld",	F3(3, 0x20, 1), F3(~3, ~0x20, ~1),		"[1+i],g", 0, v6 },
-{ "ld",	F3(3, 0x20, 1), F3(~3, ~0x20, ~1),		"[i+1],g", 0, v6 },
-{ "ld",	F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|RS1_G0,	"[i],g", 0, v6 },
-{ "ld",	F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|SIMM13(~0),	"[1],g", 0, v6 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0),              "[1+2],d", 0, v6 },
+{ "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0,       "[1],d", 0, v6 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1),              "[1+i],d", 0, v6 },
+{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1),              "[i+1],d", 0, v6 },
+{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|RS1_G0,       "[i],d", 0, v6 },
+{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|SIMM13(~0),   "[1],d", 0, v6 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x20, 0), F3(~3, ~0x20, ~0),              "[1+2],g", 0, v6 },
+{ "ld", F3(3, 0x20, 0), F3(~3, ~0x20, ~0)|RS2_G0,       "[1],g", 0, v6 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1),              "[1+i],g", 0, v6 },
+{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1),              "[i+1],g", 0, v6 },
+{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|RS1_G0,       "[i],g", 0, v6 },
+{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|SIMM13(~0),   "[1],g", 0, v6 }, /* ld [rs1+0],d */
 
-{ "ld",	F3(3, 0x21, 0), F3(~3, ~0x21, ~0)|RD(~0),	"[1+2],F", 0, v6 },
-{ "ld",	F3(3, 0x21, 0), F3(~3, ~0x21, ~0)|RS2_G0|RD(~0),"[1],F", 0, v6 }, /* ld [rs1+%g0],d */
-{ "ld",	F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RD(~0),	"[1+i],F", 0, v6 },
-{ "ld",	F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RD(~0),	"[i+1],F", 0, v6 },
-{ "ld",	F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RS1_G0|RD(~0),"[i],F", 0, v6 },
-{ "ld",	F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|SIMM13(~0)|RD(~0),"[1],F", 0, v6 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x21, 0), F3(~3, ~0x21, ~0)|RD(~0),       "[1+2],F", 0, v6 },
+{ "ld", F3(3, 0x21, 0), F3(~3, ~0x21, ~0)|RS2_G0|RD(~0),"[1],F", 0, v6 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RD(~0),       "[1+i],F", 0, v6 },
+{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RD(~0),       "[i+1],F", 0, v6 },
+{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RS1_G0|RD(~0),"[i],F", 0, v6 },
+{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|SIMM13(~0)|RD(~0),"[1],F", 0, v6 }, /* ld [rs1+0],d */
 
-{ "ld",	F3(3, 0x30, 0), F3(~3, ~0x30, ~0),		"[1+2],D", 0, v6notv9 },
-{ "ld",	F3(3, 0x30, 0), F3(~3, ~0x30, ~0)|RS2_G0,	"[1],D", 0, v6notv9 }, /* ld [rs1+%g0],d */
-{ "ld",	F3(3, 0x30, 1), F3(~3, ~0x30, ~1),		"[1+i],D", 0, v6notv9 },
-{ "ld",	F3(3, 0x30, 1), F3(~3, ~0x30, ~1),		"[i+1],D", 0, v6notv9 },
-{ "ld",	F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|RS1_G0,	"[i],D", 0, v6notv9 },
-{ "ld",	F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|SIMM13(~0),	"[1],D", 0, v6notv9 }, /* ld [rs1+0],d */
-{ "ld",	F3(3, 0x31, 0), F3(~3, ~0x31, ~0),		"[1+2],C", 0, v6notv9 },
-{ "ld",	F3(3, 0x31, 0), F3(~3, ~0x31, ~0)|RS2_G0,	"[1],C", 0, v6notv9 }, /* ld [rs1+%g0],d */
-{ "ld",	F3(3, 0x31, 1), F3(~3, ~0x31, ~1),		"[1+i],C", 0, v6notv9 },
-{ "ld",	F3(3, 0x31, 1), F3(~3, ~0x31, ~1),		"[i+1],C", 0, v6notv9 },
-{ "ld",	F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|RS1_G0,	"[i],C", 0, v6notv9 },
-{ "ld",	F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|SIMM13(~0),	"[1],C", 0, v6notv9 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0),              "[1+2],D", 0, v6notv9 },
+{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0)|RS2_G0,       "[1],D", 0, v6notv9 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1),              "[1+i],D", 0, v6notv9 },
+{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1),              "[i+1],D", 0, v6notv9 },
+{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|RS1_G0,       "[i],D", 0, v6notv9 },
+{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|SIMM13(~0),   "[1],D", 0, v6notv9 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0),              "[1+2],C", 0, v6notv9 },
+{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0)|RS2_G0,       "[1],C", 0, v6notv9 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1),              "[1+i],C", 0, v6notv9 },
+{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1),              "[i+1],C", 0, v6notv9 },
+{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|RS1_G0,       "[i],C", 0, v6notv9 },
+{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|SIMM13(~0),   "[1],C", 0, v6notv9 }, /* ld [rs1+0],d */
 
 /* The v9 LDUW is the same as the old 'ld' opcode, it is not the same as the
    'ld' pseudo-op in v9.  */
-{ "lduw",	F3(3, 0x00, 0), F3(~3, ~0x00, ~0),		"[1+2],d", F_ALIAS, v9 },
-{ "lduw",	F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0,	"[1],d", F_ALIAS, v9 }, /* ld [rs1+%g0],d */
-{ "lduw",	F3(3, 0x00, 1), F3(~3, ~0x00, ~1),		"[1+i],d", F_ALIAS, v9 },
-{ "lduw",	F3(3, 0x00, 1), F3(~3, ~0x00, ~1),		"[i+1],d", F_ALIAS, v9 },
-{ "lduw",	F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|RS1_G0,	"[i],d", F_ALIAS, v9 },
-{ "lduw",	F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|SIMM13(~0),	"[1],d", F_ALIAS, v9 }, /* ld [rs1+0],d */
+{ "lduw",       F3(3, 0x00, 0), F3(~3, ~0x00, ~0),              "[1+2],d", F_ALIAS, v9 },
+{ "lduw",       F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0,       "[1],d", F_ALIAS, v9 }, /* ld [rs1+%g0],d */
+{ "lduw",       F3(3, 0x00, 1), F3(~3, ~0x00, ~1),              "[1+i],d", F_ALIAS, v9 },
+{ "lduw",       F3(3, 0x00, 1), F3(~3, ~0x00, ~1),              "[i+1],d", F_ALIAS, v9 },
+{ "lduw",       F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|RS1_G0,       "[i],d", F_ALIAS, v9 },
+{ "lduw",       F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|SIMM13(~0),   "[1],d", F_ALIAS, v9 }, /* ld [rs1+0],d */
 
-{ "ldd",	F3(3, 0x03, 0), F3(~3, ~0x03, ~0)|ASI(~0),	"[1+2],d", 0, v6 },
-{ "ldd",	F3(3, 0x03, 0), F3(~3, ~0x03, ~0)|ASI_RS2(~0),	"[1],d", 0, v6 }, /* ldd [rs1+%g0],d */
-{ "ldd",	F3(3, 0x03, 1), F3(~3, ~0x03, ~1),		"[1+i],d", 0, v6 },
-{ "ldd",	F3(3, 0x03, 1), F3(~3, ~0x03, ~1),		"[i+1],d", 0, v6 },
-{ "ldd",	F3(3, 0x03, 1), F3(~3, ~0x03, ~1)|RS1_G0,	"[i],d", 0, v6 },
-{ "ldd",	F3(3, 0x03, 1), F3(~3, ~0x03, ~1)|SIMM13(~0),	"[1],d", 0, v6 }, /* ldd [rs1+0],d */
-{ "ldd",	F3(3, 0x23, 0), F3(~3, ~0x23, ~0)|ASI(~0),	"[1+2],H", 0, v6 },
-{ "ldd",	F3(3, 0x23, 0), F3(~3, ~0x23, ~0)|ASI_RS2(~0),	"[1],H", 0, v6 }, /* ldd [rs1+%g0],d */
-{ "ldd",	F3(3, 0x23, 1), F3(~3, ~0x23, ~1),		"[1+i],H", 0, v6 },
-{ "ldd",	F3(3, 0x23, 1), F3(~3, ~0x23, ~1),		"[i+1],H", 0, v6 },
-{ "ldd",	F3(3, 0x23, 1), F3(~3, ~0x23, ~1)|RS1_G0,	"[i],H", 0, v6 },
-{ "ldd",	F3(3, 0x23, 1), F3(~3, ~0x23, ~1)|SIMM13(~0),	"[1],H", 0, v6 }, /* ldd [rs1+0],d */
+{ "ldd",        F3(3, 0x03, 0), F3(~3, ~0x03, ~0)|ASI(~0),      "[1+2],d", 0, v6 },
+{ "ldd",        F3(3, 0x03, 0), F3(~3, ~0x03, ~0)|ASI_RS2(~0),  "[1],d", 0, v6 }, /* ldd [rs1+%g0],d */
+{ "ldd",        F3(3, 0x03, 1), F3(~3, ~0x03, ~1),              "[1+i],d", 0, v6 },
+{ "ldd",        F3(3, 0x03, 1), F3(~3, ~0x03, ~1),              "[i+1],d", 0, v6 },
+{ "ldd",        F3(3, 0x03, 1), F3(~3, ~0x03, ~1)|RS1_G0,       "[i],d", 0, v6 },
+{ "ldd",        F3(3, 0x03, 1), F3(~3, ~0x03, ~1)|SIMM13(~0),   "[1],d", 0, v6 }, /* ldd [rs1+0],d */
+{ "ldd",        F3(3, 0x23, 0), F3(~3, ~0x23, ~0)|ASI(~0),      "[1+2],H", 0, v6 },
+{ "ldd",        F3(3, 0x23, 0), F3(~3, ~0x23, ~0)|ASI_RS2(~0),  "[1],H", 0, v6 }, /* ldd [rs1+%g0],d */
+{ "ldd",        F3(3, 0x23, 1), F3(~3, ~0x23, ~1),              "[1+i],H", 0, v6 },
+{ "ldd",        F3(3, 0x23, 1), F3(~3, ~0x23, ~1),              "[i+1],H", 0, v6 },
+{ "ldd",        F3(3, 0x23, 1), F3(~3, ~0x23, ~1)|RS1_G0,       "[i],H", 0, v6 },
+{ "ldd",        F3(3, 0x23, 1), F3(~3, ~0x23, ~1)|SIMM13(~0),   "[1],H", 0, v6 }, /* ldd [rs1+0],d */
 
-{ "ldd",	F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI(~0),	"[1+2],D", 0, v6notv9 },
-{ "ldd",	F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI_RS2(~0),	"[1],D", 0, v6notv9 }, /* ldd [rs1+%g0],d */
-{ "ldd",	F3(3, 0x33, 1), F3(~3, ~0x33, ~1),		"[1+i],D", 0, v6notv9 },
-{ "ldd",	F3(3, 0x33, 1), F3(~3, ~0x33, ~1),		"[i+1],D", 0, v6notv9 },
-{ "ldd",	F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|RS1_G0,	"[i],D", 0, v6notv9 },
-{ "ldd",	F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|SIMM13(~0),	"[1],D", 0, v6notv9 }, /* ldd [rs1+0],d */
+{ "ldd",        F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI(~0),      "[1+2],D", 0, v6notv9 },
+{ "ldd",        F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI_RS2(~0),  "[1],D", 0, v6notv9 }, /* ldd [rs1+%g0],d */
+{ "ldd",        F3(3, 0x33, 1), F3(~3, ~0x33, ~1),              "[1+i],D", 0, v6notv9 },
+{ "ldd",        F3(3, 0x33, 1), F3(~3, ~0x33, ~1),              "[i+1],D", 0, v6notv9 },
+{ "ldd",        F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|RS1_G0,       "[i],D", 0, v6notv9 },
+{ "ldd",        F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|SIMM13(~0),   "[1],D", 0, v6notv9 }, /* ldd [rs1+0],d */
 
-{ "ldq",	F3(3, 0x22, 0), F3(~3, ~0x22, ~0)|ASI(~0),	"[1+2],J", 0, v9 },
-{ "ldq",	F3(3, 0x22, 0), F3(~3, ~0x22, ~0)|ASI_RS2(~0),	"[1],J", 0, v9 }, /* ldd [rs1+%g0],d */
-{ "ldq",	F3(3, 0x22, 1), F3(~3, ~0x22, ~1),		"[1+i],J", 0, v9 },
-{ "ldq",	F3(3, 0x22, 1), F3(~3, ~0x22, ~1),		"[i+1],J", 0, v9 },
-{ "ldq",	F3(3, 0x22, 1), F3(~3, ~0x22, ~1)|RS1_G0,	"[i],J", 0, v9 },
-{ "ldq",	F3(3, 0x22, 1), F3(~3, ~0x22, ~1)|SIMM13(~0),	"[1],J", 0, v9 }, /* ldd [rs1+0],d */
+{ "ldq",        F3(3, 0x22, 0), F3(~3, ~0x22, ~0)|ASI(~0),      "[1+2],J", 0, v9 },
+{ "ldq",        F3(3, 0x22, 0), F3(~3, ~0x22, ~0)|ASI_RS2(~0),  "[1],J", 0, v9 }, /* ldd [rs1+%g0],d */
+{ "ldq",        F3(3, 0x22, 1), F3(~3, ~0x22, ~1),              "[1+i],J", 0, v9 },
+{ "ldq",        F3(3, 0x22, 1), F3(~3, ~0x22, ~1),              "[i+1],J", 0, v9 },
+{ "ldq",        F3(3, 0x22, 1), F3(~3, ~0x22, ~1)|RS1_G0,       "[i],J", 0, v9 },
+{ "ldq",        F3(3, 0x22, 1), F3(~3, ~0x22, ~1)|SIMM13(~0),   "[1],J", 0, v9 }, /* ldd [rs1+0],d */
 
-{ "ldsb",	F3(3, 0x09, 0), F3(~3, ~0x09, ~0)|ASI(~0),	"[1+2],d", 0, v6 },
-{ "ldsb",	F3(3, 0x09, 0), F3(~3, ~0x09, ~0)|ASI_RS2(~0),	"[1],d", 0, v6 }, /* ldsb [rs1+%g0],d */
-{ "ldsb",	F3(3, 0x09, 1), F3(~3, ~0x09, ~1),		"[1+i],d", 0, v6 },
-{ "ldsb",	F3(3, 0x09, 1), F3(~3, ~0x09, ~1),		"[i+1],d", 0, v6 },
-{ "ldsb",	F3(3, 0x09, 1), F3(~3, ~0x09, ~1)|RS1_G0,	"[i],d", 0, v6 },
-{ "ldsb",	F3(3, 0x09, 1), F3(~3, ~0x09, ~1)|SIMM13(~0),	"[1],d", 0, v6 }, /* ldsb [rs1+0],d */
+{ "ldsb",       F3(3, 0x09, 0), F3(~3, ~0x09, ~0)|ASI(~0),      "[1+2],d", 0, v6 },
+{ "ldsb",       F3(3, 0x09, 0), F3(~3, ~0x09, ~0)|ASI_RS2(~0),  "[1],d", 0, v6 }, /* ldsb [rs1+%g0],d */
+{ "ldsb",       F3(3, 0x09, 1), F3(~3, ~0x09, ~1),              "[1+i],d", 0, v6 },
+{ "ldsb",       F3(3, 0x09, 1), F3(~3, ~0x09, ~1),              "[i+1],d", 0, v6 },
+{ "ldsb",       F3(3, 0x09, 1), F3(~3, ~0x09, ~1)|RS1_G0,       "[i],d", 0, v6 },
+{ "ldsb",       F3(3, 0x09, 1), F3(~3, ~0x09, ~1)|SIMM13(~0),   "[1],d", 0, v6 }, /* ldsb [rs1+0],d */
 
-{ "ldsh",	F3(3, 0x0a, 0), F3(~3, ~0x0a, ~0)|ASI_RS2(~0),	"[1],d", 0, v6 }, /* ldsh [rs1+%g0],d */
-{ "ldsh",	F3(3, 0x0a, 0), F3(~3, ~0x0a, ~0)|ASI(~0),	"[1+2],d", 0, v6 },
-{ "ldsh",	F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1),		"[1+i],d", 0, v6 },
-{ "ldsh",	F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1),		"[i+1],d", 0, v6 },
-{ "ldsh",	F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1)|RS1_G0,	"[i],d", 0, v6 },
-{ "ldsh",	F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1)|SIMM13(~0),	"[1],d", 0, v6 }, /* ldsh [rs1+0],d */
+{ "ldsh",       F3(3, 0x0a, 0), F3(~3, ~0x0a, ~0)|ASI_RS2(~0),  "[1],d", 0, v6 }, /* ldsh [rs1+%g0],d */
+{ "ldsh",       F3(3, 0x0a, 0), F3(~3, ~0x0a, ~0)|ASI(~0),      "[1+2],d", 0, v6 },
+{ "ldsh",       F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1),              "[1+i],d", 0, v6 },
+{ "ldsh",       F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1),              "[i+1],d", 0, v6 },
+{ "ldsh",       F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1)|RS1_G0,       "[i],d", 0, v6 },
+{ "ldsh",       F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1)|SIMM13(~0),   "[1],d", 0, v6 }, /* ldsh [rs1+0],d */
 
-{ "ldstub",	F3(3, 0x0d, 0), F3(~3, ~0x0d, ~0)|ASI(~0),	"[1+2],d", 0, v6 },
-{ "ldstub",	F3(3, 0x0d, 0), F3(~3, ~0x0d, ~0)|ASI_RS2(~0),	"[1],d", 0, v6 }, /* ldstub [rs1+%g0],d */
-{ "ldstub",	F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1),		"[1+i],d", 0, v6 },
-{ "ldstub",	F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1),		"[i+1],d", 0, v6 },
-{ "ldstub",	F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1)|RS1_G0,	"[i],d", 0, v6 },
-{ "ldstub",	F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1)|SIMM13(~0),	"[1],d", 0, v6 }, /* ldstub [rs1+0],d */
+{ "ldstub",     F3(3, 0x0d, 0), F3(~3, ~0x0d, ~0)|ASI(~0),      "[1+2],d", 0, v6 },
+{ "ldstub",     F3(3, 0x0d, 0), F3(~3, ~0x0d, ~0)|ASI_RS2(~0),  "[1],d", 0, v6 }, /* ldstub [rs1+%g0],d */
+{ "ldstub",     F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1),              "[1+i],d", 0, v6 },
+{ "ldstub",     F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1),              "[i+1],d", 0, v6 },
+{ "ldstub",     F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1)|RS1_G0,       "[i],d", 0, v6 },
+{ "ldstub",     F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1)|SIMM13(~0),   "[1],d", 0, v6 }, /* ldstub [rs1+0],d */
 
-{ "ldsw",	F3(3, 0x08, 0), F3(~3, ~0x08, ~0)|ASI(~0),	"[1+2],d", 0, v9 },
-{ "ldsw",	F3(3, 0x08, 0), F3(~3, ~0x08, ~0)|ASI_RS2(~0),	"[1],d", 0, v9 }, /* ldsw [rs1+%g0],d */
-{ "ldsw",	F3(3, 0x08, 1), F3(~3, ~0x08, ~1),		"[1+i],d", 0, v9 },
-{ "ldsw",	F3(3, 0x08, 1), F3(~3, ~0x08, ~1),		"[i+1],d", 0, v9 },
-{ "ldsw",	F3(3, 0x08, 1), F3(~3, ~0x08, ~1)|RS1_G0,	"[i],d", 0, v9 },
-{ "ldsw",	F3(3, 0x08, 1), F3(~3, ~0x08, ~1)|SIMM13(~0),	"[1],d", 0, v9 }, /* ldsw [rs1+0],d */
+{ "ldsw",       F3(3, 0x08, 0), F3(~3, ~0x08, ~0)|ASI(~0),      "[1+2],d", 0, v9 },
+{ "ldsw",       F3(3, 0x08, 0), F3(~3, ~0x08, ~0)|ASI_RS2(~0),  "[1],d", 0, v9 }, /* ldsw [rs1+%g0],d */
+{ "ldsw",       F3(3, 0x08, 1), F3(~3, ~0x08, ~1),              "[1+i],d", 0, v9 },
+{ "ldsw",       F3(3, 0x08, 1), F3(~3, ~0x08, ~1),              "[i+1],d", 0, v9 },
+{ "ldsw",       F3(3, 0x08, 1), F3(~3, ~0x08, ~1)|RS1_G0,       "[i],d", 0, v9 },
+{ "ldsw",       F3(3, 0x08, 1), F3(~3, ~0x08, ~1)|SIMM13(~0),   "[1],d", 0, v9 }, /* ldsw [rs1+0],d */
 
-{ "ldub",	F3(3, 0x01, 0), F3(~3, ~0x01, ~0)|ASI(~0),	"[1+2],d", 0, v6 },
-{ "ldub",	F3(3, 0x01, 0), F3(~3, ~0x01, ~0)|ASI_RS2(~0),	"[1],d", 0, v6 }, /* ldub [rs1+%g0],d */
-{ "ldub",	F3(3, 0x01, 1), F3(~3, ~0x01, ~1),		"[1+i],d", 0, v6 },
-{ "ldub",	F3(3, 0x01, 1), F3(~3, ~0x01, ~1),		"[i+1],d", 0, v6 },
-{ "ldub",	F3(3, 0x01, 1), F3(~3, ~0x01, ~1)|RS1_G0,	"[i],d", 0, v6 },
-{ "ldub",	F3(3, 0x01, 1), F3(~3, ~0x01, ~1)|SIMM13(~0),	"[1],d", 0, v6 }, /* ldub [rs1+0],d */
+{ "ldub",       F3(3, 0x01, 0), F3(~3, ~0x01, ~0)|ASI(~0),      "[1+2],d", 0, v6 },
+{ "ldub",       F3(3, 0x01, 0), F3(~3, ~0x01, ~0)|ASI_RS2(~0),  "[1],d", 0, v6 }, /* ldub [rs1+%g0],d */
+{ "ldub",       F3(3, 0x01, 1), F3(~3, ~0x01, ~1),              "[1+i],d", 0, v6 },
+{ "ldub",       F3(3, 0x01, 1), F3(~3, ~0x01, ~1),              "[i+1],d", 0, v6 },
+{ "ldub",       F3(3, 0x01, 1), F3(~3, ~0x01, ~1)|RS1_G0,       "[i],d", 0, v6 },
+{ "ldub",       F3(3, 0x01, 1), F3(~3, ~0x01, ~1)|SIMM13(~0),   "[1],d", 0, v6 }, /* ldub [rs1+0],d */
 
-{ "lduh",	F3(3, 0x02, 0), F3(~3, ~0x02, ~0)|ASI(~0),	"[1+2],d", 0, v6 },
-{ "lduh",	F3(3, 0x02, 0), F3(~3, ~0x02, ~0)|ASI_RS2(~0),	"[1],d", 0, v6 }, /* lduh [rs1+%g0],d */
-{ "lduh",	F3(3, 0x02, 1), F3(~3, ~0x02, ~1),		"[1+i],d", 0, v6 },
-{ "lduh",	F3(3, 0x02, 1), F3(~3, ~0x02, ~1),		"[i+1],d", 0, v6 },
-{ "lduh",	F3(3, 0x02, 1), F3(~3, ~0x02, ~1)|RS1_G0,	"[i],d", 0, v6 },
-{ "lduh",	F3(3, 0x02, 1), F3(~3, ~0x02, ~1)|SIMM13(~0),	"[1],d", 0, v6 }, /* lduh [rs1+0],d */
+{ "lduh",       F3(3, 0x02, 0), F3(~3, ~0x02, ~0)|ASI(~0),      "[1+2],d", 0, v6 },
+{ "lduh",       F3(3, 0x02, 0), F3(~3, ~0x02, ~0)|ASI_RS2(~0),  "[1],d", 0, v6 }, /* lduh [rs1+%g0],d */
+{ "lduh",       F3(3, 0x02, 1), F3(~3, ~0x02, ~1),              "[1+i],d", 0, v6 },
+{ "lduh",       F3(3, 0x02, 1), F3(~3, ~0x02, ~1),              "[i+1],d", 0, v6 },
+{ "lduh",       F3(3, 0x02, 1), F3(~3, ~0x02, ~1)|RS1_G0,       "[i],d", 0, v6 },
+{ "lduh",       F3(3, 0x02, 1), F3(~3, ~0x02, ~1)|SIMM13(~0),   "[1],d", 0, v6 }, /* lduh [rs1+0],d */
 
-{ "ldx",	F3(3, 0x0b, 0), F3(~3, ~0x0b, ~0)|ASI(~0),	"[1+2],d", 0, v9 },
-{ "ldx",	F3(3, 0x0b, 0), F3(~3, ~0x0b, ~0)|ASI_RS2(~0),	"[1],d", 0, v9 }, /* ldx [rs1+%g0],d */
-{ "ldx",	F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1),		"[1+i],d", 0, v9 },
-{ "ldx",	F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1),		"[i+1],d", 0, v9 },
-{ "ldx",	F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1)|RS1_G0,	"[i],d", 0, v9 },
-{ "ldx",	F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1)|SIMM13(~0),	"[1],d", 0, v9 }, /* ldx [rs1+0],d */
+{ "ldx",        F3(3, 0x0b, 0), F3(~3, ~0x0b, ~0)|ASI(~0),      "[1+2],d", 0, v9 },
+{ "ldx",        F3(3, 0x0b, 0), F3(~3, ~0x0b, ~0)|ASI_RS2(~0),  "[1],d", 0, v9 }, /* ldx [rs1+%g0],d */
+{ "ldx",        F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1),              "[1+i],d", 0, v9 },
+{ "ldx",        F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1),              "[i+1],d", 0, v9 },
+{ "ldx",        F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1)|RS1_G0,       "[i],d", 0, v9 },
+{ "ldx",        F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1)|SIMM13(~0),   "[1],d", 0, v9 }, /* ldx [rs1+0],d */
 
-{ "ldx",	F3(3, 0x21, 0)|RD(1), F3(~3, ~0x21, ~0)|RD(~1),	"[1+2],F", 0, v9 },
-{ "ldx",	F3(3, 0x21, 0)|RD(1), F3(~3, ~0x21, ~0)|RS2_G0|RD(~1),	"[1],F", 0, v9 }, /* ld [rs1+%g0],d */
-{ "ldx",	F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|RD(~1),	"[1+i],F", 0, v9 },
-{ "ldx",	F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|RD(~1),	"[i+1],F", 0, v9 },
-{ "ldx",	F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|RS1_G0|RD(~1),	"[i],F", 0, v9 },
-{ "ldx",	F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|SIMM13(~0)|RD(~1),"[1],F", 0, v9 }, /* ld [rs1+0],d */
+{ "ldx",        F3(3, 0x21, 0)|RD(1), F3(~3, ~0x21, ~0)|RD(~1), "[1+2],F", 0, v9 },
+{ "ldx",        F3(3, 0x21, 0)|RD(1), F3(~3, ~0x21, ~0)|RS2_G0|RD(~1),  "[1],F", 0, v9 }, /* ld [rs1+%g0],d */
+{ "ldx",        F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|RD(~1), "[1+i],F", 0, v9 },
+{ "ldx",        F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|RD(~1), "[i+1],F", 0, v9 },
+{ "ldx",        F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|RS1_G0|RD(~1),  "[i],F", 0, v9 },
+{ "ldx",        F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|SIMM13(~0)|RD(~1),"[1],F", 0, v9 }, /* ld [rs1+0],d */
 
-{ "lda",	F3(3, 0x10, 0), F3(~3, ~0x10, ~0),		"[1+2]A,d", 0, v6 },
-{ "lda",	F3(3, 0x10, 0), F3(~3, ~0x10, ~0)|RS2_G0,	"[1]A,d", 0, v6 }, /* lda [rs1+%g0],d */
-{ "lda",	F3(3, 0x10, 1), F3(~3, ~0x10, ~1),		"[1+i]o,d", 0, v9 },
-{ "lda",	F3(3, 0x10, 1), F3(~3, ~0x10, ~1),		"[i+1]o,d", 0, v9 },
-{ "lda",	F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|RS1_G0,	"[i]o,d", 0, v9 },
-{ "lda",	F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|SIMM13(~0),	"[1]o,d", 0, v9 }, /* ld [rs1+0],d */
-{ "lda",	F3(3, 0x30, 0), F3(~3, ~0x30, ~0),		"[1+2]A,g", 0, v9 },
-{ "lda",	F3(3, 0x30, 0), F3(~3, ~0x30, ~0)|RS2_G0,	"[1]A,g", 0, v9 }, /* lda [rs1+%g0],d */
-{ "lda",	F3(3, 0x30, 1), F3(~3, ~0x30, ~1),		"[1+i]o,g", 0, v9 },
-{ "lda",	F3(3, 0x30, 1), F3(~3, ~0x30, ~1),		"[i+1]o,g", 0, v9 },
-{ "lda",	F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|RS1_G0,	"[i]o,g", 0, v9 },
-{ "lda",	F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|SIMM13(~0),	"[1]o,g", 0, v9 }, /* ld [rs1+0],d */
+{ "lda",        F3(3, 0x10, 0), F3(~3, ~0x10, ~0),              "[1+2]A,d", 0, v6 },
+{ "lda",        F3(3, 0x10, 0), F3(~3, ~0x10, ~0)|RS2_G0,       "[1]A,d", 0, v6 }, /* lda [rs1+%g0],d */
+{ "lda",        F3(3, 0x10, 1), F3(~3, ~0x10, ~1),              "[1+i]o,d", 0, v9 },
+{ "lda",        F3(3, 0x10, 1), F3(~3, ~0x10, ~1),              "[i+1]o,d", 0, v9 },
+{ "lda",        F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|RS1_G0,       "[i]o,d", 0, v9 },
+{ "lda",        F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|SIMM13(~0),   "[1]o,d", 0, v9 }, /* ld [rs1+0],d */
+{ "lda",        F3(3, 0x30, 0), F3(~3, ~0x30, ~0),              "[1+2]A,g", 0, v9 },
+{ "lda",        F3(3, 0x30, 0), F3(~3, ~0x30, ~0)|RS2_G0,       "[1]A,g", 0, v9 }, /* lda [rs1+%g0],d */
+{ "lda",        F3(3, 0x30, 1), F3(~3, ~0x30, ~1),              "[1+i]o,g", 0, v9 },
+{ "lda",        F3(3, 0x30, 1), F3(~3, ~0x30, ~1),              "[i+1]o,g", 0, v9 },
+{ "lda",        F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|RS1_G0,       "[i]o,g", 0, v9 },
+{ "lda",        F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|SIMM13(~0),   "[1]o,g", 0, v9 }, /* ld [rs1+0],d */
 
-{ "ldda",	F3(3, 0x13, 0), F3(~3, ~0x13, ~0),		"[1+2]A,d", 0, v6 },
-{ "ldda",	F3(3, 0x13, 0), F3(~3, ~0x13, ~0)|RS2_G0,	"[1]A,d", 0, v6 }, /* ldda [rs1+%g0],d */
-{ "ldda",	F3(3, 0x13, 1), F3(~3, ~0x13, ~1),		"[1+i]o,d", 0, v9 },
-{ "ldda",	F3(3, 0x13, 1), F3(~3, ~0x13, ~1),		"[i+1]o,d", 0, v9 },
-{ "ldda",	F3(3, 0x13, 1), F3(~3, ~0x13, ~1)|RS1_G0,	"[i]o,d", 0, v9 },
-{ "ldda",	F3(3, 0x13, 1), F3(~3, ~0x13, ~1)|SIMM13(~0),	"[1]o,d", 0, v9 }, /* ld [rs1+0],d */
+{ "ldda",       F3(3, 0x13, 0), F3(~3, ~0x13, ~0),              "[1+2]A,d", 0, v6 },
+{ "ldda",       F3(3, 0x13, 0), F3(~3, ~0x13, ~0)|RS2_G0,       "[1]A,d", 0, v6 }, /* ldda [rs1+%g0],d */
+{ "ldda",       F3(3, 0x13, 1), F3(~3, ~0x13, ~1),              "[1+i]o,d", 0, v9 },
+{ "ldda",       F3(3, 0x13, 1), F3(~3, ~0x13, ~1),              "[i+1]o,d", 0, v9 },
+{ "ldda",       F3(3, 0x13, 1), F3(~3, ~0x13, ~1)|RS1_G0,       "[i]o,d", 0, v9 },
+{ "ldda",       F3(3, 0x13, 1), F3(~3, ~0x13, ~1)|SIMM13(~0),   "[1]o,d", 0, v9 }, /* ld [rs1+0],d */
 
-{ "ldda",	F3(3, 0x33, 0), F3(~3, ~0x33, ~0),		"[1+2]A,H", 0, v9 },
-{ "ldda",	F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|RS2_G0,	"[1]A,H", 0, v9 }, /* ldda [rs1+%g0],d */
-{ "ldda",	F3(3, 0x33, 1), F3(~3, ~0x33, ~1),		"[1+i]o,H", 0, v9 },
-{ "ldda",	F3(3, 0x33, 1), F3(~3, ~0x33, ~1),		"[i+1]o,H", 0, v9 },
-{ "ldda",	F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|RS1_G0,	"[i]o,H", 0, v9 },
-{ "ldda",	F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|SIMM13(~0),	"[1]o,H", 0, v9 }, /* ld [rs1+0],d */
+{ "ldda",       F3(3, 0x33, 0), F3(~3, ~0x33, ~0),              "[1+2]A,H", 0, v9 },
+{ "ldda",       F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|RS2_G0,       "[1]A,H", 0, v9 }, /* ldda [rs1+%g0],d */
+{ "ldda",       F3(3, 0x33, 1), F3(~3, ~0x33, ~1),              "[1+i]o,H", 0, v9 },
+{ "ldda",       F3(3, 0x33, 1), F3(~3, ~0x33, ~1),              "[i+1]o,H", 0, v9 },
+{ "ldda",       F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|RS1_G0,       "[i]o,H", 0, v9 },
+{ "ldda",       F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|SIMM13(~0),   "[1]o,H", 0, v9 }, /* ld [rs1+0],d */
 
-{ "ldqa",	F3(3, 0x32, 0), F3(~3, ~0x32, ~0),		"[1+2]A,J", 0, v9 },
-{ "ldqa",	F3(3, 0x32, 0), F3(~3, ~0x32, ~0)|RS2_G0,	"[1]A,J", 0, v9 }, /* ldd [rs1+%g0],d */
-{ "ldqa",	F3(3, 0x32, 1), F3(~3, ~0x32, ~1),		"[1+i]o,J", 0, v9 },
-{ "ldqa",	F3(3, 0x32, 1), F3(~3, ~0x32, ~1),		"[i+1]o,J", 0, v9 },
-{ "ldqa",	F3(3, 0x32, 1), F3(~3, ~0x32, ~1)|RS1_G0,	"[i]o,J", 0, v9 },
-{ "ldqa",	F3(3, 0x32, 1), F3(~3, ~0x32, ~1)|SIMM13(~0),	"[1]o,J", 0, v9 }, /* ldd [rs1+0],d */
+{ "ldqa",       F3(3, 0x32, 0), F3(~3, ~0x32, ~0),              "[1+2]A,J", 0, v9 },
+{ "ldqa",       F3(3, 0x32, 0), F3(~3, ~0x32, ~0)|RS2_G0,       "[1]A,J", 0, v9 }, /* ldd [rs1+%g0],d */
+{ "ldqa",       F3(3, 0x32, 1), F3(~3, ~0x32, ~1),              "[1+i]o,J", 0, v9 },
+{ "ldqa",       F3(3, 0x32, 1), F3(~3, ~0x32, ~1),              "[i+1]o,J", 0, v9 },
+{ "ldqa",       F3(3, 0x32, 1), F3(~3, ~0x32, ~1)|RS1_G0,       "[i]o,J", 0, v9 },
+{ "ldqa",       F3(3, 0x32, 1), F3(~3, ~0x32, ~1)|SIMM13(~0),   "[1]o,J", 0, v9 }, /* ldd [rs1+0],d */
 
-{ "ldsba",	F3(3, 0x19, 0), F3(~3, ~0x19, ~0),		"[1+2]A,d", 0, v6 },
-{ "ldsba",	F3(3, 0x19, 0), F3(~3, ~0x19, ~0)|RS2_G0,	"[1]A,d", 0, v6 }, /* ldsba [rs1+%g0],d */
-{ "ldsba",	F3(3, 0x19, 1), F3(~3, ~0x19, ~1),		"[1+i]o,d", 0, v9 },
-{ "ldsba",	F3(3, 0x19, 1), F3(~3, ~0x19, ~1),		"[i+1]o,d", 0, v9 },
-{ "ldsba",	F3(3, 0x19, 1), F3(~3, ~0x19, ~1)|RS1_G0,	"[i]o,d", 0, v9 },
-{ "ldsba",	F3(3, 0x19, 1), F3(~3, ~0x19, ~1)|SIMM13(~0),	"[1]o,d", 0, v9 }, /* ld [rs1+0],d */
+{ "ldsba",      F3(3, 0x19, 0), F3(~3, ~0x19, ~0),              "[1+2]A,d", 0, v6 },
+{ "ldsba",      F3(3, 0x19, 0), F3(~3, ~0x19, ~0)|RS2_G0,       "[1]A,d", 0, v6 }, /* ldsba [rs1+%g0],d */
+{ "ldsba",      F3(3, 0x19, 1), F3(~3, ~0x19, ~1),              "[1+i]o,d", 0, v9 },
+{ "ldsba",      F3(3, 0x19, 1), F3(~3, ~0x19, ~1),              "[i+1]o,d", 0, v9 },
+{ "ldsba",      F3(3, 0x19, 1), F3(~3, ~0x19, ~1)|RS1_G0,       "[i]o,d", 0, v9 },
+{ "ldsba",      F3(3, 0x19, 1), F3(~3, ~0x19, ~1)|SIMM13(~0),   "[1]o,d", 0, v9 }, /* ld [rs1+0],d */
 
-{ "ldsha",	F3(3, 0x1a, 0), F3(~3, ~0x1a, ~0),		"[1+2]A,d", 0, v6 },
-{ "ldsha",	F3(3, 0x1a, 0), F3(~3, ~0x1a, ~0)|RS2_G0,	"[1]A,d", 0, v6 }, /* ldsha [rs1+%g0],d */
-{ "ldsha",	F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1),		"[1+i]o,d", 0, v9 },
-{ "ldsha",	F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1),		"[i+1]o,d", 0, v9 },
-{ "ldsha",	F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1)|RS1_G0,	"[i]o,d", 0, v9 },
-{ "ldsha",	F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1)|SIMM13(~0),	"[1]o,d", 0, v9 }, /* ld [rs1+0],d */
+{ "ldsha",      F3(3, 0x1a, 0), F3(~3, ~0x1a, ~0),              "[1+2]A,d", 0, v6 },
+{ "ldsha",      F3(3, 0x1a, 0), F3(~3, ~0x1a, ~0)|RS2_G0,       "[1]A,d", 0, v6 }, /* ldsha [rs1+%g0],d */
+{ "ldsha",      F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1),              "[1+i]o,d", 0, v9 },
+{ "ldsha",      F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1),              "[i+1]o,d", 0, v9 },
+{ "ldsha",      F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1)|RS1_G0,       "[i]o,d", 0, v9 },
+{ "ldsha",      F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1)|SIMM13(~0),   "[1]o,d", 0, v9 }, /* ld [rs1+0],d */
 
-{ "ldstuba",	F3(3, 0x1d, 0), F3(~3, ~0x1d, ~0),		"[1+2]A,d", 0, v6 },
-{ "ldstuba",	F3(3, 0x1d, 0), F3(~3, ~0x1d, ~0)|RS2_G0,	"[1]A,d", 0, v6 }, /* ldstuba [rs1+%g0],d */
-{ "ldstuba",	F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1),		"[1+i]o,d", 0, v9 },
-{ "ldstuba",	F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1),		"[i+1]o,d", 0, v9 },
-{ "ldstuba",	F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1)|RS1_G0,	"[i]o,d", 0, v9 },
-{ "ldstuba",	F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1)|SIMM13(~0),	"[1]o,d", 0, v9 }, /* ld [rs1+0],d */
+{ "ldstuba",    F3(3, 0x1d, 0), F3(~3, ~0x1d, ~0),              "[1+2]A,d", 0, v6 },
+{ "ldstuba",    F3(3, 0x1d, 0), F3(~3, ~0x1d, ~0)|RS2_G0,       "[1]A,d", 0, v6 }, /* ldstuba [rs1+%g0],d */
+{ "ldstuba",    F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1),              "[1+i]o,d", 0, v9 },
+{ "ldstuba",    F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1),              "[i+1]o,d", 0, v9 },
+{ "ldstuba",    F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1)|RS1_G0,       "[i]o,d", 0, v9 },
+{ "ldstuba",    F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1)|SIMM13(~0),   "[1]o,d", 0, v9 }, /* ld [rs1+0],d */
 
-{ "ldswa",	F3(3, 0x18, 0), F3(~3, ~0x18, ~0),		"[1+2]A,d", 0, v9 },
-{ "ldswa",	F3(3, 0x18, 0), F3(~3, ~0x18, ~0)|RS2_G0,	"[1]A,d", 0, v9 }, /* lda [rs1+%g0],d */
-{ "ldswa",	F3(3, 0x18, 1), F3(~3, ~0x18, ~1),		"[1+i]o,d", 0, v9 },
-{ "ldswa",	F3(3, 0x18, 1), F3(~3, ~0x18, ~1),		"[i+1]o,d", 0, v9 },
-{ "ldswa",	F3(3, 0x18, 1), F3(~3, ~0x18, ~1)|RS1_G0,	"[i]o,d", 0, v9 },
-{ "ldswa",	F3(3, 0x18, 1), F3(~3, ~0x18, ~1)|SIMM13(~0),	"[1]o,d", 0, v9 }, /* ld [rs1+0],d */
+{ "ldswa",      F3(3, 0x18, 0), F3(~3, ~0x18, ~0),              "[1+2]A,d", 0, v9 },
+{ "ldswa",      F3(3, 0x18, 0), F3(~3, ~0x18, ~0)|RS2_G0,       "[1]A,d", 0, v9 }, /* lda [rs1+%g0],d */
+{ "ldswa",      F3(3, 0x18, 1), F3(~3, ~0x18, ~1),              "[1+i]o,d", 0, v9 },
+{ "ldswa",      F3(3, 0x18, 1), F3(~3, ~0x18, ~1),              "[i+1]o,d", 0, v9 },
+{ "ldswa",      F3(3, 0x18, 1), F3(~3, ~0x18, ~1)|RS1_G0,       "[i]o,d", 0, v9 },
+{ "ldswa",      F3(3, 0x18, 1), F3(~3, ~0x18, ~1)|SIMM13(~0),   "[1]o,d", 0, v9 }, /* ld [rs1+0],d */
 
-{ "lduba",	F3(3, 0x11, 0), F3(~3, ~0x11, ~0),		"[1+2]A,d", 0, v6 },
-{ "lduba",	F3(3, 0x11, 0), F3(~3, ~0x11, ~0)|RS2_G0,	"[1]A,d", 0, v6 }, /* lduba [rs1+%g0],d */
-{ "lduba",	F3(3, 0x11, 1), F3(~3, ~0x11, ~1),		"[1+i]o,d", 0, v9 },
-{ "lduba",	F3(3, 0x11, 1), F3(~3, ~0x11, ~1),		"[i+1]o,d", 0, v9 },
-{ "lduba",	F3(3, 0x11, 1), F3(~3, ~0x11, ~1)|RS1_G0,	"[i]o,d", 0, v9 },
-{ "lduba",	F3(3, 0x11, 1), F3(~3, ~0x11, ~1)|SIMM13(~0),	"[1]o,d", 0, v9 }, /* ld [rs1+0],d */
+{ "lduba",      F3(3, 0x11, 0), F3(~3, ~0x11, ~0),              "[1+2]A,d", 0, v6 },
+{ "lduba",      F3(3, 0x11, 0), F3(~3, ~0x11, ~0)|RS2_G0,       "[1]A,d", 0, v6 }, /* lduba [rs1+%g0],d */
+{ "lduba",      F3(3, 0x11, 1), F3(~3, ~0x11, ~1),              "[1+i]o,d", 0, v9 },
+{ "lduba",      F3(3, 0x11, 1), F3(~3, ~0x11, ~1),              "[i+1]o,d", 0, v9 },
+{ "lduba",      F3(3, 0x11, 1), F3(~3, ~0x11, ~1)|RS1_G0,       "[i]o,d", 0, v9 },
+{ "lduba",      F3(3, 0x11, 1), F3(~3, ~0x11, ~1)|SIMM13(~0),   "[1]o,d", 0, v9 }, /* ld [rs1+0],d */
 
-{ "lduha",	F3(3, 0x12, 0), F3(~3, ~0x12, ~0),		"[1+2]A,d", 0, v6 },
-{ "lduha",	F3(3, 0x12, 0), F3(~3, ~0x12, ~0)|RS2_G0,	"[1]A,d", 0, v6 }, /* lduha [rs1+%g0],d */
-{ "lduha",	F3(3, 0x12, 1), F3(~3, ~0x12, ~1),		"[1+i]o,d", 0, v9 },
-{ "lduha",	F3(3, 0x12, 1), F3(~3, ~0x12, ~1),		"[i+1]o,d", 0, v9 },
-{ "lduha",	F3(3, 0x12, 1), F3(~3, ~0x12, ~1)|RS1_G0,	"[i]o,d", 0, v9 },
-{ "lduha",	F3(3, 0x12, 1), F3(~3, ~0x12, ~1)|SIMM13(~0),	"[1]o,d", 0, v9 }, /* ld [rs1+0],d */
+{ "lduha",      F3(3, 0x12, 0), F3(~3, ~0x12, ~0),              "[1+2]A,d", 0, v6 },
+{ "lduha",      F3(3, 0x12, 0), F3(~3, ~0x12, ~0)|RS2_G0,       "[1]A,d", 0, v6 }, /* lduha [rs1+%g0],d */
+{ "lduha",      F3(3, 0x12, 1), F3(~3, ~0x12, ~1),              "[1+i]o,d", 0, v9 },
+{ "lduha",      F3(3, 0x12, 1), F3(~3, ~0x12, ~1),              "[i+1]o,d", 0, v9 },
+{ "lduha",      F3(3, 0x12, 1), F3(~3, ~0x12, ~1)|RS1_G0,       "[i]o,d", 0, v9 },
+{ "lduha",      F3(3, 0x12, 1), F3(~3, ~0x12, ~1)|SIMM13(~0),   "[1]o,d", 0, v9 }, /* ld [rs1+0],d */
 
-{ "lduwa",	F3(3, 0x10, 0), F3(~3, ~0x10, ~0),		"[1+2]A,d", F_ALIAS, v9 }, /* lduwa === lda */
-{ "lduwa",	F3(3, 0x10, 0), F3(~3, ~0x10, ~0)|RS2_G0,	"[1]A,d", F_ALIAS, v9 }, /* lda [rs1+%g0],d */
-{ "lduwa",	F3(3, 0x10, 1), F3(~3, ~0x10, ~1),		"[1+i]o,d", F_ALIAS, v9 },
-{ "lduwa",	F3(3, 0x10, 1), F3(~3, ~0x10, ~1),		"[i+1]o,d", F_ALIAS, v9 },
-{ "lduwa",	F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|RS1_G0,	"[i]o,d", F_ALIAS, v9 },
-{ "lduwa",	F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|SIMM13(~0),	"[1]o,d", F_ALIAS, v9 }, /* ld [rs1+0],d */
+{ "lduwa",      F3(3, 0x10, 0), F3(~3, ~0x10, ~0),              "[1+2]A,d", F_ALIAS, v9 }, /* lduwa === lda */
+{ "lduwa",      F3(3, 0x10, 0), F3(~3, ~0x10, ~0)|RS2_G0,       "[1]A,d", F_ALIAS, v9 }, /* lda [rs1+%g0],d */
+{ "lduwa",      F3(3, 0x10, 1), F3(~3, ~0x10, ~1),              "[1+i]o,d", F_ALIAS, v9 },
+{ "lduwa",      F3(3, 0x10, 1), F3(~3, ~0x10, ~1),              "[i+1]o,d", F_ALIAS, v9 },
+{ "lduwa",      F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|RS1_G0,       "[i]o,d", F_ALIAS, v9 },
+{ "lduwa",      F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|SIMM13(~0),   "[1]o,d", F_ALIAS, v9 }, /* ld [rs1+0],d */
 
-{ "ldxa",	F3(3, 0x1b, 0), F3(~3, ~0x1b, ~0),		"[1+2]A,d", 0, v9 },
-{ "ldxa",	F3(3, 0x1b, 0), F3(~3, ~0x1b, ~0)|RS2_G0,	"[1]A,d", 0, v9 }, /* lda [rs1+%g0],d */
-{ "ldxa",	F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1),		"[1+i]o,d", 0, v9 },
-{ "ldxa",	F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1),		"[i+1]o,d", 0, v9 },
-{ "ldxa",	F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1)|RS1_G0,	"[i]o,d", 0, v9 },
-{ "ldxa",	F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1)|SIMM13(~0),	"[1]o,d", 0, v9 }, /* ld [rs1+0],d */
+{ "ldxa",       F3(3, 0x1b, 0), F3(~3, ~0x1b, ~0),              "[1+2]A,d", 0, v9 },
+{ "ldxa",       F3(3, 0x1b, 0), F3(~3, ~0x1b, ~0)|RS2_G0,       "[1]A,d", 0, v9 }, /* lda [rs1+%g0],d */
+{ "ldxa",       F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1),              "[1+i]o,d", 0, v9 },
+{ "ldxa",       F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1),              "[i+1]o,d", 0, v9 },
+{ "ldxa",       F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1)|RS1_G0,       "[i]o,d", 0, v9 },
+{ "ldxa",       F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1)|SIMM13(~0),   "[1]o,d", 0, v9 }, /* ld [rs1+0],d */
 
-{ "st",	F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0),		"d,[1+2]", 0, v6 },
-{ "st",	F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0),		"d,[1]", 0, v6 }, /* st d,[rs1+%g0] */
-{ "st",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1),			"d,[1+i]", 0, v6 },
-{ "st",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1),			"d,[i+1]", 0, v6 },
-{ "st",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0,		"d,[i]", 0, v6 },
-{ "st",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0),		"d,[1]", 0, v6 }, /* st d,[rs1+0] */
-{ "st",	F3(3, 0x24, 0), F3(~3, ~0x24, ~0)|ASI(~0),		"g,[1+2]", 0, v6 },
-{ "st",	F3(3, 0x24, 0), F3(~3, ~0x24, ~0)|ASI_RS2(~0),		"g,[1]", 0, v6 }, /* st d[rs1+%g0] */
-{ "st",	F3(3, 0x24, 1), F3(~3, ~0x24, ~1),			"g,[1+i]", 0, v6 },
-{ "st",	F3(3, 0x24, 1), F3(~3, ~0x24, ~1),			"g,[i+1]", 0, v6 },
-{ "st",	F3(3, 0x24, 1), F3(~3, ~0x24, ~1)|RS1_G0,		"g,[i]", 0, v6 },
-{ "st",	F3(3, 0x24, 1), F3(~3, ~0x24, ~1)|SIMM13(~0),		"g,[1]", 0, v6 }, /* st d,[rs1+0] */
+{ "st", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0),              "d,[1+2]", 0, v6 },
+{ "st", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0),          "d,[1]", 0, v6 }, /* st d,[rs1+%g0] */
+{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1),                      "d,[1+i]", 0, v6 },
+{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1),                      "d,[i+1]", 0, v6 },
+{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0,               "d,[i]", 0, v6 },
+{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0),           "d,[1]", 0, v6 }, /* st d,[rs1+0] */
+{ "st", F3(3, 0x24, 0), F3(~3, ~0x24, ~0)|ASI(~0),              "g,[1+2]", 0, v6 },
+{ "st", F3(3, 0x24, 0), F3(~3, ~0x24, ~0)|ASI_RS2(~0),          "g,[1]", 0, v6 }, /* st d[rs1+%g0] */
+{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1),                      "g,[1+i]", 0, v6 },
+{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1),                      "g,[i+1]", 0, v6 },
+{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1)|RS1_G0,               "g,[i]", 0, v6 },
+{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1)|SIMM13(~0),           "g,[1]", 0, v6 }, /* st d,[rs1+0] */
 
-{ "st",	F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI(~0),		"D,[1+2]", 0, v6notv9 },
-{ "st",	F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI_RS2(~0),		"D,[1]", 0, v6notv9 }, /* st d,[rs1+%g0] */
-{ "st",	F3(3, 0x34, 1), F3(~3, ~0x34, ~1),			"D,[1+i]", 0, v6notv9 },
-{ "st",	F3(3, 0x34, 1), F3(~3, ~0x34, ~1),			"D,[i+1]", 0, v6notv9 },
-{ "st",	F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|RS1_G0,		"D,[i]", 0, v6notv9 },
-{ "st",	F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|SIMM13(~0),		"D,[1]", 0, v6notv9 }, /* st d,[rs1+0] */
-{ "st",	F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI(~0),		"C,[1+2]", 0, v6notv9 },
-{ "st",	F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI_RS2(~0),		"C,[1]", 0, v6notv9 }, /* st d,[rs1+%g0] */
-{ "st",	F3(3, 0x35, 1), F3(~3, ~0x35, ~1),			"C,[1+i]", 0, v6notv9 },
-{ "st",	F3(3, 0x35, 1), F3(~3, ~0x35, ~1),			"C,[i+1]", 0, v6notv9 },
-{ "st",	F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|RS1_G0,		"C,[i]", 0, v6notv9 },
-{ "st",	F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|SIMM13(~0),		"C,[1]", 0, v6notv9 }, /* st d,[rs1+0] */
+{ "st", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI(~0),              "D,[1+2]", 0, v6notv9 },
+{ "st", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI_RS2(~0),          "D,[1]", 0, v6notv9 }, /* st d,[rs1+%g0] */
+{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1),                      "D,[1+i]", 0, v6notv9 },
+{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1),                      "D,[i+1]", 0, v6notv9 },
+{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|RS1_G0,               "D,[i]", 0, v6notv9 },
+{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|SIMM13(~0),           "D,[1]", 0, v6notv9 }, /* st d,[rs1+0] */
+{ "st", F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI(~0),              "C,[1+2]", 0, v6notv9 },
+{ "st", F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI_RS2(~0),          "C,[1]", 0, v6notv9 }, /* st d,[rs1+%g0] */
+{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1),                      "C,[1+i]", 0, v6notv9 },
+{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1),                      "C,[i+1]", 0, v6notv9 },
+{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|RS1_G0,               "C,[i]", 0, v6notv9 },
+{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|SIMM13(~0),           "C,[1]", 0, v6notv9 }, /* st d,[rs1+0] */
 
-{ "st",	F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI(~0),	"F,[1+2]", 0, v6 },
-{ "st",	F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI_RS2(~0),	"F,[1]", 0, v6 }, /* st d,[rs1+%g0] */
-{ "st",	F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0,		"F,[1+i]", 0, v6 },
-{ "st",	F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0,		"F,[i+1]", 0, v6 },
-{ "st",	F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0|RS1_G0,		"F,[i]", 0, v6 },
-{ "st",	F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0|SIMM13(~0),	"F,[1]", 0, v6 }, /* st d,[rs1+0] */
+{ "st", F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI(~0),        "F,[1+2]", 0, v6 },
+{ "st", F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI_RS2(~0),    "F,[1]", 0, v6 }, /* st d,[rs1+%g0] */
+{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0,                "F,[1+i]", 0, v6 },
+{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0,                "F,[i+1]", 0, v6 },
+{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0|RS1_G0,         "F,[i]", 0, v6 },
+{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0|SIMM13(~0),     "F,[1]", 0, v6 }, /* st d,[rs1+0] */
 
-{ "stw",	F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0),	"d,[1+2]", F_ALIAS, v9 },
-{ "stw",	F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0),	"d,[1]", F_ALIAS, v9 }, /* st d,[rs1+%g0] */
-{ "stw",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1),		"d,[1+i]", F_ALIAS, v9 },
-{ "stw",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1),		"d,[i+1]", F_ALIAS, v9 },
-{ "stw",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0,	"d,[i]", F_ALIAS, v9 },
-{ "stw",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0),	"d,[1]", F_ALIAS, v9 }, /* st d,[rs1+0] */
-{ "stsw",	F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0),	"d,[1+2]", F_ALIAS, v9 },
-{ "stsw",	F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0),	"d,[1]", F_ALIAS, v9 }, /* st d,[rs1+%g0] */
-{ "stsw",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1),		"d,[1+i]", F_ALIAS, v9 },
-{ "stsw",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1),		"d,[i+1]", F_ALIAS, v9 },
-{ "stsw",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0,	"d,[i]", F_ALIAS, v9 },
-{ "stsw",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0),	"d,[1]", F_ALIAS, v9 }, /* st d,[rs1+0] */
-{ "stuw",	F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0),	"d,[1+2]", F_ALIAS, v9 },
-{ "stuw",	F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0),	"d,[1]", F_ALIAS, v9 }, /* st d,[rs1+%g0] */
-{ "stuw",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1),		"d,[1+i]", F_ALIAS, v9 },
-{ "stuw",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1),		"d,[i+1]", F_ALIAS, v9 },
-{ "stuw",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0,	"d,[i]", F_ALIAS, v9 },
-{ "stuw",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0),	"d,[1]", F_ALIAS, v9 }, /* st d,[rs1+0] */
+{ "stw",        F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0),      "d,[1+2]", F_ALIAS, v9 },
+{ "stw",        F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0),  "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+%g0] */
+{ "stw",        F3(3, 0x04, 1), F3(~3, ~0x04, ~1),              "d,[1+i]", F_ALIAS, v9 },
+{ "stw",        F3(3, 0x04, 1), F3(~3, ~0x04, ~1),              "d,[i+1]", F_ALIAS, v9 },
+{ "stw",        F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0,       "d,[i]", F_ALIAS, v9 },
+{ "stw",        F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0),   "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+0] */
+{ "stsw",       F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0),      "d,[1+2]", F_ALIAS, v9 },
+{ "stsw",       F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0),  "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+%g0] */
+{ "stsw",       F3(3, 0x04, 1), F3(~3, ~0x04, ~1),              "d,[1+i]", F_ALIAS, v9 },
+{ "stsw",       F3(3, 0x04, 1), F3(~3, ~0x04, ~1),              "d,[i+1]", F_ALIAS, v9 },
+{ "stsw",       F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0,       "d,[i]", F_ALIAS, v9 },
+{ "stsw",       F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0),   "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+0] */
+{ "stuw",       F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0),      "d,[1+2]", F_ALIAS, v9 },
+{ "stuw",       F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0),  "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+%g0] */
+{ "stuw",       F3(3, 0x04, 1), F3(~3, ~0x04, ~1),              "d,[1+i]", F_ALIAS, v9 },
+{ "stuw",       F3(3, 0x04, 1), F3(~3, ~0x04, ~1),              "d,[i+1]", F_ALIAS, v9 },
+{ "stuw",       F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0,       "d,[i]", F_ALIAS, v9 },
+{ "stuw",       F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0),   "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+0] */
 
-{ "spill",	F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0),	"d,[1+2]", F_ALIAS, v6 },
-{ "spill",	F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0),	"d,[1]", F_ALIAS, v6 }, /* st d,[rs1+%g0] */
-{ "spill",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1),		"d,[1+i]", F_ALIAS, v6 },
-{ "spill",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1),		"d,[i+1]", F_ALIAS, v6 },
-{ "spill",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0,	"d,[i]", F_ALIAS, v6 },
-{ "spill",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0),	"d,[1]", F_ALIAS, v6 }, /* st d,[rs1+0] */
+{ "spill",      F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0),      "d,[1+2]", F_ALIAS, v6 },
+{ "spill",      F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0),  "d,[1]", F_ALIAS, v6 }, /* st d,[rs1+%g0] */
+{ "spill",      F3(3, 0x04, 1), F3(~3, ~0x04, ~1),              "d,[1+i]", F_ALIAS, v6 },
+{ "spill",      F3(3, 0x04, 1), F3(~3, ~0x04, ~1),              "d,[i+1]", F_ALIAS, v6 },
+{ "spill",      F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0,       "d,[i]", F_ALIAS, v6 },
+{ "spill",      F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0),   "d,[1]", F_ALIAS, v6 }, /* st d,[rs1+0] */
 
-{ "sta",	F3(3, 0x14, 0), F3(~3, ~0x14, ~0),		"d,[1+2]A", 0, v6 },
-{ "sta",	F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0),	"d,[1]A", 0, v6 }, /* sta d,[rs1+%g0] */
-{ "sta",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1),		"d,[1+i]o", 0, v9 },
-{ "sta",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1),		"d,[i+1]o", 0, v9 },
-{ "sta",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0,	"d,[i]o", 0, v9 },
-{ "sta",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0),	"d,[1]o", 0, v9 }, /* st d,[rs1+0] */
+{ "sta",        F3(3, 0x14, 0), F3(~3, ~0x14, ~0),              "d,[1+2]A", 0, v6 },
+{ "sta",        F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0),      "d,[1]A", 0, v6 }, /* sta d,[rs1+%g0] */
+{ "sta",        F3(3, 0x14, 1), F3(~3, ~0x14, ~1),              "d,[1+i]o", 0, v9 },
+{ "sta",        F3(3, 0x14, 1), F3(~3, ~0x14, ~1),              "d,[i+1]o", 0, v9 },
+{ "sta",        F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0,       "d,[i]o", 0, v9 },
+{ "sta",        F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0),   "d,[1]o", 0, v9 }, /* st d,[rs1+0] */
 
-{ "sta",	F3(3, 0x34, 0), F3(~3, ~0x34, ~0),		"g,[1+2]A", 0, v9 },
-{ "sta",	F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|RS2(~0),	"g,[1]A", 0, v9 }, /* sta d,[rs1+%g0] */
-{ "sta",	F3(3, 0x34, 1), F3(~3, ~0x34, ~1),		"g,[1+i]o", 0, v9 },
-{ "sta",	F3(3, 0x34, 1), F3(~3, ~0x34, ~1),		"g,[i+1]o", 0, v9 },
-{ "sta",	F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|RS1_G0,	"g,[i]o", 0, v9 },
-{ "sta",	F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|SIMM13(~0),	"g,[1]o", 0, v9 }, /* st d,[rs1+0] */
+{ "sta",        F3(3, 0x34, 0), F3(~3, ~0x34, ~0),              "g,[1+2]A", 0, v9 },
+{ "sta",        F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|RS2(~0),      "g,[1]A", 0, v9 }, /* sta d,[rs1+%g0] */
+{ "sta",        F3(3, 0x34, 1), F3(~3, ~0x34, ~1),              "g,[1+i]o", 0, v9 },
+{ "sta",        F3(3, 0x34, 1), F3(~3, ~0x34, ~1),              "g,[i+1]o", 0, v9 },
+{ "sta",        F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|RS1_G0,       "g,[i]o", 0, v9 },
+{ "sta",        F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|SIMM13(~0),   "g,[1]o", 0, v9 }, /* st d,[rs1+0] */
 
-{ "stwa",	F3(3, 0x14, 0), F3(~3, ~0x14, ~0),		"d,[1+2]A", F_ALIAS, v9 },
-{ "stwa",	F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0),	"d,[1]A", F_ALIAS, v9 }, /* sta d,[rs1+%g0] */
-{ "stwa",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1),		"d,[1+i]o", F_ALIAS, v9 },
-{ "stwa",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1),		"d,[i+1]o", F_ALIAS, v9 },
-{ "stwa",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0,	"d,[i]o", F_ALIAS, v9 },
-{ "stwa",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0),	"d,[1]o", F_ALIAS, v9 }, /* st d,[rs1+0] */
-{ "stswa",	F3(3, 0x14, 0), F3(~3, ~0x14, ~0),		"d,[1+2]A", F_ALIAS, v9 },
-{ "stswa",	F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0),	"d,[1]A", F_ALIAS, v9 }, /* sta d,[rs1+%g0] */
-{ "stswa",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1),		"d,[1+i]o", F_ALIAS, v9 },
-{ "stswa",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1),		"d,[i+1]o", F_ALIAS, v9 },
-{ "stswa",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0,	"d,[i]o", F_ALIAS, v9 },
-{ "stswa",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0),	"d,[1]o", F_ALIAS, v9 }, /* st d,[rs1+0] */
-{ "stuwa",	F3(3, 0x14, 0), F3(~3, ~0x14, ~0),		"d,[1+2]A", F_ALIAS, v9 },
-{ "stuwa",	F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0),	"d,[1]A", F_ALIAS, v9 }, /* sta d,[rs1+%g0] */
-{ "stuwa",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1),		"d,[1+i]o", F_ALIAS, v9 },
-{ "stuwa",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1),		"d,[i+1]o", F_ALIAS, v9 },
-{ "stuwa",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0,	"d,[i]o", F_ALIAS, v9 },
-{ "stuwa",	F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0),	"d,[1]o", F_ALIAS, v9 }, /* st d,[rs1+0] */
+{ "stwa",       F3(3, 0x14, 0), F3(~3, ~0x14, ~0),              "d,[1+2]A", F_ALIAS, v9 },
+{ "stwa",       F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0),      "d,[1]A", F_ALIAS, v9 }, /* sta d,[rs1+%g0] */
+{ "stwa",       F3(3, 0x14, 1), F3(~3, ~0x14, ~1),              "d,[1+i]o", F_ALIAS, v9 },
+{ "stwa",       F3(3, 0x14, 1), F3(~3, ~0x14, ~1),              "d,[i+1]o", F_ALIAS, v9 },
+{ "stwa",       F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0,       "d,[i]o", F_ALIAS, v9 },
+{ "stwa",       F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0),   "d,[1]o", F_ALIAS, v9 }, /* st d,[rs1+0] */
+{ "stswa",      F3(3, 0x14, 0), F3(~3, ~0x14, ~0),              "d,[1+2]A", F_ALIAS, v9 },
+{ "stswa",      F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0),      "d,[1]A", F_ALIAS, v9 }, /* sta d,[rs1+%g0] */
+{ "stswa",      F3(3, 0x14, 1), F3(~3, ~0x14, ~1),              "d,[1+i]o", F_ALIAS, v9 },
+{ "stswa",      F3(3, 0x14, 1), F3(~3, ~0x14, ~1),              "d,[i+1]o", F_ALIAS, v9 },
+{ "stswa",      F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0,       "d,[i]o", F_ALIAS, v9 },
+{ "stswa",      F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0),   "d,[1]o", F_ALIAS, v9 }, /* st d,[rs1+0] */
+{ "stuwa",      F3(3, 0x14, 0), F3(~3, ~0x14, ~0),              "d,[1+2]A", F_ALIAS, v9 },
+{ "stuwa",      F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0),      "d,[1]A", F_ALIAS, v9 }, /* sta d,[rs1+%g0] */
+{ "stuwa",      F3(3, 0x14, 1), F3(~3, ~0x14, ~1),              "d,[1+i]o", F_ALIAS, v9 },
+{ "stuwa",      F3(3, 0x14, 1), F3(~3, ~0x14, ~1),              "d,[i+1]o", F_ALIAS, v9 },
+{ "stuwa",      F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0,       "d,[i]o", F_ALIAS, v9 },
+{ "stuwa",      F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0),   "d,[1]o", F_ALIAS, v9 }, /* st d,[rs1+0] */
 
-{ "stb",	F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI(~0),	"d,[1+2]", 0, v6 },
-{ "stb",	F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI_RS2(~0),	"d,[1]", 0, v6 }, /* stb d,[rs1+%g0] */
-{ "stb",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1),		"d,[1+i]", 0, v6 },
-{ "stb",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1),		"d,[i+1]", 0, v6 },
-{ "stb",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RS1_G0,	"d,[i]", 0, v6 },
-{ "stb",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|SIMM13(~0),	"d,[1]", 0, v6 }, /* stb d,[rs1+0] */
+{ "stb",        F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI(~0),      "d,[1+2]", 0, v6 },
+{ "stb",        F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI_RS2(~0),  "d,[1]", 0, v6 }, /* stb d,[rs1+%g0] */
+{ "stb",        F3(3, 0x05, 1), F3(~3, ~0x05, ~1),              "d,[1+i]", 0, v6 },
+{ "stb",        F3(3, 0x05, 1), F3(~3, ~0x05, ~1),              "d,[i+1]", 0, v6 },
+{ "stb",        F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RS1_G0,       "d,[i]", 0, v6 },
+{ "stb",        F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|SIMM13(~0),   "d,[1]", 0, v6 }, /* stb d,[rs1+0] */
 
-{ "stsb",	F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI(~0),	"d,[1+2]", F_ALIAS, v6 },
-{ "stsb",	F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI_RS2(~0),	"d,[1]", F_ALIAS, v6 }, /* stb d,[rs1+%g0] */
-{ "stsb",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1),		"d,[1+i]", F_ALIAS, v6 },
-{ "stsb",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1),		"d,[i+1]", F_ALIAS, v6 },
-{ "stsb",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RS1_G0,	"d,[i]", F_ALIAS, v6 },
-{ "stsb",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|SIMM13(~0),	"d,[1]", F_ALIAS, v6 }, /* stb d,[rs1+0] */
-{ "stub",	F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI(~0),	"d,[1+2]", F_ALIAS, v6 },
-{ "stub",	F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI_RS2(~0),	"d,[1]", F_ALIAS, v6 }, /* stb d,[rs1+%g0] */
-{ "stub",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1),		"d,[1+i]", F_ALIAS, v6 },
-{ "stub",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1),		"d,[i+1]", F_ALIAS, v6 },
-{ "stub",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RS1_G0,	"d,[i]", F_ALIAS, v6 },
-{ "stub",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|SIMM13(~0),	"d,[1]", F_ALIAS, v6 }, /* stb d,[rs1+0] */
+{ "stsb",       F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI(~0),      "d,[1+2]", F_ALIAS, v6 },
+{ "stsb",       F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI_RS2(~0),  "d,[1]", F_ALIAS, v6 }, /* stb d,[rs1+%g0] */
+{ "stsb",       F3(3, 0x05, 1), F3(~3, ~0x05, ~1),              "d,[1+i]", F_ALIAS, v6 },
+{ "stsb",       F3(3, 0x05, 1), F3(~3, ~0x05, ~1),              "d,[i+1]", F_ALIAS, v6 },
+{ "stsb",       F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RS1_G0,       "d,[i]", F_ALIAS, v6 },
+{ "stsb",       F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|SIMM13(~0),   "d,[1]", F_ALIAS, v6 }, /* stb d,[rs1+0] */
+{ "stub",       F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI(~0),      "d,[1+2]", F_ALIAS, v6 },
+{ "stub",       F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI_RS2(~0),  "d,[1]", F_ALIAS, v6 }, /* stb d,[rs1+%g0] */
+{ "stub",       F3(3, 0x05, 1), F3(~3, ~0x05, ~1),              "d,[1+i]", F_ALIAS, v6 },
+{ "stub",       F3(3, 0x05, 1), F3(~3, ~0x05, ~1),              "d,[i+1]", F_ALIAS, v6 },
+{ "stub",       F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RS1_G0,       "d,[i]", F_ALIAS, v6 },
+{ "stub",       F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|SIMM13(~0),   "d,[1]", F_ALIAS, v6 }, /* stb d,[rs1+0] */
 
-{ "stba",	F3(3, 0x15, 0), F3(~3, ~0x15, ~0),		"d,[1+2]A", 0, v6 },
-{ "stba",	F3(3, 0x15, 0), F3(~3, ~0x15, ~0)|RS2(~0),	"d,[1]A", 0, v6 }, /* stba d,[rs1+%g0] */
-{ "stba",	F3(3, 0x15, 1), F3(~3, ~0x15, ~1),		"d,[1+i]o", 0, v9 },
-{ "stba",	F3(3, 0x15, 1), F3(~3, ~0x15, ~1),		"d,[i+1]o", 0, v9 },
-{ "stba",	F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|RS1_G0,	"d,[i]o", 0, v9 },
-{ "stba",	F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|SIMM13(~0),	"d,[1]o", 0, v9 }, /* stb d,[rs1+0] */
+{ "stba",       F3(3, 0x15, 0), F3(~3, ~0x15, ~0),              "d,[1+2]A", 0, v6 },
+{ "stba",       F3(3, 0x15, 0), F3(~3, ~0x15, ~0)|RS2(~0),      "d,[1]A", 0, v6 }, /* stba d,[rs1+%g0] */
+{ "stba",       F3(3, 0x15, 1), F3(~3, ~0x15, ~1),              "d,[1+i]o", 0, v9 },
+{ "stba",       F3(3, 0x15, 1), F3(~3, ~0x15, ~1),              "d,[i+1]o", 0, v9 },
+{ "stba",       F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|RS1_G0,       "d,[i]o", 0, v9 },
+{ "stba",       F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|SIMM13(~0),   "d,[1]o", 0, v9 }, /* stb d,[rs1+0] */
 
-{ "stsba",	F3(3, 0x15, 0), F3(~3, ~0x15, ~0),		"d,[1+2]A", F_ALIAS, v6 },
-{ "stsba",	F3(3, 0x15, 0), F3(~3, ~0x15, ~0)|RS2(~0),	"d,[1]A", F_ALIAS, v6 }, /* stba d,[rs1+%g0] */
-{ "stsba",	F3(3, 0x15, 1), F3(~3, ~0x15, ~1),		"d,[1+i]o", F_ALIAS, v9 },
-{ "stsba",	F3(3, 0x15, 1), F3(~3, ~0x15, ~1),		"d,[i+1]o", F_ALIAS, v9 },
-{ "stsba",	F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|RS1_G0,	"d,[i]o", F_ALIAS, v9 },
-{ "stsba",	F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|SIMM13(~0),	"d,[1]o", F_ALIAS, v9 }, /* stb d,[rs1+0] */
-{ "stuba",	F3(3, 0x15, 0), F3(~3, ~0x15, ~0),		"d,[1+2]A", F_ALIAS, v6 },
-{ "stuba",	F3(3, 0x15, 0), F3(~3, ~0x15, ~0)|RS2(~0),	"d,[1]A", F_ALIAS, v6 }, /* stba d,[rs1+%g0] */
-{ "stuba",	F3(3, 0x15, 1), F3(~3, ~0x15, ~1),		"d,[1+i]o", F_ALIAS, v9 },
-{ "stuba",	F3(3, 0x15, 1), F3(~3, ~0x15, ~1),		"d,[i+1]o", F_ALIAS, v9 },
-{ "stuba",	F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|RS1_G0,	"d,[i]o", F_ALIAS, v9 },
-{ "stuba",	F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|SIMM13(~0),	"d,[1]o", F_ALIAS, v9 }, /* stb d,[rs1+0] */
+{ "stsba",      F3(3, 0x15, 0), F3(~3, ~0x15, ~0),              "d,[1+2]A", F_ALIAS, v6 },
+{ "stsba",      F3(3, 0x15, 0), F3(~3, ~0x15, ~0)|RS2(~0),      "d,[1]A", F_ALIAS, v6 }, /* stba d,[rs1+%g0] */
+{ "stsba",      F3(3, 0x15, 1), F3(~3, ~0x15, ~1),              "d,[1+i]o", F_ALIAS, v9 },
+{ "stsba",      F3(3, 0x15, 1), F3(~3, ~0x15, ~1),              "d,[i+1]o", F_ALIAS, v9 },
+{ "stsba",      F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|RS1_G0,       "d,[i]o", F_ALIAS, v9 },
+{ "stsba",      F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|SIMM13(~0),   "d,[1]o", F_ALIAS, v9 }, /* stb d,[rs1+0] */
+{ "stuba",      F3(3, 0x15, 0), F3(~3, ~0x15, ~0),              "d,[1+2]A", F_ALIAS, v6 },
+{ "stuba",      F3(3, 0x15, 0), F3(~3, ~0x15, ~0)|RS2(~0),      "d,[1]A", F_ALIAS, v6 }, /* stba d,[rs1+%g0] */
+{ "stuba",      F3(3, 0x15, 1), F3(~3, ~0x15, ~1),              "d,[1+i]o", F_ALIAS, v9 },
+{ "stuba",      F3(3, 0x15, 1), F3(~3, ~0x15, ~1),              "d,[i+1]o", F_ALIAS, v9 },
+{ "stuba",      F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|RS1_G0,       "d,[i]o", F_ALIAS, v9 },
+{ "stuba",      F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|SIMM13(~0),   "d,[1]o", F_ALIAS, v9 }, /* stb d,[rs1+0] */
 
-{ "std",	F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI(~0),	"d,[1+2]", 0, v6 },
-{ "std",	F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI_RS2(~0),	"d,[1]", 0, v6 }, /* std d,[rs1+%g0] */
-{ "std",	F3(3, 0x07, 1), F3(~3, ~0x07, ~1),		"d,[1+i]", 0, v6 },
-{ "std",	F3(3, 0x07, 1), F3(~3, ~0x07, ~1),		"d,[i+1]", 0, v6 },
-{ "std",	F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|RS1_G0,	"d,[i]", 0, v6 },
-{ "std",	F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|SIMM13(~0),	"d,[1]", 0, v6 }, /* std d,[rs1+0] */
+{ "std",        F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI(~0),      "d,[1+2]", 0, v6 },
+{ "std",        F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI_RS2(~0),  "d,[1]", 0, v6 }, /* std d,[rs1+%g0] */
+{ "std",        F3(3, 0x07, 1), F3(~3, ~0x07, ~1),              "d,[1+i]", 0, v6 },
+{ "std",        F3(3, 0x07, 1), F3(~3, ~0x07, ~1),              "d,[i+1]", 0, v6 },
+{ "std",        F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|RS1_G0,       "d,[i]", 0, v6 },
+{ "std",        F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|SIMM13(~0),   "d,[1]", 0, v6 }, /* std d,[rs1+0] */
 
-{ "std",	F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI(~0),	"q,[1+2]", 0, v6notv9 },
-{ "std",	F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI_RS2(~0),	"q,[1]", 0, v6notv9 }, /* std d,[rs1+%g0] */
-{ "std",	F3(3, 0x26, 1), F3(~3, ~0x26, ~1),		"q,[1+i]", 0, v6notv9 },
-{ "std",	F3(3, 0x26, 1), F3(~3, ~0x26, ~1),		"q,[i+1]", 0, v6notv9 },
-{ "std",	F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|RS1_G0,	"q,[i]", 0, v6notv9 },
-{ "std",	F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|SIMM13(~0),	"q,[1]", 0, v6notv9 }, /* std d,[rs1+0] */
-{ "std",	F3(3, 0x27, 0), F3(~3, ~0x27, ~0)|ASI(~0),	"H,[1+2]", 0, v6 },
-{ "std",	F3(3, 0x27, 0), F3(~3, ~0x27, ~0)|ASI_RS2(~0),	"H,[1]", 0, v6 }, /* std d,[rs1+%g0] */
-{ "std",	F3(3, 0x27, 1), F3(~3, ~0x27, ~1),		"H,[1+i]", 0, v6 },
-{ "std",	F3(3, 0x27, 1), F3(~3, ~0x27, ~1),		"H,[i+1]", 0, v6 },
-{ "std",	F3(3, 0x27, 1), F3(~3, ~0x27, ~1)|RS1_G0,	"H,[i]", 0, v6 },
-{ "std",	F3(3, 0x27, 1), F3(~3, ~0x27, ~1)|SIMM13(~0),	"H,[1]", 0, v6 }, /* std d,[rs1+0] */
+{ "std",        F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI(~0),      "q,[1+2]", 0, v6notv9 },
+{ "std",        F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI_RS2(~0),  "q,[1]", 0, v6notv9 }, /* std d,[rs1+%g0] */
+{ "std",        F3(3, 0x26, 1), F3(~3, ~0x26, ~1),              "q,[1+i]", 0, v6notv9 },
+{ "std",        F3(3, 0x26, 1), F3(~3, ~0x26, ~1),              "q,[i+1]", 0, v6notv9 },
+{ "std",        F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|RS1_G0,       "q,[i]", 0, v6notv9 },
+{ "std",        F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|SIMM13(~0),   "q,[1]", 0, v6notv9 }, /* std d,[rs1+0] */
+{ "std",        F3(3, 0x27, 0), F3(~3, ~0x27, ~0)|ASI(~0),      "H,[1+2]", 0, v6 },
+{ "std",        F3(3, 0x27, 0), F3(~3, ~0x27, ~0)|ASI_RS2(~0),  "H,[1]", 0, v6 }, /* std d,[rs1+%g0] */
+{ "std",        F3(3, 0x27, 1), F3(~3, ~0x27, ~1),              "H,[1+i]", 0, v6 },
+{ "std",        F3(3, 0x27, 1), F3(~3, ~0x27, ~1),              "H,[i+1]", 0, v6 },
+{ "std",        F3(3, 0x27, 1), F3(~3, ~0x27, ~1)|RS1_G0,       "H,[i]", 0, v6 },
+{ "std",        F3(3, 0x27, 1), F3(~3, ~0x27, ~1)|SIMM13(~0),   "H,[1]", 0, v6 }, /* std d,[rs1+0] */
 
-{ "std",	F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI(~0),	"Q,[1+2]", 0, v6notv9 },
-{ "std",	F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI_RS2(~0),	"Q,[1]", 0, v6notv9 }, /* std d,[rs1+%g0] */
-{ "std",	F3(3, 0x36, 1), F3(~3, ~0x36, ~1),		"Q,[1+i]", 0, v6notv9 },
-{ "std",	F3(3, 0x36, 1), F3(~3, ~0x36, ~1),		"Q,[i+1]", 0, v6notv9 },
-{ "std",	F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|RS1_G0,	"Q,[i]", 0, v6notv9 },
-{ "std",	F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|SIMM13(~0),	"Q,[1]", 0, v6notv9 }, /* std d,[rs1+0] */
-{ "std",	F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI(~0),	"D,[1+2]", 0, v6notv9 },
-{ "std",	F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI_RS2(~0),	"D,[1]", 0, v6notv9 }, /* std d,[rs1+%g0] */
-{ "std",	F3(3, 0x37, 1), F3(~3, ~0x37, ~1),		"D,[1+i]", 0, v6notv9 },
-{ "std",	F3(3, 0x37, 1), F3(~3, ~0x37, ~1),		"D,[i+1]", 0, v6notv9 },
-{ "std",	F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|RS1_G0,	"D,[i]", 0, v6notv9 },
-{ "std",	F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|SIMM13(~0),	"D,[1]", 0, v6notv9 }, /* std d,[rs1+0] */
+{ "std",        F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI(~0),      "Q,[1+2]", 0, v6notv9 },
+{ "std",        F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI_RS2(~0),  "Q,[1]", 0, v6notv9 }, /* std d,[rs1+%g0] */
+{ "std",        F3(3, 0x36, 1), F3(~3, ~0x36, ~1),              "Q,[1+i]", 0, v6notv9 },
+{ "std",        F3(3, 0x36, 1), F3(~3, ~0x36, ~1),              "Q,[i+1]", 0, v6notv9 },
+{ "std",        F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|RS1_G0,       "Q,[i]", 0, v6notv9 },
+{ "std",        F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|SIMM13(~0),   "Q,[1]", 0, v6notv9 }, /* std d,[rs1+0] */
+{ "std",        F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI(~0),      "D,[1+2]", 0, v6notv9 },
+{ "std",        F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI_RS2(~0),  "D,[1]", 0, v6notv9 }, /* std d,[rs1+%g0] */
+{ "std",        F3(3, 0x37, 1), F3(~3, ~0x37, ~1),              "D,[1+i]", 0, v6notv9 },
+{ "std",        F3(3, 0x37, 1), F3(~3, ~0x37, ~1),              "D,[i+1]", 0, v6notv9 },
+{ "std",        F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|RS1_G0,       "D,[i]", 0, v6notv9 },
+{ "std",        F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|SIMM13(~0),   "D,[1]", 0, v6notv9 }, /* std d,[rs1+0] */
 
-{ "spilld",	F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI(~0),	"d,[1+2]", F_ALIAS, v6 },
-{ "spilld",	F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI_RS2(~0),	"d,[1]", F_ALIAS, v6 }, /* std d,[rs1+%g0] */
-{ "spilld",	F3(3, 0x07, 1), F3(~3, ~0x07, ~1),		"d,[1+i]", F_ALIAS, v6 },
-{ "spilld",	F3(3, 0x07, 1), F3(~3, ~0x07, ~1),		"d,[i+1]", F_ALIAS, v6 },
-{ "spilld",	F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|RS1_G0,	"d,[i]", F_ALIAS, v6 },
-{ "spilld",	F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|SIMM13(~0),	"d,[1]", F_ALIAS, v6 }, /* std d,[rs1+0] */
+{ "spilld",     F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI(~0),      "d,[1+2]", F_ALIAS, v6 },
+{ "spilld",     F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI_RS2(~0),  "d,[1]", F_ALIAS, v6 }, /* std d,[rs1+%g0] */
+{ "spilld",     F3(3, 0x07, 1), F3(~3, ~0x07, ~1),              "d,[1+i]", F_ALIAS, v6 },
+{ "spilld",     F3(3, 0x07, 1), F3(~3, ~0x07, ~1),              "d,[i+1]", F_ALIAS, v6 },
+{ "spilld",     F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|RS1_G0,       "d,[i]", F_ALIAS, v6 },
+{ "spilld",     F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|SIMM13(~0),   "d,[1]", F_ALIAS, v6 }, /* std d,[rs1+0] */
 
-{ "stda",	F3(3, 0x17, 0), F3(~3, ~0x17, ~0),		"d,[1+2]A", 0, v6 },
-{ "stda",	F3(3, 0x17, 0), F3(~3, ~0x17, ~0)|RS2(~0),	"d,[1]A", 0, v6 }, /* stda d,[rs1+%g0] */
-{ "stda",	F3(3, 0x17, 1), F3(~3, ~0x17, ~1),		"d,[1+i]o", 0, v9 },
-{ "stda",	F3(3, 0x17, 1), F3(~3, ~0x17, ~1),		"d,[i+1]o", 0, v9 },
-{ "stda",	F3(3, 0x17, 1), F3(~3, ~0x17, ~1)|RS1_G0,	"d,[i]o", 0, v9 },
-{ "stda",	F3(3, 0x17, 1), F3(~3, ~0x17, ~1)|SIMM13(~0),	"d,[1]o", 0, v9 }, /* std d,[rs1+0] */
-{ "stda",	F3(3, 0x37, 0), F3(~3, ~0x37, ~0),		"H,[1+2]A", 0, v9 },
-{ "stda",	F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|RS2(~0),	"H,[1]A", 0, v9 }, /* stda d,[rs1+%g0] */
-{ "stda",	F3(3, 0x37, 1), F3(~3, ~0x37, ~1),		"H,[1+i]o", 0, v9 },
-{ "stda",	F3(3, 0x37, 1), F3(~3, ~0x37, ~1),		"H,[i+1]o", 0, v9 },
-{ "stda",	F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|RS1_G0,	"H,[i]o", 0, v9 },
-{ "stda",	F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|SIMM13(~0),	"H,[1]o", 0, v9 }, /* std d,[rs1+0] */
+{ "stda",       F3(3, 0x17, 0), F3(~3, ~0x17, ~0),              "d,[1+2]A", 0, v6 },
+{ "stda",       F3(3, 0x17, 0), F3(~3, ~0x17, ~0)|RS2(~0),      "d,[1]A", 0, v6 }, /* stda d,[rs1+%g0] */
+{ "stda",       F3(3, 0x17, 1), F3(~3, ~0x17, ~1),              "d,[1+i]o", 0, v9 },
+{ "stda",       F3(3, 0x17, 1), F3(~3, ~0x17, ~1),              "d,[i+1]o", 0, v9 },
+{ "stda",       F3(3, 0x17, 1), F3(~3, ~0x17, ~1)|RS1_G0,       "d,[i]o", 0, v9 },
+{ "stda",       F3(3, 0x17, 1), F3(~3, ~0x17, ~1)|SIMM13(~0),   "d,[1]o", 0, v9 }, /* std d,[rs1+0] */
+{ "stda",       F3(3, 0x37, 0), F3(~3, ~0x37, ~0),              "H,[1+2]A", 0, v9 },
+{ "stda",       F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|RS2(~0),      "H,[1]A", 0, v9 }, /* stda d,[rs1+%g0] */
+{ "stda",       F3(3, 0x37, 1), F3(~3, ~0x37, ~1),              "H,[1+i]o", 0, v9 },
+{ "stda",       F3(3, 0x37, 1), F3(~3, ~0x37, ~1),              "H,[i+1]o", 0, v9 },
+{ "stda",       F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|RS1_G0,       "H,[i]o", 0, v9 },
+{ "stda",       F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|SIMM13(~0),   "H,[1]o", 0, v9 }, /* std d,[rs1+0] */
 
-{ "sth",	F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI(~0),	"d,[1+2]", 0, v6 },
-{ "sth",	F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI_RS2(~0),	"d,[1]", 0, v6 }, /* sth d,[rs1+%g0] */
-{ "sth",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1),		"d,[1+i]", 0, v6 },
-{ "sth",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1),		"d,[i+1]", 0, v6 },
-{ "sth",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RS1_G0,	"d,[i]", 0, v6 },
-{ "sth",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|SIMM13(~0),	"d,[1]", 0, v6 }, /* sth d,[rs1+0] */
+{ "sth",        F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI(~0),      "d,[1+2]", 0, v6 },
+{ "sth",        F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI_RS2(~0),  "d,[1]", 0, v6 }, /* sth d,[rs1+%g0] */
+{ "sth",        F3(3, 0x06, 1), F3(~3, ~0x06, ~1),              "d,[1+i]", 0, v6 },
+{ "sth",        F3(3, 0x06, 1), F3(~3, ~0x06, ~1),              "d,[i+1]", 0, v6 },
+{ "sth",        F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RS1_G0,       "d,[i]", 0, v6 },
+{ "sth",        F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|SIMM13(~0),   "d,[1]", 0, v6 }, /* sth d,[rs1+0] */
 
-{ "stsh",	F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI(~0),	"d,[1+2]", F_ALIAS, v6 },
-{ "stsh",	F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI_RS2(~0),	"d,[1]", F_ALIAS, v6 }, /* sth d,[rs1+%g0] */
-{ "stsh",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1),		"d,[1+i]", F_ALIAS, v6 },
-{ "stsh",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1),		"d,[i+1]", F_ALIAS, v6 },
-{ "stsh",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RS1_G0,	"d,[i]", F_ALIAS, v6 },
-{ "stsh",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|SIMM13(~0),	"d,[1]", F_ALIAS, v6 }, /* sth d,[rs1+0] */
-{ "stuh",	F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI(~0),	"d,[1+2]", F_ALIAS, v6 },
-{ "stuh",	F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI_RS2(~0),	"d,[1]", F_ALIAS, v6 }, /* sth d,[rs1+%g0] */
-{ "stuh",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1),		"d,[1+i]", F_ALIAS, v6 },
-{ "stuh",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1),		"d,[i+1]", F_ALIAS, v6 },
-{ "stuh",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RS1_G0,	"d,[i]", F_ALIAS, v6 },
-{ "stuh",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|SIMM13(~0),	"d,[1]", F_ALIAS, v6 }, /* sth d,[rs1+0] */
+{ "stsh",       F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI(~0),      "d,[1+2]", F_ALIAS, v6 },
+{ "stsh",       F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI_RS2(~0),  "d,[1]", F_ALIAS, v6 }, /* sth d,[rs1+%g0] */
+{ "stsh",       F3(3, 0x06, 1), F3(~3, ~0x06, ~1),              "d,[1+i]", F_ALIAS, v6 },
+{ "stsh",       F3(3, 0x06, 1), F3(~3, ~0x06, ~1),              "d,[i+1]", F_ALIAS, v6 },
+{ "stsh",       F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RS1_G0,       "d,[i]", F_ALIAS, v6 },
+{ "stsh",       F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|SIMM13(~0),   "d,[1]", F_ALIAS, v6 }, /* sth d,[rs1+0] */
+{ "stuh",       F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI(~0),      "d,[1+2]", F_ALIAS, v6 },
+{ "stuh",       F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI_RS2(~0),  "d,[1]", F_ALIAS, v6 }, /* sth d,[rs1+%g0] */
+{ "stuh",       F3(3, 0x06, 1), F3(~3, ~0x06, ~1),              "d,[1+i]", F_ALIAS, v6 },
+{ "stuh",       F3(3, 0x06, 1), F3(~3, ~0x06, ~1),              "d,[i+1]", F_ALIAS, v6 },
+{ "stuh",       F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RS1_G0,       "d,[i]", F_ALIAS, v6 },
+{ "stuh",       F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|SIMM13(~0),   "d,[1]", F_ALIAS, v6 }, /* sth d,[rs1+0] */
 
-{ "stha",	F3(3, 0x16, 0), F3(~3, ~0x16, ~0),		"d,[1+2]A", 0, v6 },
-{ "stha",	F3(3, 0x16, 0), F3(~3, ~0x16, ~0)|RS2(~0),	"d,[1]A", 0, v6 }, /* stha ,[rs1+%g0] */
-{ "stha",	F3(3, 0x16, 1), F3(~3, ~0x16, ~1),		"d,[1+i]o", 0, v9 },
-{ "stha",	F3(3, 0x16, 1), F3(~3, ~0x16, ~1),		"d,[i+1]o", 0, v9 },
-{ "stha",	F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|RS1_G0,	"d,[i]o", 0, v9 },
-{ "stha",	F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|SIMM13(~0),	"d,[1]o", 0, v9 }, /* sth d,[rs1+0] */
+{ "stha",       F3(3, 0x16, 0), F3(~3, ~0x16, ~0),              "d,[1+2]A", 0, v6 },
+{ "stha",       F3(3, 0x16, 0), F3(~3, ~0x16, ~0)|RS2(~0),      "d,[1]A", 0, v6 }, /* stha ,[rs1+%g0] */
+{ "stha",       F3(3, 0x16, 1), F3(~3, ~0x16, ~1),              "d,[1+i]o", 0, v9 },
+{ "stha",       F3(3, 0x16, 1), F3(~3, ~0x16, ~1),              "d,[i+1]o", 0, v9 },
+{ "stha",       F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|RS1_G0,       "d,[i]o", 0, v9 },
+{ "stha",       F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|SIMM13(~0),   "d,[1]o", 0, v9 }, /* sth d,[rs1+0] */
 
-{ "stsha",	F3(3, 0x16, 0), F3(~3, ~0x16, ~0),		"d,[1+2]A", F_ALIAS, v6 },
-{ "stsha",	F3(3, 0x16, 0), F3(~3, ~0x16, ~0)|RS2(~0),	"d,[1]A", F_ALIAS, v6 }, /* stha ,[rs1+%g0] */
-{ "stsha",	F3(3, 0x16, 1), F3(~3, ~0x16, ~1),		"d,[1+i]o", F_ALIAS, v9 },
-{ "stsha",	F3(3, 0x16, 1), F3(~3, ~0x16, ~1),		"d,[i+1]o", F_ALIAS, v9 },
-{ "stsha",	F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|RS1_G0,	"d,[i]o", F_ALIAS, v9 },
-{ "stsha",	F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|SIMM13(~0),	"d,[1]o", F_ALIAS, v9 }, /* sth d,[rs1+0] */
-{ "stuha",	F3(3, 0x16, 0), F3(~3, ~0x16, ~0),		"d,[1+2]A", F_ALIAS, v6 },
-{ "stuha",	F3(3, 0x16, 0), F3(~3, ~0x16, ~0)|RS2(~0),	"d,[1]A", F_ALIAS, v6 }, /* stha ,[rs1+%g0] */
-{ "stuha",	F3(3, 0x16, 1), F3(~3, ~0x16, ~1),		"d,[1+i]o", F_ALIAS, v9 },
-{ "stuha",	F3(3, 0x16, 1), F3(~3, ~0x16, ~1),		"d,[i+1]o", F_ALIAS, v9 },
-{ "stuha",	F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|RS1_G0,	"d,[i]o", F_ALIAS, v9 },
-{ "stuha",	F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|SIMM13(~0),	"d,[1]o", F_ALIAS, v9 }, /* sth d,[rs1+0] */
+{ "stsha",      F3(3, 0x16, 0), F3(~3, ~0x16, ~0),              "d,[1+2]A", F_ALIAS, v6 },
+{ "stsha",      F3(3, 0x16, 0), F3(~3, ~0x16, ~0)|RS2(~0),      "d,[1]A", F_ALIAS, v6 }, /* stha ,[rs1+%g0] */
+{ "stsha",      F3(3, 0x16, 1), F3(~3, ~0x16, ~1),              "d,[1+i]o", F_ALIAS, v9 },
+{ "stsha",      F3(3, 0x16, 1), F3(~3, ~0x16, ~1),              "d,[i+1]o", F_ALIAS, v9 },
+{ "stsha",      F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|RS1_G0,       "d,[i]o", F_ALIAS, v9 },
+{ "stsha",      F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|SIMM13(~0),   "d,[1]o", F_ALIAS, v9 }, /* sth d,[rs1+0] */
+{ "stuha",      F3(3, 0x16, 0), F3(~3, ~0x16, ~0),              "d,[1+2]A", F_ALIAS, v6 },
+{ "stuha",      F3(3, 0x16, 0), F3(~3, ~0x16, ~0)|RS2(~0),      "d,[1]A", F_ALIAS, v6 }, /* stha ,[rs1+%g0] */
+{ "stuha",      F3(3, 0x16, 1), F3(~3, ~0x16, ~1),              "d,[1+i]o", F_ALIAS, v9 },
+{ "stuha",      F3(3, 0x16, 1), F3(~3, ~0x16, ~1),              "d,[i+1]o", F_ALIAS, v9 },
+{ "stuha",      F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|RS1_G0,       "d,[i]o", F_ALIAS, v9 },
+{ "stuha",      F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|SIMM13(~0),   "d,[1]o", F_ALIAS, v9 }, /* sth d,[rs1+0] */
 
-{ "stx",	F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|ASI(~0),	"d,[1+2]", 0, v9 },
-{ "stx",	F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|ASI_RS2(~0),	"d,[1]", 0, v9 }, /* stx d,[rs1+%g0] */
-{ "stx",	F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1),		"d,[1+i]", 0, v9 },
-{ "stx",	F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1),		"d,[i+1]", 0, v9 },
-{ "stx",	F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RS1_G0,	"d,[i]", 0, v9 },
-{ "stx",	F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|SIMM13(~0),	"d,[1]", 0, v9 }, /* stx d,[rs1+0] */
+{ "stx",        F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|ASI(~0),      "d,[1+2]", 0, v9 },
+{ "stx",        F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|ASI_RS2(~0),  "d,[1]", 0, v9 }, /* stx d,[rs1+%g0] */
+{ "stx",        F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1),              "d,[1+i]", 0, v9 },
+{ "stx",        F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1),              "d,[i+1]", 0, v9 },
+{ "stx",        F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RS1_G0,       "d,[i]", 0, v9 },
+{ "stx",        F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|SIMM13(~0),   "d,[1]", 0, v9 }, /* stx d,[rs1+0] */
 
-{ "stx",	F3(3, 0x25, 0)|RD(1), F3(~3, ~0x25, ~0)|ASI(~0)|RD(~1),	"F,[1+2]", 0, v9 },
-{ "stx",	F3(3, 0x25, 0)|RD(1), F3(~3, ~0x25, ~0)|ASI_RS2(~0)|RD(~1),"F,[1]", 0, v9 }, /* stx d,[rs1+%g0] */
-{ "stx",	F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|RD(~1),		"F,[1+i]", 0, v9 },
-{ "stx",	F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|RD(~1),		"F,[i+1]", 0, v9 },
-{ "stx",	F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|RS1_G0|RD(~1),	"F,[i]", 0, v9 },
-{ "stx",	F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|SIMM13(~0)|RD(~1),"F,[1]", 0, v9 }, /* stx d,[rs1+0] */
+{ "stx",        F3(3, 0x25, 0)|RD(1), F3(~3, ~0x25, ~0)|ASI(~0)|RD(~1), "F,[1+2]", 0, v9 },
+{ "stx",        F3(3, 0x25, 0)|RD(1), F3(~3, ~0x25, ~0)|ASI_RS2(~0)|RD(~1),"F,[1]", 0, v9 }, /* stx d,[rs1+%g0] */
+{ "stx",        F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|RD(~1),         "F,[1+i]", 0, v9 },
+{ "stx",        F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|RD(~1),         "F,[i+1]", 0, v9 },
+{ "stx",        F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|RS1_G0|RD(~1),  "F,[i]", 0, v9 },
+{ "stx",        F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|SIMM13(~0)|RD(~1),"F,[1]", 0, v9 }, /* stx d,[rs1+0] */
 
-{ "stxa",	F3(3, 0x1e, 0), F3(~3, ~0x1e, ~0),		"d,[1+2]A", 0, v9 },
-{ "stxa",	F3(3, 0x1e, 0), F3(~3, ~0x1e, ~0)|RS2(~0),	"d,[1]A", 0, v9 }, /* stxa d,[rs1+%g0] */
-{ "stxa",	F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1),		"d,[1+i]o", 0, v9 },
-{ "stxa",	F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1),		"d,[i+1]o", 0, v9 },
-{ "stxa",	F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1)|RS1_G0,	"d,[i]o", 0, v9 },
-{ "stxa",	F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1)|SIMM13(~0),	"d,[1]o", 0, v9 }, /* stx d,[rs1+0] */
+{ "stxa",       F3(3, 0x1e, 0), F3(~3, ~0x1e, ~0),              "d,[1+2]A", 0, v9 },
+{ "stxa",       F3(3, 0x1e, 0), F3(~3, ~0x1e, ~0)|RS2(~0),      "d,[1]A", 0, v9 }, /* stxa d,[rs1+%g0] */
+{ "stxa",       F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1),              "d,[1+i]o", 0, v9 },
+{ "stxa",       F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1),              "d,[i+1]o", 0, v9 },
+{ "stxa",       F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1)|RS1_G0,       "d,[i]o", 0, v9 },
+{ "stxa",       F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1)|SIMM13(~0),   "d,[1]o", 0, v9 }, /* stx d,[rs1+0] */
 
-{ "stq",	F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI(~0),	"J,[1+2]", 0, v9 },
-{ "stq",	F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI_RS2(~0),	"J,[1]", 0, v9 }, /* stq [rs1+%g0] */
-{ "stq",	F3(3, 0x26, 1), F3(~3, ~0x26, ~1),		"J,[1+i]", 0, v9 },
-{ "stq",	F3(3, 0x26, 1), F3(~3, ~0x26, ~1),		"J,[i+1]", 0, v9 },
-{ "stq",	F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|RS1_G0,	"J,[i]", 0, v9 },
-{ "stq",	F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|SIMM13(~0),	"J,[1]", 0, v9 }, /* stq [rs1+0] */
+{ "stq",        F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI(~0),      "J,[1+2]", 0, v9 },
+{ "stq",        F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI_RS2(~0),  "J,[1]", 0, v9 }, /* stq [rs1+%g0] */
+{ "stq",        F3(3, 0x26, 1), F3(~3, ~0x26, ~1),              "J,[1+i]", 0, v9 },
+{ "stq",        F3(3, 0x26, 1), F3(~3, ~0x26, ~1),              "J,[i+1]", 0, v9 },
+{ "stq",        F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|RS1_G0,       "J,[i]", 0, v9 },
+{ "stq",        F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|SIMM13(~0),   "J,[1]", 0, v9 }, /* stq [rs1+0] */
 
-{ "stqa",	F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI(~0),	"J,[1+2]A", 0, v9 },
-{ "stqa",	F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI_RS2(~0),	"J,[1]A", 0, v9 }, /* stqa [rs1+%g0] */
-{ "stqa",	F3(3, 0x36, 1), F3(~3, ~0x36, ~1),		"J,[1+i]o", 0, v9 },
-{ "stqa",	F3(3, 0x36, 1), F3(~3, ~0x36, ~1),		"J,[i+1]o", 0, v9 },
-{ "stqa",	F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|RS1_G0,	"J,[i]o", 0, v9 },
-{ "stqa",	F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|SIMM13(~0),	"J,[1]o", 0, v9 }, /* stqa [rs1+0] */
+{ "stqa",       F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI(~0),      "J,[1+2]A", 0, v9 },
+{ "stqa",       F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI_RS2(~0),  "J,[1]A", 0, v9 }, /* stqa [rs1+%g0] */
+{ "stqa",       F3(3, 0x36, 1), F3(~3, ~0x36, ~1),              "J,[1+i]o", 0, v9 },
+{ "stqa",       F3(3, 0x36, 1), F3(~3, ~0x36, ~1),              "J,[i+1]o", 0, v9 },
+{ "stqa",       F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|RS1_G0,       "J,[i]o", 0, v9 },
+{ "stqa",       F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|SIMM13(~0),   "J,[1]o", 0, v9 }, /* stqa [rs1+0] */
 
-{ "swap",	F3(3, 0x0f, 0), F3(~3, ~0x0f, ~0)|ASI(~0),	"[1+2],d", 0, v7 },
-{ "swap",	F3(3, 0x0f, 0), F3(~3, ~0x0f, ~0)|ASI_RS2(~0),	"[1],d", 0, v7 }, /* swap [rs1+%g0],d */
-{ "swap",	F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1),		"[1+i],d", 0, v7 },
-{ "swap",	F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1),		"[i+1],d", 0, v7 },
-{ "swap",	F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1)|RS1_G0,	"[i],d", 0, v7 },
-{ "swap",	F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1)|SIMM13(~0),	"[1],d", 0, v7 }, /* swap [rs1+0],d */
+{ "swap",       F3(3, 0x0f, 0), F3(~3, ~0x0f, ~0)|ASI(~0),      "[1+2],d", 0, v7 },
+{ "swap",       F3(3, 0x0f, 0), F3(~3, ~0x0f, ~0)|ASI_RS2(~0),  "[1],d", 0, v7 }, /* swap [rs1+%g0],d */
+{ "swap",       F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1),              "[1+i],d", 0, v7 },
+{ "swap",       F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1),              "[i+1],d", 0, v7 },
+{ "swap",       F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1)|RS1_G0,       "[i],d", 0, v7 },
+{ "swap",       F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1)|SIMM13(~0),   "[1],d", 0, v7 }, /* swap [rs1+0],d */
 
-{ "swapa",	F3(3, 0x1f, 0), F3(~3, ~0x1f, ~0),		"[1+2]A,d", 0, v7 },
-{ "swapa",	F3(3, 0x1f, 0), F3(~3, ~0x1f, ~0)|RS2(~0),	"[1]A,d", 0, v7 }, /* swapa [rs1+%g0],d */
-{ "swapa",	F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1),		"[1+i]o,d", 0, v9 },
-{ "swapa",	F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1),		"[i+1]o,d", 0, v9 },
-{ "swapa",	F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1)|RS1_G0,	"[i]o,d", 0, v9 },
-{ "swapa",	F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1)|SIMM13(~0),	"[1]o,d", 0, v9 }, /* swap [rs1+0],d */
+{ "swapa",      F3(3, 0x1f, 0), F3(~3, ~0x1f, ~0),              "[1+2]A,d", 0, v7 },
+{ "swapa",      F3(3, 0x1f, 0), F3(~3, ~0x1f, ~0)|RS2(~0),      "[1]A,d", 0, v7 }, /* swapa [rs1+%g0],d */
+{ "swapa",      F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1),              "[1+i]o,d", 0, v9 },
+{ "swapa",      F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1),              "[i+1]o,d", 0, v9 },
+{ "swapa",      F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1)|RS1_G0,       "[i]o,d", 0, v9 },
+{ "swapa",      F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1)|SIMM13(~0),   "[1]o,d", 0, v9 }, /* swap [rs1+0],d */
 
-{ "restore",	F3(2, 0x3d, 0), F3(~2, ~0x3d, ~0)|ASI(~0),			"1,2,d", 0, v6 },
-{ "restore",	F3(2, 0x3d, 0), F3(~2, ~0x3d, ~0)|RD_G0|RS1_G0|ASI_RS2(~0),	"", 0, v6 }, /* restore %g0,%g0,%g0 */
-{ "restore",	F3(2, 0x3d, 1), F3(~2, ~0x3d, ~1),				"1,i,d", 0, v6 },
-{ "restore",	F3(2, 0x3d, 1), F3(~2, ~0x3d, ~1)|RD_G0|RS1_G0|SIMM13(~0),	"", 0, v6 }, /* restore %g0,0,%g0 */
+{ "restore",    F3(2, 0x3d, 0), F3(~2, ~0x3d, ~0)|ASI(~0),                      "1,2,d", 0, v6 },
+{ "restore",    F3(2, 0x3d, 0), F3(~2, ~0x3d, ~0)|RD_G0|RS1_G0|ASI_RS2(~0),     "", 0, v6 }, /* restore %g0,%g0,%g0 */
+{ "restore",    F3(2, 0x3d, 1), F3(~2, ~0x3d, ~1),                              "1,i,d", 0, v6 },
+{ "restore",    F3(2, 0x3d, 1), F3(~2, ~0x3d, ~1)|RD_G0|RS1_G0|SIMM13(~0),      "", 0, v6 }, /* restore %g0,0,%g0 */
 
-{ "rett",	F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|RD_G0|ASI(~0),	"1+2", F_UNBR|F_DELAYED, v6 }, /* rett rs1+rs2 */
-{ "rett",	F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|RD_G0|ASI_RS2(~0),	"1", F_UNBR|F_DELAYED, v6 },	/* rett rs1,%g0 */
-{ "rett",	F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0,		"1+i", F_UNBR|F_DELAYED, v6 }, /* rett rs1+X */
-{ "rett",	F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0,		"i+1", F_UNBR|F_DELAYED, v6 }, /* rett X+rs1 */
-{ "rett",	F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|RS1_G0,		"i", F_UNBR|F_DELAYED, v6 }, /* rett X+rs1 */
-{ "rett",	F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|RS1_G0,		"i", F_UNBR|F_DELAYED, v6 },	/* rett X */
-{ "rett",	F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|SIMM13(~0),	"1", F_UNBR|F_DELAYED, v6 },	/* rett rs1+0 */
+{ "rett",       F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|RD_G0|ASI(~0),        "1+2", F_UNBR|F_DELAYED, v6 }, /* rett rs1+rs2 */
+{ "rett",       F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|RD_G0|ASI_RS2(~0),    "1", F_UNBR|F_DELAYED, v6 },    /* rett rs1,%g0 */
+{ "rett",       F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0,                "1+i", F_UNBR|F_DELAYED, v6 }, /* rett rs1+X */
+{ "rett",       F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0,                "i+1", F_UNBR|F_DELAYED, v6 }, /* rett X+rs1 */
+{ "rett",       F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|RS1_G0,         "i", F_UNBR|F_DELAYED, v6 }, /* rett X+rs1 */
+{ "rett",       F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|RS1_G0,         "i", F_UNBR|F_DELAYED, v6 },    /* rett X */
+{ "rett",       F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|SIMM13(~0),     "1", F_UNBR|F_DELAYED, v6 },    /* rett rs1+0 */
 
-{ "save",	F3(2, 0x3c, 0), F3(~2, ~0x3c, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "save",	F3(2, 0x3c, 1), F3(~2, ~0x3c, ~1),		"1,i,d", 0, v6 },
-{ "save",	0x81e00000,	~0x81e00000,			"", F_ALIAS, v6 },
+{ "save",       F3(2, 0x3c, 0), F3(~2, ~0x3c, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "save",       F3(2, 0x3c, 1), F3(~2, ~0x3c, ~1),              "1,i,d", 0, v6 },
+{ "save",       0x81e00000,     ~0x81e00000,                    "", F_ALIAS, v6 },
 
-{ "ret",  F3(2, 0x38, 1)|RS1(0x1f)|SIMM13(8), F3(~2, ~0x38, ~1)|SIMM13(~8),	       "", F_UNBR|F_DELAYED, v6 }, /* jmpl %i7+8,%g0 */
+{ "ret",  F3(2, 0x38, 1)|RS1(0x1f)|SIMM13(8), F3(~2, ~0x38, ~1)|SIMM13(~8),            "", F_UNBR|F_DELAYED, v6 }, /* jmpl %i7+8,%g0 */
 { "retl", F3(2, 0x38, 1)|RS1(0x0f)|SIMM13(8), F3(~2, ~0x38, ~1)|RS1(~0x0f)|SIMM13(~8), "", F_UNBR|F_DELAYED, v6 }, /* jmpl %o7+8,%g0 */
 
-{ "jmpl",	F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|ASI(~0),	"1+2,d", F_JSR|F_DELAYED, v6 },
-{ "jmpl",	F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|ASI_RS2(~0),	"1,d", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+%g0,d */
-{ "jmpl",	F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|SIMM13(~0),	"1,d", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+0,d */
-{ "jmpl",	F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RS1_G0,	"i,d", F_JSR|F_DELAYED, v6 }, /* jmpl %g0+i,d */
-{ "jmpl",	F3(2, 0x38, 1), F3(~2, ~0x38, ~1),		"1+i,d", F_JSR|F_DELAYED, v6 },
-{ "jmpl",	F3(2, 0x38, 1), F3(~2, ~0x38, ~1),		"i+1,d", F_JSR|F_DELAYED, v6 },
+{ "jmpl",       F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|ASI(~0),      "1+2,d", F_JSR|F_DELAYED, v6 },
+{ "jmpl",       F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|ASI_RS2(~0),  "1,d", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+%g0,d */
+{ "jmpl",       F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|SIMM13(~0),   "1,d", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+0,d */
+{ "jmpl",       F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RS1_G0,       "i,d", F_JSR|F_DELAYED, v6 }, /* jmpl %g0+i,d */
+{ "jmpl",       F3(2, 0x38, 1), F3(~2, ~0x38, ~1),              "1+i,d", F_JSR|F_DELAYED, v6 },
+{ "jmpl",       F3(2, 0x38, 1), F3(~2, ~0x38, ~1),              "i+1,d", F_JSR|F_DELAYED, v6 },
 
-{ "done",	F3(2, 0x3e, 0)|RD(0), F3(~2, ~0x3e, ~0)|RD(~0)|RS1_G0|SIMM13(~0),	"", 0, v9 },
-{ "retry",	F3(2, 0x3e, 0)|RD(1), F3(~2, ~0x3e, ~0)|RD(~1)|RS1_G0|SIMM13(~0),	"", 0, v9 },
-{ "saved",	F3(2, 0x31, 0)|RD(0), F3(~2, ~0x31, ~0)|RD(~0)|RS1_G0|SIMM13(~0),	"", 0, v9 },
-{ "restored",	F3(2, 0x31, 0)|RD(1), F3(~2, ~0x31, ~0)|RD(~1)|RS1_G0|SIMM13(~0),	"", 0, v9 },
-{ "sir",	F3(2, 0x30, 1)|RD(0xf), F3(~2, ~0x30, ~1)|RD(~0xf)|RS1_G0,		"i", 0, v9 },
+{ "done",       F3(2, 0x3e, 0)|RD(0), F3(~2, ~0x3e, ~0)|RD(~0)|RS1_G0|SIMM13(~0),       "", 0, v9 },
+{ "retry",      F3(2, 0x3e, 0)|RD(1), F3(~2, ~0x3e, ~0)|RD(~1)|RS1_G0|SIMM13(~0),       "", 0, v9 },
+{ "saved",      F3(2, 0x31, 0)|RD(0), F3(~2, ~0x31, ~0)|RD(~0)|RS1_G0|SIMM13(~0),       "", 0, v9 },
+{ "restored",   F3(2, 0x31, 0)|RD(1), F3(~2, ~0x31, ~0)|RD(~1)|RS1_G0|SIMM13(~0),       "", 0, v9 },
+{ "sir",        F3(2, 0x30, 1)|RD(0xf), F3(~2, ~0x30, ~1)|RD(~0xf)|RS1_G0,              "i", 0, v9 },
 
-{ "flush",	F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI(~0),	"1+2", 0, v8 },
-{ "flush",	F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI_RS2(~0),	"1", 0, v8 }, /* flush rs1+%g0 */
-{ "flush",	F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|SIMM13(~0),	"1", 0, v8 }, /* flush rs1+0 */
-{ "flush",	F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|RS1_G0,	"i", 0, v8 }, /* flush %g0+i */
-{ "flush",	F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1),		"1+i", 0, v8 },
-{ "flush",	F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1),		"i+1", 0, v8 },
+{ "flush",      F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI(~0),      "1+2", 0, v8 },
+{ "flush",      F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI_RS2(~0),  "1", 0, v8 }, /* flush rs1+%g0 */
+{ "flush",      F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|SIMM13(~0),   "1", 0, v8 }, /* flush rs1+0 */
+{ "flush",      F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|RS1_G0,       "i", 0, v8 }, /* flush %g0+i */
+{ "flush",      F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1),              "1+i", 0, v8 },
+{ "flush",      F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1),              "i+1", 0, v8 },
 
 /* IFLUSH was renamed to FLUSH in v8.  */
-{ "iflush",	F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI(~0),	"1+2", F_ALIAS, v6 },
-{ "iflush",	F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI_RS2(~0),	"1", F_ALIAS, v6 }, /* flush rs1+%g0 */
-{ "iflush",	F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|SIMM13(~0),	"1", F_ALIAS, v6 }, /* flush rs1+0 */
-{ "iflush",	F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|RS1_G0,	"i", F_ALIAS, v6 },
-{ "iflush",	F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1),		"1+i", F_ALIAS, v6 },
-{ "iflush",	F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1),		"i+1", F_ALIAS, v6 },
+{ "iflush",     F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI(~0),      "1+2", F_ALIAS, v6 },
+{ "iflush",     F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI_RS2(~0),  "1", F_ALIAS, v6 }, /* flush rs1+%g0 */
+{ "iflush",     F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|SIMM13(~0),   "1", F_ALIAS, v6 }, /* flush rs1+0 */
+{ "iflush",     F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|RS1_G0,       "i", F_ALIAS, v6 },
+{ "iflush",     F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1),              "1+i", F_ALIAS, v6 },
+{ "iflush",     F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1),              "i+1", F_ALIAS, v6 },
 
-{ "return",	F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|ASI(~0),	"1+2", 0, v9 },
-{ "return",	F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|ASI_RS2(~0),	"1", 0, v9 }, /* return rs1+%g0 */
-{ "return",	F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|SIMM13(~0),	"1", 0, v9 }, /* return rs1+0 */
-{ "return",	F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RS1_G0,	"i", 0, v9 }, /* return %g0+i */
-{ "return",	F3(2, 0x39, 1), F3(~2, ~0x39, ~1),		"1+i", 0, v9 },
-{ "return",	F3(2, 0x39, 1), F3(~2, ~0x39, ~1),		"i+1", 0, v9 },
+{ "return",     F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|ASI(~0),      "1+2", 0, v9 },
+{ "return",     F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|ASI_RS2(~0),  "1", 0, v9 }, /* return rs1+%g0 */
+{ "return",     F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|SIMM13(~0),   "1", 0, v9 }, /* return rs1+0 */
+{ "return",     F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RS1_G0,       "i", 0, v9 }, /* return %g0+i */
+{ "return",     F3(2, 0x39, 1), F3(~2, ~0x39, ~1),              "1+i", 0, v9 },
+{ "return",     F3(2, 0x39, 1), F3(~2, ~0x39, ~1),              "i+1", 0, v9 },
 
-{ "flushw",	F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RD_G0|RS1_G0|ASI_RS2(~0),	"", 0, v9 },
+{ "flushw",     F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RD_G0|RS1_G0|ASI_RS2(~0),     "", 0, v9 },
 
-{ "membar",	F3(2, 0x28, 1)|RS1(0xf), F3(~2, ~0x28, ~1)|RD_G0|RS1(~0xf)|SIMM13(~127), "K", 0, v9 },
-{ "stbar",	F3(2, 0x28, 0)|RS1(0xf), F3(~2, ~0x28, ~0)|RD_G0|RS1(~0xf)|SIMM13(~0), "", 0, v8 },
+{ "membar",     F3(2, 0x28, 1)|RS1(0xf), F3(~2, ~0x28, ~1)|RD_G0|RS1(~0xf)|SIMM13(~127), "K", 0, v9 },
+{ "stbar",      F3(2, 0x28, 0)|RS1(0xf), F3(~2, ~0x28, ~0)|RD_G0|RS1(~0xf)|SIMM13(~0), "", 0, v8 },
 
-{ "prefetch",	F3(3, 0x2d, 0), F3(~3, ~0x2d, ~0),		"[1+2],*", 0, v9 },
-{ "prefetch",	F3(3, 0x2d, 0), F3(~3, ~0x2d, ~0)|RS2_G0,	"[1],*", 0, v9 }, /* prefetch [rs1+%g0],prefetch_fcn */
-{ "prefetch",	F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1),		"[1+i],*", 0, v9 },
-{ "prefetch",	F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1),		"[i+1],*", 0, v9 },
-{ "prefetch",	F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1)|RS1_G0,	"[i],*", 0, v9 },
-{ "prefetch",	F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1)|SIMM13(~0),	"[1],*", 0, v9 }, /* prefetch [rs1+0],prefetch_fcn */
-{ "prefetcha",	F3(3, 0x3d, 0), F3(~3, ~0x3d, ~0),		"[1+2]A,*", 0, v9 },
-{ "prefetcha",	F3(3, 0x3d, 0), F3(~3, ~0x3d, ~0)|RS2_G0,	"[1]A,*", 0, v9 }, /* prefetcha [rs1+%g0],prefetch_fcn */
-{ "prefetcha",	F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1),		"[1+i]o,*", 0, v9 },
-{ "prefetcha",	F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1),		"[i+1]o,*", 0, v9 },
-{ "prefetcha",	F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1)|RS1_G0,	"[i]o,*", 0, v9 },
-{ "prefetcha",	F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1)|SIMM13(~0),	"[1]o,*", 0, v9 }, /* prefetcha [rs1+0],d */
+{ "prefetch",   F3(3, 0x2d, 0), F3(~3, ~0x2d, ~0),              "[1+2],*", 0, v9 },
+{ "prefetch",   F3(3, 0x2d, 0), F3(~3, ~0x2d, ~0)|RS2_G0,       "[1],*", 0, v9 }, /* prefetch [rs1+%g0],prefetch_fcn */
+{ "prefetch",   F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1),              "[1+i],*", 0, v9 },
+{ "prefetch",   F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1),              "[i+1],*", 0, v9 },
+{ "prefetch",   F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1)|RS1_G0,       "[i],*", 0, v9 },
+{ "prefetch",   F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1)|SIMM13(~0),   "[1],*", 0, v9 }, /* prefetch [rs1+0],prefetch_fcn */
+{ "prefetcha",  F3(3, 0x3d, 0), F3(~3, ~0x3d, ~0),              "[1+2]A,*", 0, v9 },
+{ "prefetcha",  F3(3, 0x3d, 0), F3(~3, ~0x3d, ~0)|RS2_G0,       "[1]A,*", 0, v9 }, /* prefetcha [rs1+%g0],prefetch_fcn */
+{ "prefetcha",  F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1),              "[1+i]o,*", 0, v9 },
+{ "prefetcha",  F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1),              "[i+1]o,*", 0, v9 },
+{ "prefetcha",  F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1)|RS1_G0,       "[i]o,*", 0, v9 },
+{ "prefetcha",  F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1)|SIMM13(~0),   "[1]o,*", 0, v9 }, /* prefetcha [rs1+0],d */
 
-{ "sll",	F3(2, 0x25, 0), F3(~2, ~0x25, ~0)|(1<<12)|(0x7f<<5),	"1,2,d", 0, v6 },
-{ "sll",	F3(2, 0x25, 1), F3(~2, ~0x25, ~1)|(1<<12)|(0x7f<<5),	"1,X,d", 0, v6 },
-{ "sra",	F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|(0x7f<<5),	"1,2,d", 0, v6 },
-{ "sra",	F3(2, 0x27, 1), F3(~2, ~0x27, ~1)|(1<<12)|(0x7f<<5),	"1,X,d", 0, v6 },
-{ "srl",	F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|(0x7f<<5),	"1,2,d", 0, v6 },
-{ "srl",	F3(2, 0x26, 1), F3(~2, ~0x26, ~1)|(1<<12)|(0x7f<<5),	"1,X,d", 0, v6 },
+{ "sll",        F3(2, 0x25, 0), F3(~2, ~0x25, ~0)|(1<<12)|(0x7f<<5),    "1,2,d", 0, v6 },
+{ "sll",        F3(2, 0x25, 1), F3(~2, ~0x25, ~1)|(1<<12)|(0x7f<<5),    "1,X,d", 0, v6 },
+{ "sra",        F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|(0x7f<<5),    "1,2,d", 0, v6 },
+{ "sra",        F3(2, 0x27, 1), F3(~2, ~0x27, ~1)|(1<<12)|(0x7f<<5),    "1,X,d", 0, v6 },
+{ "srl",        F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|(0x7f<<5),    "1,2,d", 0, v6 },
+{ "srl",        F3(2, 0x26, 1), F3(~2, ~0x26, ~1)|(1<<12)|(0x7f<<5),    "1,X,d", 0, v6 },
 
-{ "sllx",	F3(2, 0x25, 0)|(1<<12), F3(~2, ~0x25, ~0)|(0x7f<<5),	"1,2,d", 0, v9 },
-{ "sllx",	F3(2, 0x25, 1)|(1<<12), F3(~2, ~0x25, ~1)|(0x3f<<6),	"1,Y,d", 0, v9 },
-{ "srax",	F3(2, 0x27, 0)|(1<<12), F3(~2, ~0x27, ~0)|(0x7f<<5),	"1,2,d", 0, v9 },
-{ "srax",	F3(2, 0x27, 1)|(1<<12), F3(~2, ~0x27, ~1)|(0x3f<<6),	"1,Y,d", 0, v9 },
-{ "srlx",	F3(2, 0x26, 0)|(1<<12), F3(~2, ~0x26, ~0)|(0x7f<<5),	"1,2,d", 0, v9 },
-{ "srlx",	F3(2, 0x26, 1)|(1<<12), F3(~2, ~0x26, ~1)|(0x3f<<6),	"1,Y,d", 0, v9 },
+{ "sllx",       F3(2, 0x25, 0)|(1<<12), F3(~2, ~0x25, ~0)|(0x7f<<5),    "1,2,d", 0, v9 },
+{ "sllx",       F3(2, 0x25, 1)|(1<<12), F3(~2, ~0x25, ~1)|(0x3f<<6),    "1,Y,d", 0, v9 },
+{ "srax",       F3(2, 0x27, 0)|(1<<12), F3(~2, ~0x27, ~0)|(0x7f<<5),    "1,2,d", 0, v9 },
+{ "srax",       F3(2, 0x27, 1)|(1<<12), F3(~2, ~0x27, ~1)|(0x3f<<6),    "1,Y,d", 0, v9 },
+{ "srlx",       F3(2, 0x26, 0)|(1<<12), F3(~2, ~0x26, ~0)|(0x7f<<5),    "1,2,d", 0, v9 },
+{ "srlx",       F3(2, 0x26, 1)|(1<<12), F3(~2, ~0x26, ~1)|(0x3f<<6),    "1,Y,d", 0, v9 },
 
-{ "mulscc",	F3(2, 0x24, 0), F3(~2, ~0x24, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "mulscc",	F3(2, 0x24, 1), F3(~2, ~0x24, ~1),		"1,i,d", 0, v6 },
+{ "mulscc",     F3(2, 0x24, 0), F3(~2, ~0x24, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "mulscc",     F3(2, 0x24, 1), F3(~2, ~0x24, ~1),              "1,i,d", 0, v6 },
 
-{ "divscc",	F3(2, 0x1d, 0), F3(~2, ~0x1d, ~0)|ASI(~0),	"1,2,d", 0, sparclite },
-{ "divscc",	F3(2, 0x1d, 1), F3(~2, ~0x1d, ~1),		"1,i,d", 0, sparclite },
+{ "divscc",     F3(2, 0x1d, 0), F3(~2, ~0x1d, ~0)|ASI(~0),      "1,2,d", 0, sparclite },
+{ "divscc",     F3(2, 0x1d, 1), F3(~2, ~0x1d, ~1),              "1,i,d", 0, sparclite },
 
-{ "scan",	F3(2, 0x2c, 0), F3(~2, ~0x2c, ~0)|ASI(~0),	"1,2,d", 0, sparclet|sparclite },
-{ "scan",	F3(2, 0x2c, 1), F3(~2, ~0x2c, ~1),		"1,i,d", 0, sparclet|sparclite },
+{ "scan",       F3(2, 0x2c, 0), F3(~2, ~0x2c, ~0)|ASI(~0),      "1,2,d", 0, sparclet|sparclite },
+{ "scan",       F3(2, 0x2c, 1), F3(~2, ~0x2c, ~1),              "1,i,d", 0, sparclet|sparclite },
 
-{ "popc",	F3(2, 0x2e, 0), F3(~2, ~0x2e, ~0)|RS1_G0|ASI(~0),"2,d", 0, v9 },
-{ "popc",	F3(2, 0x2e, 1), F3(~2, ~0x2e, ~1)|RS1_G0,	"i,d", 0, v9 },
+{ "popc",       F3(2, 0x2e, 0), F3(~2, ~0x2e, ~0)|RS1_G0|ASI(~0),"2,d", 0, v9 },
+{ "popc",       F3(2, 0x2e, 1), F3(~2, ~0x2e, ~1)|RS1_G0,       "i,d", 0, v9 },
 
-{ "clr",	F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|RD_G0|RS1_G0|ASI_RS2(~0),	"d", F_ALIAS, v6 }, /* or %g0,%g0,d */
-{ "clr",	F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|RS1_G0|SIMM13(~0),		"d", F_ALIAS, v6 }, /* or %g0,0,d	*/
-{ "clr",	F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|RD_G0|ASI(~0),		"[1+2]", F_ALIAS, v6 },
-{ "clr",	F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|RD_G0|ASI_RS2(~0),		"[1]", F_ALIAS, v6 }, /* st %g0,[rs1+%g0] */
-{ "clr",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0,			"[1+i]", F_ALIAS, v6 },
-{ "clr",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0,			"[i+1]", F_ALIAS, v6 },
-{ "clr",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0|RS1_G0,			"[i]", F_ALIAS, v6 },
-{ "clr",	F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0|SIMM13(~0),		"[1]", F_ALIAS, v6 }, /* st %g0,[rs1+0] */
+{ "clr",        F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|RD_G0|RS1_G0|ASI_RS2(~0),     "d", F_ALIAS, v6 }, /* or %g0,%g0,d */
+{ "clr",        F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|RS1_G0|SIMM13(~0),            "d", F_ALIAS, v6 }, /* or %g0,0,d       */
+{ "clr",        F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|RD_G0|ASI(~0),                "[1+2]", F_ALIAS, v6 },
+{ "clr",        F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|RD_G0|ASI_RS2(~0),            "[1]", F_ALIAS, v6 }, /* st %g0,[rs1+%g0] */
+{ "clr",        F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0,                        "[1+i]", F_ALIAS, v6 },
+{ "clr",        F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0,                        "[i+1]", F_ALIAS, v6 },
+{ "clr",        F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0|RS1_G0,                 "[i]", F_ALIAS, v6 },
+{ "clr",        F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0|SIMM13(~0),             "[1]", F_ALIAS, v6 }, /* st %g0,[rs1+0] */
 
-{ "clrb",	F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|RD_G0|ASI(~0),	"[1+2]", F_ALIAS, v6 },
-{ "clrb",	F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|RD_G0|ASI_RS2(~0),	"[1]", F_ALIAS, v6 }, /* stb %g0,[rs1+%g0] */
-{ "clrb",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0,		"[1+i]", F_ALIAS, v6 },
-{ "clrb",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0,		"[i+1]", F_ALIAS, v6 },
-{ "clrb",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0|RS1_G0,		"[i]", F_ALIAS, v6 },
-{ "clrb",	F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0|SIMM13(~0),	"[1]", F_ALIAS, v6 }, /* stb %g0,[rs1+0] */
+{ "clrb",       F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|RD_G0|ASI(~0),        "[1+2]", F_ALIAS, v6 },
+{ "clrb",       F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|RD_G0|ASI_RS2(~0),    "[1]", F_ALIAS, v6 }, /* stb %g0,[rs1+%g0] */
+{ "clrb",       F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0,                "[1+i]", F_ALIAS, v6 },
+{ "clrb",       F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0,                "[i+1]", F_ALIAS, v6 },
+{ "clrb",       F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0|RS1_G0,         "[i]", F_ALIAS, v6 },
+{ "clrb",       F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0|SIMM13(~0),     "[1]", F_ALIAS, v6 }, /* stb %g0,[rs1+0] */
 
-{ "clrh",	F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|RD_G0|ASI(~0),	"[1+2]", F_ALIAS, v6 },
-{ "clrh",	F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|RD_G0|ASI_RS2(~0),	"[1]", F_ALIAS, v6 }, /* sth %g0,[rs1+%g0] */
-{ "clrh",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0,		"[1+i]", F_ALIAS, v6 },
-{ "clrh",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0,		"[i+1]", F_ALIAS, v6 },
-{ "clrh",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0|RS1_G0,		"[i]", F_ALIAS, v6 },
-{ "clrh",	F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0|SIMM13(~0),	"[1]", F_ALIAS, v6 }, /* sth %g0,[rs1+0] */
+{ "clrh",       F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|RD_G0|ASI(~0),        "[1+2]", F_ALIAS, v6 },
+{ "clrh",       F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|RD_G0|ASI_RS2(~0),    "[1]", F_ALIAS, v6 }, /* sth %g0,[rs1+%g0] */
+{ "clrh",       F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0,                "[1+i]", F_ALIAS, v6 },
+{ "clrh",       F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0,                "[i+1]", F_ALIAS, v6 },
+{ "clrh",       F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0|RS1_G0,         "[i]", F_ALIAS, v6 },
+{ "clrh",       F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0|SIMM13(~0),     "[1]", F_ALIAS, v6 }, /* sth %g0,[rs1+0] */
 
-{ "clrx",	F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|RD_G0|ASI(~0),	"[1+2]", F_ALIAS, v9 },
-{ "clrx",	F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|RD_G0|ASI_RS2(~0),	"[1]", F_ALIAS, v9 }, /* stx %g0,[rs1+%g0] */
-{ "clrx",	F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0,		"[1+i]", F_ALIAS, v9 },
-{ "clrx",	F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0,		"[i+1]", F_ALIAS, v9 },
-{ "clrx",	F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0|RS1_G0,		"[i]", F_ALIAS, v9 },
-{ "clrx",	F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0|SIMM13(~0),	"[1]", F_ALIAS, v9 }, /* stx %g0,[rs1+0] */
+{ "clrx",       F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|RD_G0|ASI(~0),        "[1+2]", F_ALIAS, v9 },
+{ "clrx",       F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|RD_G0|ASI_RS2(~0),    "[1]", F_ALIAS, v9 }, /* stx %g0,[rs1+%g0] */
+{ "clrx",       F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0,                "[1+i]", F_ALIAS, v9 },
+{ "clrx",       F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0,                "[i+1]", F_ALIAS, v9 },
+{ "clrx",       F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0|RS1_G0,         "[i]", F_ALIAS, v9 },
+{ "clrx",       F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0|SIMM13(~0),     "[1]", F_ALIAS, v9 }, /* stx %g0,[rs1+0] */
 
-{ "orcc",	F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "orcc",	F3(2, 0x12, 1), F3(~2, ~0x12, ~1),		"1,i,d", 0, v6 },
-{ "orcc",	F3(2, 0x12, 1), F3(~2, ~0x12, ~1),		"i,1,d", 0, v6 },
+{ "orcc",       F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "orcc",       F3(2, 0x12, 1), F3(~2, ~0x12, ~1),              "1,i,d", 0, v6 },
+{ "orcc",       F3(2, 0x12, 1), F3(~2, ~0x12, ~1),              "i,1,d", 0, v6 },
 
 /* This is not a commutative instruction.  */
-{ "orncc",	F3(2, 0x16, 0), F3(~2, ~0x16, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "orncc",	F3(2, 0x16, 1), F3(~2, ~0x16, ~1),		"1,i,d", 0, v6 },
+{ "orncc",      F3(2, 0x16, 0), F3(~2, ~0x16, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "orncc",      F3(2, 0x16, 1), F3(~2, ~0x16, ~1),              "1,i,d", 0, v6 },
 
 /* This is not a commutative instruction.  */
-{ "orn",	F3(2, 0x06, 0), F3(~2, ~0x06, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "orn",	F3(2, 0x06, 1), F3(~2, ~0x06, ~1),		"1,i,d", 0, v6 },
+{ "orn",        F3(2, 0x06, 0), F3(~2, ~0x06, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "orn",        F3(2, 0x06, 1), F3(~2, ~0x06, ~1),              "1,i,d", 0, v6 },
 
-{ "tst",	F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|RD_G0|ASI_RS2(~0),	"1", 0, v6 }, /* orcc rs1, %g0, %g0 */
-{ "tst",	F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|RD_G0|RS1_G0|ASI(~0),	"2", 0, v6 }, /* orcc %g0, rs2, %g0 */
-{ "tst",	F3(2, 0x12, 1), F3(~2, ~0x12, ~1)|RD_G0|SIMM13(~0),	"1", 0, v6 }, /* orcc rs1, 0, %g0 */
+{ "tst",        F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|RD_G0|ASI_RS2(~0),    "1", 0, v6 }, /* orcc rs1, %g0, %g0 */
+{ "tst",        F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|RD_G0|RS1_G0|ASI(~0), "2", 0, v6 }, /* orcc %g0, rs2, %g0 */
+{ "tst",        F3(2, 0x12, 1), F3(~2, ~0x12, ~1)|RD_G0|SIMM13(~0),     "1", 0, v6 }, /* orcc rs1, 0, %g0 */
 
-{ "wr",	F3(2, 0x30, 0),		F3(~2, ~0x30, ~0)|ASI(~0),		"1,2,m", 0, v8 }, /* wr r,r,%asrX */
-{ "wr",	F3(2, 0x30, 1),		F3(~2, ~0x30, ~1),			"1,i,m", 0, v8 }, /* wr r,i,%asrX */
-{ "wr",	F3(2, 0x30, 0),		F3(~2, ~0x30, ~0)|ASI_RS2(~0),		"1,m", F_ALIAS, v8 }, /* wr rs1,%g0,%asrX */
-{ "wr",	F3(2, 0x30, 0),		F3(~2, ~0x30, ~0)|RD_G0|ASI(~0),	"1,2,y", 0, v6 }, /* wr r,r,%y */
-{ "wr",	F3(2, 0x30, 1),		F3(~2, ~0x30, ~1)|RD_G0,		"1,i,y", 0, v6 }, /* wr r,i,%y */
-{ "wr",	F3(2, 0x30, 0),		F3(~2, ~0x30, ~0)|RD_G0|ASI_RS2(~0),	"1,y", F_ALIAS, v6 }, /* wr rs1,%g0,%y */
-{ "wr",	F3(2, 0x31, 0),		F3(~2, ~0x31, ~0)|RD_G0|ASI(~0),	"1,2,p", 0, v6notv9 }, /* wr r,r,%psr */
-{ "wr",	F3(2, 0x31, 1),		F3(~2, ~0x31, ~1)|RD_G0,		"1,i,p", 0, v6notv9 }, /* wr r,i,%psr */
-{ "wr",	F3(2, 0x31, 0),		F3(~2, ~0x31, ~0)|RD_G0|ASI_RS2(~0),	"1,p", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%psr */
-{ "wr",	F3(2, 0x32, 0),		F3(~2, ~0x32, ~0)|RD_G0|ASI(~0),	"1,2,w", 0, v6notv9 }, /* wr r,r,%wim */
-{ "wr",	F3(2, 0x32, 1),		F3(~2, ~0x32, ~1)|RD_G0,		"1,i,w", 0, v6notv9 }, /* wr r,i,%wim */
-{ "wr",	F3(2, 0x32, 0),		F3(~2, ~0x32, ~0)|RD_G0|ASI_RS2(~0),	"1,w", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%wim */
-{ "wr",	F3(2, 0x33, 0),		F3(~2, ~0x33, ~0)|RD_G0|ASI(~0),	"1,2,t", 0, v6notv9 }, /* wr r,r,%tbr */
-{ "wr",	F3(2, 0x33, 1),		F3(~2, ~0x33, ~1)|RD_G0,		"1,i,t", 0, v6notv9 }, /* wr r,i,%tbr */
-{ "wr",	F3(2, 0x33, 0),		F3(~2, ~0x33, ~0)|RD_G0|ASI_RS2(~0),	"1,t", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%tbr */
+{ "wr", F3(2, 0x30, 0),         F3(~2, ~0x30, ~0)|ASI(~0),              "1,2,m", 0, v8 }, /* wr r,r,%asrX */
+{ "wr", F3(2, 0x30, 1),         F3(~2, ~0x30, ~1),                      "1,i,m", 0, v8 }, /* wr r,i,%asrX */
+{ "wr", F3(2, 0x30, 0),         F3(~2, ~0x30, ~0)|ASI_RS2(~0),          "1,m", F_ALIAS, v8 }, /* wr rs1,%g0,%asrX */
+{ "wr", F3(2, 0x30, 0),         F3(~2, ~0x30, ~0)|RD_G0|ASI(~0),        "1,2,y", 0, v6 }, /* wr r,r,%y */
+{ "wr", F3(2, 0x30, 1),         F3(~2, ~0x30, ~1)|RD_G0,                "1,i,y", 0, v6 }, /* wr r,i,%y */
+{ "wr", F3(2, 0x30, 0),         F3(~2, ~0x30, ~0)|RD_G0|ASI_RS2(~0),    "1,y", F_ALIAS, v6 }, /* wr rs1,%g0,%y */
+{ "wr", F3(2, 0x31, 0),         F3(~2, ~0x31, ~0)|RD_G0|ASI(~0),        "1,2,p", 0, v6notv9 }, /* wr r,r,%psr */
+{ "wr", F3(2, 0x31, 1),         F3(~2, ~0x31, ~1)|RD_G0,                "1,i,p", 0, v6notv9 }, /* wr r,i,%psr */
+{ "wr", F3(2, 0x31, 0),         F3(~2, ~0x31, ~0)|RD_G0|ASI_RS2(~0),    "1,p", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%psr */
+{ "wr", F3(2, 0x32, 0),         F3(~2, ~0x32, ~0)|RD_G0|ASI(~0),        "1,2,w", 0, v6notv9 }, /* wr r,r,%wim */
+{ "wr", F3(2, 0x32, 1),         F3(~2, ~0x32, ~1)|RD_G0,                "1,i,w", 0, v6notv9 }, /* wr r,i,%wim */
+{ "wr", F3(2, 0x32, 0),         F3(~2, ~0x32, ~0)|RD_G0|ASI_RS2(~0),    "1,w", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%wim */
+{ "wr", F3(2, 0x33, 0),         F3(~2, ~0x33, ~0)|RD_G0|ASI(~0),        "1,2,t", 0, v6notv9 }, /* wr r,r,%tbr */
+{ "wr", F3(2, 0x33, 1),         F3(~2, ~0x33, ~1)|RD_G0,                "1,i,t", 0, v6notv9 }, /* wr r,i,%tbr */
+{ "wr", F3(2, 0x33, 0),         F3(~2, ~0x33, ~0)|RD_G0|ASI_RS2(~0),    "1,t", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%tbr */
 
-{ "wr", F3(2, 0x30, 0)|RD(2),	F3(~2, ~0x30, ~0)|RD(~2)|ASI(~0),	"1,2,E", 0, v9 }, /* wr r,r,%ccr */
-{ "wr", F3(2, 0x30, 1)|RD(2),	F3(~2, ~0x30, ~1)|RD(~2),		"1,i,E", 0, v9 }, /* wr r,i,%ccr */
-{ "wr", F3(2, 0x30, 0)|RD(3),	F3(~2, ~0x30, ~0)|RD(~3)|ASI(~0),	"1,2,o", 0, v9 }, /* wr r,r,%asi */
-{ "wr", F3(2, 0x30, 1)|RD(3),	F3(~2, ~0x30, ~1)|RD(~3),		"1,i,o", 0, v9 }, /* wr r,i,%asi */
-{ "wr", F3(2, 0x30, 0)|RD(6),	F3(~2, ~0x30, ~0)|RD(~6)|ASI(~0),	"1,2,s", 0, v9 }, /* wr r,r,%fprs */
-{ "wr", F3(2, 0x30, 1)|RD(6),	F3(~2, ~0x30, ~1)|RD(~6),		"1,i,s", 0, v9 }, /* wr r,i,%fprs */
+{ "wr", F3(2, 0x30, 0)|RD(2),   F3(~2, ~0x30, ~0)|RD(~2)|ASI(~0),       "1,2,E", 0, v9 }, /* wr r,r,%ccr */
+{ "wr", F3(2, 0x30, 1)|RD(2),   F3(~2, ~0x30, ~1)|RD(~2),               "1,i,E", 0, v9 }, /* wr r,i,%ccr */
+{ "wr", F3(2, 0x30, 0)|RD(3),   F3(~2, ~0x30, ~0)|RD(~3)|ASI(~0),       "1,2,o", 0, v9 }, /* wr r,r,%asi */
+{ "wr", F3(2, 0x30, 1)|RD(3),   F3(~2, ~0x30, ~1)|RD(~3),               "1,i,o", 0, v9 }, /* wr r,i,%asi */
+{ "wr", F3(2, 0x30, 0)|RD(6),   F3(~2, ~0x30, ~0)|RD(~6)|ASI(~0),       "1,2,s", 0, v9 }, /* wr r,r,%fprs */
+{ "wr", F3(2, 0x30, 1)|RD(6),   F3(~2, ~0x30, ~1)|RD(~6),               "1,i,s", 0, v9 }, /* wr r,i,%fprs */
 
-{ "wr", F3(2, 0x30, 0)|RD(16),	F3(~2, ~0x30, ~0)|RD(~16)|ASI(~0),	"1,2,_", 0, v9a }, /* wr r,r,%pcr */
-{ "wr", F3(2, 0x30, 1)|RD(16),	F3(~2, ~0x30, ~1)|RD(~16),		"1,i,_", 0, v9a }, /* wr r,i,%pcr */
-{ "wr", F3(2, 0x30, 0)|RD(17),	F3(~2, ~0x30, ~0)|RD(~17)|ASI(~0),	"1,2,_", 0, v9a }, /* wr r,r,%pic */
-{ "wr", F3(2, 0x30, 1)|RD(17),	F3(~2, ~0x30, ~1)|RD(~17),		"1,i,_", 0, v9a }, /* wr r,i,%pic */
-{ "wr", F3(2, 0x30, 0)|RD(18),	F3(~2, ~0x30, ~0)|RD(~18)|ASI(~0),	"1,2,_", 0, v9a }, /* wr r,r,%dcr */
-{ "wr", F3(2, 0x30, 1)|RD(18),	F3(~2, ~0x30, ~1)|RD(~18),		"1,i,_", 0, v9a }, /* wr r,i,%dcr */
-{ "wr", F3(2, 0x30, 0)|RD(19),	F3(~2, ~0x30, ~0)|RD(~19)|ASI(~0),	"1,2,_", 0, v9a }, /* wr r,r,%gsr */
-{ "wr", F3(2, 0x30, 1)|RD(19),	F3(~2, ~0x30, ~1)|RD(~19),		"1,i,_", 0, v9a }, /* wr r,i,%gsr */
-{ "wr", F3(2, 0x30, 0)|RD(20),	F3(~2, ~0x30, ~0)|RD(~20)|ASI(~0),	"1,2,_", 0, v9a }, /* wr r,r,%set_softint */
-{ "wr", F3(2, 0x30, 1)|RD(20),	F3(~2, ~0x30, ~1)|RD(~20),		"1,i,_", 0, v9a }, /* wr r,i,%set_softint */
-{ "wr", F3(2, 0x30, 0)|RD(21),	F3(~2, ~0x30, ~0)|RD(~21)|ASI(~0),	"1,2,_", 0, v9a }, /* wr r,r,%clear_softint */
-{ "wr", F3(2, 0x30, 1)|RD(21),	F3(~2, ~0x30, ~1)|RD(~21),		"1,i,_", 0, v9a }, /* wr r,i,%clear_softint */
-{ "wr", F3(2, 0x30, 0)|RD(22),	F3(~2, ~0x30, ~0)|RD(~22)|ASI(~0),	"1,2,_", 0, v9a }, /* wr r,r,%softint */
-{ "wr", F3(2, 0x30, 1)|RD(22),	F3(~2, ~0x30, ~1)|RD(~22),		"1,i,_", 0, v9a }, /* wr r,i,%softint */
-{ "wr", F3(2, 0x30, 0)|RD(23),	F3(~2, ~0x30, ~0)|RD(~23)|ASI(~0),	"1,2,_", 0, v9a }, /* wr r,r,%tick_cmpr */
-{ "wr", F3(2, 0x30, 1)|RD(23),	F3(~2, ~0x30, ~1)|RD(~23),		"1,i,_", 0, v9a }, /* wr r,i,%tick_cmpr */
-{ "wr", F3(2, 0x30, 0)|RD(24),	F3(~2, ~0x30, ~0)|RD(~24)|ASI(~0),	"1,2,_", 0, v9b }, /* wr r,r,%sys_tick */
-{ "wr", F3(2, 0x30, 1)|RD(24),	F3(~2, ~0x30, ~1)|RD(~24),		"1,i,_", 0, v9b }, /* wr r,i,%sys_tick */
-{ "wr", F3(2, 0x30, 0)|RD(25),	F3(~2, ~0x30, ~0)|RD(~25)|ASI(~0),	"1,2,_", 0, v9b }, /* wr r,r,%sys_tick_cmpr */
-{ "wr", F3(2, 0x30, 1)|RD(25),	F3(~2, ~0x30, ~1)|RD(~25),		"1,i,_", 0, v9b }, /* wr r,i,%sys_tick_cmpr */
+{ "wr", F3(2, 0x30, 0)|RD(16),  F3(~2, ~0x30, ~0)|RD(~16)|ASI(~0),      "1,2,_", 0, v9a }, /* wr r,r,%pcr */
+{ "wr", F3(2, 0x30, 1)|RD(16),  F3(~2, ~0x30, ~1)|RD(~16),              "1,i,_", 0, v9a }, /* wr r,i,%pcr */
+{ "wr", F3(2, 0x30, 0)|RD(17),  F3(~2, ~0x30, ~0)|RD(~17)|ASI(~0),      "1,2,_", 0, v9a }, /* wr r,r,%pic */
+{ "wr", F3(2, 0x30, 1)|RD(17),  F3(~2, ~0x30, ~1)|RD(~17),              "1,i,_", 0, v9a }, /* wr r,i,%pic */
+{ "wr", F3(2, 0x30, 0)|RD(18),  F3(~2, ~0x30, ~0)|RD(~18)|ASI(~0),      "1,2,_", 0, v9a }, /* wr r,r,%dcr */
+{ "wr", F3(2, 0x30, 1)|RD(18),  F3(~2, ~0x30, ~1)|RD(~18),              "1,i,_", 0, v9a }, /* wr r,i,%dcr */
+{ "wr", F3(2, 0x30, 0)|RD(19),  F3(~2, ~0x30, ~0)|RD(~19)|ASI(~0),      "1,2,_", 0, v9a }, /* wr r,r,%gsr */
+{ "wr", F3(2, 0x30, 1)|RD(19),  F3(~2, ~0x30, ~1)|RD(~19),              "1,i,_", 0, v9a }, /* wr r,i,%gsr */
+{ "wr", F3(2, 0x30, 0)|RD(20),  F3(~2, ~0x30, ~0)|RD(~20)|ASI(~0),      "1,2,_", 0, v9a }, /* wr r,r,%set_softint */
+{ "wr", F3(2, 0x30, 1)|RD(20),  F3(~2, ~0x30, ~1)|RD(~20),              "1,i,_", 0, v9a }, /* wr r,i,%set_softint */
+{ "wr", F3(2, 0x30, 0)|RD(21),  F3(~2, ~0x30, ~0)|RD(~21)|ASI(~0),      "1,2,_", 0, v9a }, /* wr r,r,%clear_softint */
+{ "wr", F3(2, 0x30, 1)|RD(21),  F3(~2, ~0x30, ~1)|RD(~21),              "1,i,_", 0, v9a }, /* wr r,i,%clear_softint */
+{ "wr", F3(2, 0x30, 0)|RD(22),  F3(~2, ~0x30, ~0)|RD(~22)|ASI(~0),      "1,2,_", 0, v9a }, /* wr r,r,%softint */
+{ "wr", F3(2, 0x30, 1)|RD(22),  F3(~2, ~0x30, ~1)|RD(~22),              "1,i,_", 0, v9a }, /* wr r,i,%softint */
+{ "wr", F3(2, 0x30, 0)|RD(23),  F3(~2, ~0x30, ~0)|RD(~23)|ASI(~0),      "1,2,_", 0, v9a }, /* wr r,r,%tick_cmpr */
+{ "wr", F3(2, 0x30, 1)|RD(23),  F3(~2, ~0x30, ~1)|RD(~23),              "1,i,_", 0, v9a }, /* wr r,i,%tick_cmpr */
+{ "wr", F3(2, 0x30, 0)|RD(24),  F3(~2, ~0x30, ~0)|RD(~24)|ASI(~0),      "1,2,_", 0, v9b }, /* wr r,r,%sys_tick */
+{ "wr", F3(2, 0x30, 1)|RD(24),  F3(~2, ~0x30, ~1)|RD(~24),              "1,i,_", 0, v9b }, /* wr r,i,%sys_tick */
+{ "wr", F3(2, 0x30, 0)|RD(25),  F3(~2, ~0x30, ~0)|RD(~25)|ASI(~0),      "1,2,_", 0, v9b }, /* wr r,r,%sys_tick_cmpr */
+{ "wr", F3(2, 0x30, 1)|RD(25),  F3(~2, ~0x30, ~1)|RD(~25),              "1,i,_", 0, v9b }, /* wr r,i,%sys_tick_cmpr */
 
-{ "rd",	F3(2, 0x28, 0),			F3(~2, ~0x28, ~0)|SIMM13(~0),		"M,d", 0, v8 }, /* rd %asrX,r */
-{ "rd",	F3(2, 0x28, 0),			F3(~2, ~0x28, ~0)|RS1_G0|SIMM13(~0),	"y,d", 0, v6 }, /* rd %y,r */
-{ "rd",	F3(2, 0x29, 0),			F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0),	"p,d", 0, v6notv9 }, /* rd %psr,r */
-{ "rd",	F3(2, 0x2a, 0),			F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0),	"w,d", 0, v6notv9 }, /* rd %wim,r */
-{ "rd",	F3(2, 0x2b, 0),			F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0),	"t,d", 0, v6notv9 }, /* rd %tbr,r */
+{ "rd", F3(2, 0x28, 0),                 F3(~2, ~0x28, ~0)|SIMM13(~0),           "M,d", 0, v8 }, /* rd %asrX,r */
+{ "rd", F3(2, 0x28, 0),                 F3(~2, ~0x28, ~0)|RS1_G0|SIMM13(~0),    "y,d", 0, v6 }, /* rd %y,r */
+{ "rd", F3(2, 0x29, 0),                 F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0),    "p,d", 0, v6notv9 }, /* rd %psr,r */
+{ "rd", F3(2, 0x2a, 0),                 F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0),    "w,d", 0, v6notv9 }, /* rd %wim,r */
+{ "rd", F3(2, 0x2b, 0),                 F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0),    "t,d", 0, v6notv9 }, /* rd %tbr,r */
 
-{ "rd",	F3(2, 0x28, 0)|RS1(2),		F3(~2, ~0x28, ~0)|RS1(~2)|SIMM13(~0),	"E,d", 0, v9 }, /* rd %ccr,r */
-{ "rd",	F3(2, 0x28, 0)|RS1(3),		F3(~2, ~0x28, ~0)|RS1(~3)|SIMM13(~0),	"o,d", 0, v9 }, /* rd %asi,r */
-{ "rd",	F3(2, 0x28, 0)|RS1(4),		F3(~2, ~0x28, ~0)|RS1(~4)|SIMM13(~0),	"W,d", 0, v9 }, /* rd %tick,r */
-{ "rd",	F3(2, 0x28, 0)|RS1(5),		F3(~2, ~0x28, ~0)|RS1(~5)|SIMM13(~0),	"P,d", 0, v9 }, /* rd %pc,r */
-{ "rd",	F3(2, 0x28, 0)|RS1(6),		F3(~2, ~0x28, ~0)|RS1(~6)|SIMM13(~0),	"s,d", 0, v9 }, /* rd %fprs,r */
+{ "rd", F3(2, 0x28, 0)|RS1(2),          F3(~2, ~0x28, ~0)|RS1(~2)|SIMM13(~0),   "E,d", 0, v9 }, /* rd %ccr,r */
+{ "rd", F3(2, 0x28, 0)|RS1(3),          F3(~2, ~0x28, ~0)|RS1(~3)|SIMM13(~0),   "o,d", 0, v9 }, /* rd %asi,r */
+{ "rd", F3(2, 0x28, 0)|RS1(4),          F3(~2, ~0x28, ~0)|RS1(~4)|SIMM13(~0),   "W,d", 0, v9 }, /* rd %tick,r */
+{ "rd", F3(2, 0x28, 0)|RS1(5),          F3(~2, ~0x28, ~0)|RS1(~5)|SIMM13(~0),   "P,d", 0, v9 }, /* rd %pc,r */
+{ "rd", F3(2, 0x28, 0)|RS1(6),          F3(~2, ~0x28, ~0)|RS1(~6)|SIMM13(~0),   "s,d", 0, v9 }, /* rd %fprs,r */
 
-{ "rd",	F3(2, 0x28, 0)|RS1(16),		F3(~2, ~0x28, ~0)|RS1(~16)|SIMM13(~0),	"/,d", 0, v9a }, /* rd %pcr,r */
-{ "rd",	F3(2, 0x28, 0)|RS1(17),		F3(~2, ~0x28, ~0)|RS1(~17)|SIMM13(~0),	"/,d", 0, v9a }, /* rd %pic,r */
-{ "rd",	F3(2, 0x28, 0)|RS1(18),		F3(~2, ~0x28, ~0)|RS1(~18)|SIMM13(~0),	"/,d", 0, v9a }, /* rd %dcr,r */
-{ "rd",	F3(2, 0x28, 0)|RS1(19),		F3(~2, ~0x28, ~0)|RS1(~19)|SIMM13(~0),	"/,d", 0, v9a }, /* rd %gsr,r */
-{ "rd",	F3(2, 0x28, 0)|RS1(22),		F3(~2, ~0x28, ~0)|RS1(~22)|SIMM13(~0),	"/,d", 0, v9a }, /* rd %softint,r */
-{ "rd",	F3(2, 0x28, 0)|RS1(23),		F3(~2, ~0x28, ~0)|RS1(~23)|SIMM13(~0),	"/,d", 0, v9a }, /* rd %tick_cmpr,r */
-{ "rd",	F3(2, 0x28, 0)|RS1(24),		F3(~2, ~0x28, ~0)|RS1(~24)|SIMM13(~0),	"/,d", 0, v9b }, /* rd %sys_tick,r */
-{ "rd",	F3(2, 0x28, 0)|RS1(25),		F3(~2, ~0x28, ~0)|RS1(~25)|SIMM13(~0),	"/,d", 0, v9b }, /* rd %sys_tick_cmpr,r */
+{ "rd", F3(2, 0x28, 0)|RS1(16),         F3(~2, ~0x28, ~0)|RS1(~16)|SIMM13(~0),  "/,d", 0, v9a }, /* rd %pcr,r */
+{ "rd", F3(2, 0x28, 0)|RS1(17),         F3(~2, ~0x28, ~0)|RS1(~17)|SIMM13(~0),  "/,d", 0, v9a }, /* rd %pic,r */
+{ "rd", F3(2, 0x28, 0)|RS1(18),         F3(~2, ~0x28, ~0)|RS1(~18)|SIMM13(~0),  "/,d", 0, v9a }, /* rd %dcr,r */
+{ "rd", F3(2, 0x28, 0)|RS1(19),         F3(~2, ~0x28, ~0)|RS1(~19)|SIMM13(~0),  "/,d", 0, v9a }, /* rd %gsr,r */
+{ "rd", F3(2, 0x28, 0)|RS1(22),         F3(~2, ~0x28, ~0)|RS1(~22)|SIMM13(~0),  "/,d", 0, v9a }, /* rd %softint,r */
+{ "rd", F3(2, 0x28, 0)|RS1(23),         F3(~2, ~0x28, ~0)|RS1(~23)|SIMM13(~0),  "/,d", 0, v9a }, /* rd %tick_cmpr,r */
+{ "rd", F3(2, 0x28, 0)|RS1(24),         F3(~2, ~0x28, ~0)|RS1(~24)|SIMM13(~0),  "/,d", 0, v9b }, /* rd %sys_tick,r */
+{ "rd", F3(2, 0x28, 0)|RS1(25),         F3(~2, ~0x28, ~0)|RS1(~25)|SIMM13(~0),  "/,d", 0, v9b }, /* rd %sys_tick_cmpr,r */
 
-{ "rdpr",	F3(2, 0x2a, 0),		F3(~2, ~0x2a, ~0)|SIMM13(~0),	"?,d", 0, v9 },   /* rdpr %priv,r */
-{ "wrpr",	F3(2, 0x32, 0),		F3(~2, ~0x32, ~0),		"1,2,!", 0, v9 }, /* wrpr r1,r2,%priv */
-{ "wrpr",	F3(2, 0x32, 0),		F3(~2, ~0x32, ~0)|SIMM13(~0),	"1,!", 0, v9 },   /* wrpr r1,%priv */
-{ "wrpr",	F3(2, 0x32, 1),		F3(~2, ~0x32, ~1),		"1,i,!", 0, v9 }, /* wrpr r1,i,%priv */
-{ "wrpr",	F3(2, 0x32, 1),		F3(~2, ~0x32, ~1),		"i,1,!", F_ALIAS, v9 }, /* wrpr i,r1,%priv */
-{ "wrpr",	F3(2, 0x32, 1),		F3(~2, ~0x32, ~1)|RS1(~0),	"i,!", 0, v9 },   /* wrpr i,%priv */
+{ "rdpr",       F3(2, 0x2a, 0),         F3(~2, ~0x2a, ~0)|SIMM13(~0),   "?,d", 0, v9 },   /* rdpr %priv,r */
+{ "wrpr",       F3(2, 0x32, 0),         F3(~2, ~0x32, ~0),              "1,2,!", 0, v9 }, /* wrpr r1,r2,%priv */
+{ "wrpr",       F3(2, 0x32, 0),         F3(~2, ~0x32, ~0)|SIMM13(~0),   "1,!", 0, v9 },   /* wrpr r1,%priv */
+{ "wrpr",       F3(2, 0x32, 1),         F3(~2, ~0x32, ~1),              "1,i,!", 0, v9 }, /* wrpr r1,i,%priv */
+{ "wrpr",       F3(2, 0x32, 1),         F3(~2, ~0x32, ~1),              "i,1,!", F_ALIAS, v9 }, /* wrpr i,r1,%priv */
+{ "wrpr",       F3(2, 0x32, 1),         F3(~2, ~0x32, ~1)|RS1(~0),      "i,!", 0, v9 },   /* wrpr i,%priv */
 
 /* ??? This group seems wrong.  A three operand move?  */
-{ "mov",	F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI(~0),		"1,2,m", F_ALIAS, v8 }, /* wr r,r,%asrX */
-{ "mov",	F3(2, 0x30, 1), F3(~2, ~0x30, ~1),			"1,i,m", F_ALIAS, v8 }, /* wr r,i,%asrX */
-{ "mov",	F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|ASI(~0),	"1,2,y", F_ALIAS, v6 }, /* wr r,r,%y */
-{ "mov",	F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0,		"1,i,y", F_ALIAS, v6 }, /* wr r,i,%y */
-{ "mov",	F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI(~0),	"1,2,p", F_ALIAS, v6notv9 }, /* wr r,r,%psr */
-{ "mov",	F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0,		"1,i,p", F_ALIAS, v6notv9 }, /* wr r,i,%psr */
-{ "mov",	F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI(~0),	"1,2,w", F_ALIAS, v6notv9 }, /* wr r,r,%wim */
-{ "mov",	F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0,		"1,i,w", F_ALIAS, v6notv9 }, /* wr r,i,%wim */
-{ "mov",	F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI(~0),	"1,2,t", F_ALIAS, v6notv9 }, /* wr r,r,%tbr */
-{ "mov",	F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0,		"1,i,t", F_ALIAS, v6notv9 }, /* wr r,i,%tbr */
+{ "mov",        F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI(~0),              "1,2,m", F_ALIAS, v8 }, /* wr r,r,%asrX */
+{ "mov",        F3(2, 0x30, 1), F3(~2, ~0x30, ~1),                      "1,i,m", F_ALIAS, v8 }, /* wr r,i,%asrX */
+{ "mov",        F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|ASI(~0),        "1,2,y", F_ALIAS, v6 }, /* wr r,r,%y */
+{ "mov",        F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0,                "1,i,y", F_ALIAS, v6 }, /* wr r,i,%y */
+{ "mov",        F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI(~0),        "1,2,p", F_ALIAS, v6notv9 }, /* wr r,r,%psr */
+{ "mov",        F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0,                "1,i,p", F_ALIAS, v6notv9 }, /* wr r,i,%psr */
+{ "mov",        F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI(~0),        "1,2,w", F_ALIAS, v6notv9 }, /* wr r,r,%wim */
+{ "mov",        F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0,                "1,i,w", F_ALIAS, v6notv9 }, /* wr r,i,%wim */
+{ "mov",        F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI(~0),        "1,2,t", F_ALIAS, v6notv9 }, /* wr r,r,%tbr */
+{ "mov",        F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0,                "1,i,t", F_ALIAS, v6notv9 }, /* wr r,i,%tbr */
 
-{ "mov",	F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|SIMM13(~0),		"M,d", F_ALIAS, v8 }, /* rd %asr1,r */
-{ "mov",	F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|RS1_G0|SIMM13(~0),	"y,d", F_ALIAS, v6 }, /* rd %y,r */
-{ "mov",	F3(2, 0x29, 0), F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0),	"p,d", F_ALIAS, v6notv9 }, /* rd %psr,r */
-{ "mov",	F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0),	"w,d", F_ALIAS, v6notv9 }, /* rd %wim,r */
-{ "mov",	F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0),	"t,d", F_ALIAS, v6notv9 }, /* rd %tbr,r */
+{ "mov",        F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|SIMM13(~0),           "M,d", F_ALIAS, v8 }, /* rd %asr1,r */
+{ "mov",        F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|RS1_G0|SIMM13(~0),    "y,d", F_ALIAS, v6 }, /* rd %y,r */
+{ "mov",        F3(2, 0x29, 0), F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0),    "p,d", F_ALIAS, v6notv9 }, /* rd %psr,r */
+{ "mov",        F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0),    "w,d", F_ALIAS, v6notv9 }, /* rd %wim,r */
+{ "mov",        F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0),    "t,d", F_ALIAS, v6notv9 }, /* rd %tbr,r */
 
-{ "mov",	F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI_RS2(~0),		"1,m", F_ALIAS, v8 }, /* wr rs1,%g0,%asrX */
-{ "mov",	F3(2, 0x30, 1), F3(~2, ~0x30, ~1),			"i,m", F_ALIAS, v8 }, /* wr %g0,i,%asrX */
-{ "mov",	F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|SIMM13(~0),		"1,m", F_ALIAS, v8 }, /* wr rs1,0,%asrX */
-{ "mov",	F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|ASI_RS2(~0),	"1,y", F_ALIAS, v6 }, /* wr rs1,%g0,%y */
-{ "mov",	F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0,		"i,y", F_ALIAS, v6 }, /* wr %g0,i,%y */
-{ "mov",	F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0|SIMM13(~0),	"1,y", F_ALIAS, v6 }, /* wr rs1,0,%y */
-{ "mov",	F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI_RS2(~0),	"1,p", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%psr */
-{ "mov",	F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0,		"i,p", F_ALIAS, v6notv9 }, /* wr %g0,i,%psr */
-{ "mov",	F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0|SIMM13(~0),	"1,p", F_ALIAS, v6notv9 }, /* wr rs1,0,%psr */
-{ "mov",	F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI_RS2(~0),	"1,w", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%wim */
-{ "mov",	F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0,		"i,w", F_ALIAS, v6notv9 }, /* wr %g0,i,%wim */
-{ "mov",	F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0|SIMM13(~0),	"1,w", F_ALIAS, v6notv9 }, /* wr rs1,0,%wim */
-{ "mov",	F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI_RS2(~0),	"1,t", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%tbr */
-{ "mov",	F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0,		"i,t", F_ALIAS, v6notv9 }, /* wr %g0,i,%tbr */
-{ "mov",	F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0|SIMM13(~0),	"1,t", F_ALIAS, v6notv9 }, /* wr rs1,0,%tbr */
+{ "mov",        F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI_RS2(~0),          "1,m", F_ALIAS, v8 }, /* wr rs1,%g0,%asrX */
+{ "mov",        F3(2, 0x30, 1), F3(~2, ~0x30, ~1),                      "i,m", F_ALIAS, v8 }, /* wr %g0,i,%asrX */
+{ "mov",        F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|SIMM13(~0),           "1,m", F_ALIAS, v8 }, /* wr rs1,0,%asrX */
+{ "mov",        F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|ASI_RS2(~0),    "1,y", F_ALIAS, v6 }, /* wr rs1,%g0,%y */
+{ "mov",        F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0,                "i,y", F_ALIAS, v6 }, /* wr %g0,i,%y */
+{ "mov",        F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0|SIMM13(~0),     "1,y", F_ALIAS, v6 }, /* wr rs1,0,%y */
+{ "mov",        F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI_RS2(~0),    "1,p", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%psr */
+{ "mov",        F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0,                "i,p", F_ALIAS, v6notv9 }, /* wr %g0,i,%psr */
+{ "mov",        F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0|SIMM13(~0),     "1,p", F_ALIAS, v6notv9 }, /* wr rs1,0,%psr */
+{ "mov",        F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI_RS2(~0),    "1,w", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%wim */
+{ "mov",        F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0,                "i,w", F_ALIAS, v6notv9 }, /* wr %g0,i,%wim */
+{ "mov",        F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0|SIMM13(~0),     "1,w", F_ALIAS, v6notv9 }, /* wr rs1,0,%wim */
+{ "mov",        F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI_RS2(~0),    "1,t", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%tbr */
+{ "mov",        F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0,                "i,t", F_ALIAS, v6notv9 }, /* wr %g0,i,%tbr */
+{ "mov",        F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0|SIMM13(~0),     "1,t", F_ALIAS, v6notv9 }, /* wr rs1,0,%tbr */
 
-{ "mov",	F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|RS1_G0|ASI(~0),	"2,d", 0, v6 }, /* or %g0,rs2,d */
-{ "mov",	F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|RS1_G0,		"i,d", 0, v6 }, /* or %g0,i,d	*/
-{ "mov",        F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI_RS2(~0),		"1,d", 0, v6 }, /* or rs1,%g0,d   */
-{ "mov",        F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|SIMM13(~0),		"1,d", 0, v6 }, /* or rs1,0,d */
+{ "mov",        F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|RS1_G0|ASI(~0),       "2,d", 0, v6 }, /* or %g0,rs2,d */
+{ "mov",        F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|RS1_G0,               "i,d", 0, v6 }, /* or %g0,i,d   */
+{ "mov",        F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI_RS2(~0),          "1,d", 0, v6 }, /* or rs1,%g0,d   */
+{ "mov",        F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|SIMM13(~0),           "1,d", 0, v6 }, /* or rs1,0,d */
 
-{ "or",	F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "or",	F3(2, 0x02, 1), F3(~2, ~0x02, ~1),		"1,i,d", 0, v6 },
-{ "or",	F3(2, 0x02, 1), F3(~2, ~0x02, ~1),		"i,1,d", 0, v6 },
+{ "or", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "or", F3(2, 0x02, 1), F3(~2, ~0x02, ~1),              "1,i,d", 0, v6 },
+{ "or", F3(2, 0x02, 1), F3(~2, ~0x02, ~1),              "i,1,d", 0, v6 },
 
-{ "bset",	F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI(~0),	"2,r", F_ALIAS, v6 },	/* or rd,rs2,rd */
-{ "bset",	F3(2, 0x02, 1), F3(~2, ~0x02, ~1),		"i,r", F_ALIAS, v6 },	/* or rd,i,rd */
+{ "bset",       F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI(~0),      "2,r", F_ALIAS, v6 },   /* or rd,rs2,rd */
+{ "bset",       F3(2, 0x02, 1), F3(~2, ~0x02, ~1),              "i,r", F_ALIAS, v6 },   /* or rd,i,rd */
 
 /* This is not a commutative instruction.  */
-{ "andn",	F3(2, 0x05, 0), F3(~2, ~0x05, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "andn",	F3(2, 0x05, 1), F3(~2, ~0x05, ~1),		"1,i,d", 0, v6 },
+{ "andn",       F3(2, 0x05, 0), F3(~2, ~0x05, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "andn",       F3(2, 0x05, 1), F3(~2, ~0x05, ~1),              "1,i,d", 0, v6 },
 
 /* This is not a commutative instruction.  */
-{ "andncc",	F3(2, 0x15, 0), F3(~2, ~0x15, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "andncc",	F3(2, 0x15, 1), F3(~2, ~0x15, ~1),		"1,i,d", 0, v6 },
+{ "andncc",     F3(2, 0x15, 0), F3(~2, ~0x15, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "andncc",     F3(2, 0x15, 1), F3(~2, ~0x15, ~1),              "1,i,d", 0, v6 },
 
-{ "bclr",	F3(2, 0x05, 0), F3(~2, ~0x05, ~0)|ASI(~0),	"2,r", F_ALIAS, v6 },	/* andn rd,rs2,rd */
-{ "bclr",	F3(2, 0x05, 1), F3(~2, ~0x05, ~1),		"i,r", F_ALIAS, v6 },	/* andn rd,i,rd */
+{ "bclr",       F3(2, 0x05, 0), F3(~2, ~0x05, ~0)|ASI(~0),      "2,r", F_ALIAS, v6 },   /* andn rd,rs2,rd */
+{ "bclr",       F3(2, 0x05, 1), F3(~2, ~0x05, ~1),              "i,r", F_ALIAS, v6 },   /* andn rd,i,rd */
 
-{ "cmp",	F3(2, 0x14, 0), F3(~2, ~0x14, ~0)|RD_G0|ASI(~0),	"1,2", 0, v6 },	/* subcc rs1,rs2,%g0 */
-{ "cmp",	F3(2, 0x14, 1), F3(~2, ~0x14, ~1)|RD_G0,		"1,i", 0, v6 },	/* subcc rs1,i,%g0 */
+{ "cmp",        F3(2, 0x14, 0), F3(~2, ~0x14, ~0)|RD_G0|ASI(~0),        "1,2", 0, v6 }, /* subcc rs1,rs2,%g0 */
+{ "cmp",        F3(2, 0x14, 1), F3(~2, ~0x14, ~1)|RD_G0,                "1,i", 0, v6 }, /* subcc rs1,i,%g0 */
 
-{ "sub",	F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "sub",	F3(2, 0x04, 1), F3(~2, ~0x04, ~1),		"1,i,d", 0, v6 },
+{ "sub",        F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "sub",        F3(2, 0x04, 1), F3(~2, ~0x04, ~1),              "1,i,d", 0, v6 },
 
-{ "subcc",	F3(2, 0x14, 0), F3(~2, ~0x14, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "subcc",	F3(2, 0x14, 1), F3(~2, ~0x14, ~1),		"1,i,d", 0, v6 },
+{ "subcc",      F3(2, 0x14, 0), F3(~2, ~0x14, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "subcc",      F3(2, 0x14, 1), F3(~2, ~0x14, ~1),              "1,i,d", 0, v6 },
 
-{ "subx",	F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0),	"1,2,d", 0, v6notv9 },
-{ "subx",	F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1),		"1,i,d", 0, v6notv9 },
-{ "subc",	F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0),	"1,2,d", 0, v9 },
-{ "subc",	F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1),		"1,i,d", 0, v9 },
+{ "subx",       F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0),      "1,2,d", 0, v6notv9 },
+{ "subx",       F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1),              "1,i,d", 0, v6notv9 },
+{ "subc",       F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0),      "1,2,d", 0, v9 },
+{ "subc",       F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1),              "1,i,d", 0, v9 },
 
-{ "subxcc",	F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0),	"1,2,d", 0, v6notv9 },
-{ "subxcc",	F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1),		"1,i,d", 0, v6notv9 },
-{ "subccc",	F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0),	"1,2,d", 0, v9 },
-{ "subccc",	F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1),		"1,i,d", 0, v9 },
+{ "subxcc",     F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0),      "1,2,d", 0, v6notv9 },
+{ "subxcc",     F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1),              "1,i,d", 0, v6notv9 },
+{ "subccc",     F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0),      "1,2,d", 0, v9 },
+{ "subccc",     F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1),              "1,i,d", 0, v9 },
 
-{ "and",	F3(2, 0x01, 0), F3(~2, ~0x01, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "and",	F3(2, 0x01, 1), F3(~2, ~0x01, ~1),		"1,i,d", 0, v6 },
-{ "and",	F3(2, 0x01, 1), F3(~2, ~0x01, ~1),		"i,1,d", 0, v6 },
+{ "and",        F3(2, 0x01, 0), F3(~2, ~0x01, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "and",        F3(2, 0x01, 1), F3(~2, ~0x01, ~1),              "1,i,d", 0, v6 },
+{ "and",        F3(2, 0x01, 1), F3(~2, ~0x01, ~1),              "i,1,d", 0, v6 },
 
-{ "andcc",	F3(2, 0x11, 0), F3(~2, ~0x11, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "andcc",	F3(2, 0x11, 1), F3(~2, ~0x11, ~1),		"1,i,d", 0, v6 },
-{ "andcc",	F3(2, 0x11, 1), F3(~2, ~0x11, ~1),		"i,1,d", 0, v6 },
+{ "andcc",      F3(2, 0x11, 0), F3(~2, ~0x11, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "andcc",      F3(2, 0x11, 1), F3(~2, ~0x11, ~1),              "1,i,d", 0, v6 },
+{ "andcc",      F3(2, 0x11, 1), F3(~2, ~0x11, ~1),              "i,1,d", 0, v6 },
 
-{ "dec",	F3(2, 0x04, 1)|SIMM13(0x1), F3(~2, ~0x04, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 },	/* sub rd,1,rd */
-{ "dec",	F3(2, 0x04, 1),		    F3(~2, ~0x04, ~1),		       "i,r", F_ALIAS, v8 },	/* sub rd,imm,rd */
-{ "deccc",	F3(2, 0x14, 1)|SIMM13(0x1), F3(~2, ~0x14, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 },	/* subcc rd,1,rd */
-{ "deccc",	F3(2, 0x14, 1),		    F3(~2, ~0x14, ~1),		       "i,r", F_ALIAS, v8 },	/* subcc rd,imm,rd */
-{ "inc",	F3(2, 0x00, 1)|SIMM13(0x1), F3(~2, ~0x00, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 },	/* add rd,1,rd */
-{ "inc",	F3(2, 0x00, 1),		    F3(~2, ~0x00, ~1),		       "i,r", F_ALIAS, v8 },	/* add rd,imm,rd */
-{ "inccc",	F3(2, 0x10, 1)|SIMM13(0x1), F3(~2, ~0x10, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 },	/* addcc rd,1,rd */
-{ "inccc",	F3(2, 0x10, 1),		    F3(~2, ~0x10, ~1),		       "i,r", F_ALIAS, v8 },	/* addcc rd,imm,rd */
+{ "dec",        F3(2, 0x04, 1)|SIMM13(0x1), F3(~2, ~0x04, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 },      /* sub rd,1,rd */
+{ "dec",        F3(2, 0x04, 1),             F3(~2, ~0x04, ~1),                 "i,r", F_ALIAS, v8 },    /* sub rd,imm,rd */
+{ "deccc",      F3(2, 0x14, 1)|SIMM13(0x1), F3(~2, ~0x14, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 },      /* subcc rd,1,rd */
+{ "deccc",      F3(2, 0x14, 1),             F3(~2, ~0x14, ~1),                 "i,r", F_ALIAS, v8 },    /* subcc rd,imm,rd */
+{ "inc",        F3(2, 0x00, 1)|SIMM13(0x1), F3(~2, ~0x00, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 },      /* add rd,1,rd */
+{ "inc",        F3(2, 0x00, 1),             F3(~2, ~0x00, ~1),                 "i,r", F_ALIAS, v8 },    /* add rd,imm,rd */
+{ "inccc",      F3(2, 0x10, 1)|SIMM13(0x1), F3(~2, ~0x10, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 },      /* addcc rd,1,rd */
+{ "inccc",      F3(2, 0x10, 1),             F3(~2, ~0x10, ~1),                 "i,r", F_ALIAS, v8 },    /* addcc rd,imm,rd */
 
-{ "btst",	F3(2, 0x11, 0), F3(~2, ~0x11, ~0)|RD_G0|ASI(~0), "1,2", F_ALIAS, v6 },	/* andcc rs1,rs2,%g0 */
-{ "btst",	F3(2, 0x11, 1), F3(~2, ~0x11, ~1)|RD_G0, "i,1", F_ALIAS, v6 },	/* andcc rs1,i,%g0 */
+{ "btst",       F3(2, 0x11, 0), F3(~2, ~0x11, ~0)|RD_G0|ASI(~0), "1,2", F_ALIAS, v6 },  /* andcc rs1,rs2,%g0 */
+{ "btst",       F3(2, 0x11, 1), F3(~2, ~0x11, ~1)|RD_G0, "i,1", F_ALIAS, v6 },  /* andcc rs1,i,%g0 */
 
-{ "neg",	F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|RS1_G0|ASI(~0), "2,d", F_ALIAS, v6 }, /* sub %g0,rs2,rd */
-{ "neg",	F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|RS1_G0|ASI(~0), "O", F_ALIAS, v6 }, /* sub %g0,rd,rd */
+{ "neg",        F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|RS1_G0|ASI(~0), "2,d", F_ALIAS, v6 }, /* sub %g0,rs2,rd */
+{ "neg",        F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|RS1_G0|ASI(~0), "O", F_ALIAS, v6 }, /* sub %g0,rd,rd */
 
-{ "add",	F3(2, 0x00, 0), F3(~2, ~0x00, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "add",	F3(2, 0x00, 1), F3(~2, ~0x00, ~1),		"1,i,d", 0, v6 },
-{ "add",	F3(2, 0x00, 1), F3(~2, ~0x00, ~1),		"i,1,d", 0, v6 },
-{ "addcc",	F3(2, 0x10, 0), F3(~2, ~0x10, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "addcc",	F3(2, 0x10, 1), F3(~2, ~0x10, ~1),		"1,i,d", 0, v6 },
-{ "addcc",	F3(2, 0x10, 1), F3(~2, ~0x10, ~1),		"i,1,d", 0, v6 },
+{ "add",        F3(2, 0x00, 0), F3(~2, ~0x00, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "add",        F3(2, 0x00, 1), F3(~2, ~0x00, ~1),              "1,i,d", 0, v6 },
+{ "add",        F3(2, 0x00, 1), F3(~2, ~0x00, ~1),              "i,1,d", 0, v6 },
+{ "addcc",      F3(2, 0x10, 0), F3(~2, ~0x10, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "addcc",      F3(2, 0x10, 1), F3(~2, ~0x10, ~1),              "1,i,d", 0, v6 },
+{ "addcc",      F3(2, 0x10, 1), F3(~2, ~0x10, ~1),              "i,1,d", 0, v6 },
 
-{ "addx",	F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0),	"1,2,d", 0, v6notv9 },
-{ "addx",	F3(2, 0x08, 1), F3(~2, ~0x08, ~1),		"1,i,d", 0, v6notv9 },
-{ "addx",	F3(2, 0x08, 1), F3(~2, ~0x08, ~1),		"i,1,d", 0, v6notv9 },
-{ "addc",	F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0),	"1,2,d", 0, v9 },
-{ "addc",	F3(2, 0x08, 1), F3(~2, ~0x08, ~1),		"1,i,d", 0, v9 },
-{ "addc",	F3(2, 0x08, 1), F3(~2, ~0x08, ~1),		"i,1,d", 0, v9 },
+{ "addx",       F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0),      "1,2,d", 0, v6notv9 },
+{ "addx",       F3(2, 0x08, 1), F3(~2, ~0x08, ~1),              "1,i,d", 0, v6notv9 },
+{ "addx",       F3(2, 0x08, 1), F3(~2, ~0x08, ~1),              "i,1,d", 0, v6notv9 },
+{ "addc",       F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0),      "1,2,d", 0, v9 },
+{ "addc",       F3(2, 0x08, 1), F3(~2, ~0x08, ~1),              "1,i,d", 0, v9 },
+{ "addc",       F3(2, 0x08, 1), F3(~2, ~0x08, ~1),              "i,1,d", 0, v9 },
 
-{ "addxcc",	F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0),	"1,2,d", 0, v6notv9 },
-{ "addxcc",	F3(2, 0x18, 1), F3(~2, ~0x18, ~1),		"1,i,d", 0, v6notv9 },
-{ "addxcc",	F3(2, 0x18, 1), F3(~2, ~0x18, ~1),		"i,1,d", 0, v6notv9 },
-{ "addccc",	F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0),	"1,2,d", 0, v9 },
-{ "addccc",	F3(2, 0x18, 1), F3(~2, ~0x18, ~1),		"1,i,d", 0, v9 },
-{ "addccc",	F3(2, 0x18, 1), F3(~2, ~0x18, ~1),		"i,1,d", 0, v9 },
+{ "addxcc",     F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0),      "1,2,d", 0, v6notv9 },
+{ "addxcc",     F3(2, 0x18, 1), F3(~2, ~0x18, ~1),              "1,i,d", 0, v6notv9 },
+{ "addxcc",     F3(2, 0x18, 1), F3(~2, ~0x18, ~1),              "i,1,d", 0, v6notv9 },
+{ "addccc",     F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0),      "1,2,d", 0, v9 },
+{ "addccc",     F3(2, 0x18, 1), F3(~2, ~0x18, ~1),              "1,i,d", 0, v9 },
+{ "addccc",     F3(2, 0x18, 1), F3(~2, ~0x18, ~1),              "i,1,d", 0, v9 },
 
-{ "smul",	F3(2, 0x0b, 0), F3(~2, ~0x0b, ~0)|ASI(~0),	"1,2,d", 0, v8 },
-{ "smul",	F3(2, 0x0b, 1), F3(~2, ~0x0b, ~1),		"1,i,d", 0, v8 },
-{ "smul",	F3(2, 0x0b, 1), F3(~2, ~0x0b, ~1),		"i,1,d", 0, v8 },
-{ "smulcc",	F3(2, 0x1b, 0), F3(~2, ~0x1b, ~0)|ASI(~0),	"1,2,d", 0, v8 },
-{ "smulcc",	F3(2, 0x1b, 1), F3(~2, ~0x1b, ~1),		"1,i,d", 0, v8 },
-{ "smulcc",	F3(2, 0x1b, 1), F3(~2, ~0x1b, ~1),		"i,1,d", 0, v8 },
-{ "umul",	F3(2, 0x0a, 0), F3(~2, ~0x0a, ~0)|ASI(~0),	"1,2,d", 0, v8 },
-{ "umul",	F3(2, 0x0a, 1), F3(~2, ~0x0a, ~1),		"1,i,d", 0, v8 },
-{ "umul",	F3(2, 0x0a, 1), F3(~2, ~0x0a, ~1),		"i,1,d", 0, v8 },
-{ "umulcc",	F3(2, 0x1a, 0), F3(~2, ~0x1a, ~0)|ASI(~0),	"1,2,d", 0, v8 },
-{ "umulcc",	F3(2, 0x1a, 1), F3(~2, ~0x1a, ~1),		"1,i,d", 0, v8 },
-{ "umulcc",	F3(2, 0x1a, 1), F3(~2, ~0x1a, ~1),		"i,1,d", 0, v8 },
-{ "sdiv",	F3(2, 0x0f, 0), F3(~2, ~0x0f, ~0)|ASI(~0),	"1,2,d", 0, v8 },
-{ "sdiv",	F3(2, 0x0f, 1), F3(~2, ~0x0f, ~1),		"1,i,d", 0, v8 },
-{ "sdiv",	F3(2, 0x0f, 1), F3(~2, ~0x0f, ~1),		"i,1,d", 0, v8 },
-{ "sdivcc",	F3(2, 0x1f, 0), F3(~2, ~0x1f, ~0)|ASI(~0),	"1,2,d", 0, v8 },
-{ "sdivcc",	F3(2, 0x1f, 1), F3(~2, ~0x1f, ~1),		"1,i,d", 0, v8 },
-{ "sdivcc",	F3(2, 0x1f, 1), F3(~2, ~0x1f, ~1),		"i,1,d", 0, v8 },
-{ "udiv",	F3(2, 0x0e, 0), F3(~2, ~0x0e, ~0)|ASI(~0),	"1,2,d", 0, v8 },
-{ "udiv",	F3(2, 0x0e, 1), F3(~2, ~0x0e, ~1),		"1,i,d", 0, v8 },
-{ "udiv",	F3(2, 0x0e, 1), F3(~2, ~0x0e, ~1),		"i,1,d", 0, v8 },
-{ "udivcc",	F3(2, 0x1e, 0), F3(~2, ~0x1e, ~0)|ASI(~0),	"1,2,d", 0, v8 },
-{ "udivcc",	F3(2, 0x1e, 1), F3(~2, ~0x1e, ~1),		"1,i,d", 0, v8 },
-{ "udivcc",	F3(2, 0x1e, 1), F3(~2, ~0x1e, ~1),		"i,1,d", 0, v8 },
+{ "smul",       F3(2, 0x0b, 0), F3(~2, ~0x0b, ~0)|ASI(~0),      "1,2,d", 0, v8 },
+{ "smul",       F3(2, 0x0b, 1), F3(~2, ~0x0b, ~1),              "1,i,d", 0, v8 },
+{ "smul",       F3(2, 0x0b, 1), F3(~2, ~0x0b, ~1),              "i,1,d", 0, v8 },
+{ "smulcc",     F3(2, 0x1b, 0), F3(~2, ~0x1b, ~0)|ASI(~0),      "1,2,d", 0, v8 },
+{ "smulcc",     F3(2, 0x1b, 1), F3(~2, ~0x1b, ~1),              "1,i,d", 0, v8 },
+{ "smulcc",     F3(2, 0x1b, 1), F3(~2, ~0x1b, ~1),              "i,1,d", 0, v8 },
+{ "umul",       F3(2, 0x0a, 0), F3(~2, ~0x0a, ~0)|ASI(~0),      "1,2,d", 0, v8 },
+{ "umul",       F3(2, 0x0a, 1), F3(~2, ~0x0a, ~1),              "1,i,d", 0, v8 },
+{ "umul",       F3(2, 0x0a, 1), F3(~2, ~0x0a, ~1),              "i,1,d", 0, v8 },
+{ "umulcc",     F3(2, 0x1a, 0), F3(~2, ~0x1a, ~0)|ASI(~0),      "1,2,d", 0, v8 },
+{ "umulcc",     F3(2, 0x1a, 1), F3(~2, ~0x1a, ~1),              "1,i,d", 0, v8 },
+{ "umulcc",     F3(2, 0x1a, 1), F3(~2, ~0x1a, ~1),              "i,1,d", 0, v8 },
+{ "sdiv",       F3(2, 0x0f, 0), F3(~2, ~0x0f, ~0)|ASI(~0),      "1,2,d", 0, v8 },
+{ "sdiv",       F3(2, 0x0f, 1), F3(~2, ~0x0f, ~1),              "1,i,d", 0, v8 },
+{ "sdiv",       F3(2, 0x0f, 1), F3(~2, ~0x0f, ~1),              "i,1,d", 0, v8 },
+{ "sdivcc",     F3(2, 0x1f, 0), F3(~2, ~0x1f, ~0)|ASI(~0),      "1,2,d", 0, v8 },
+{ "sdivcc",     F3(2, 0x1f, 1), F3(~2, ~0x1f, ~1),              "1,i,d", 0, v8 },
+{ "sdivcc",     F3(2, 0x1f, 1), F3(~2, ~0x1f, ~1),              "i,1,d", 0, v8 },
+{ "udiv",       F3(2, 0x0e, 0), F3(~2, ~0x0e, ~0)|ASI(~0),      "1,2,d", 0, v8 },
+{ "udiv",       F3(2, 0x0e, 1), F3(~2, ~0x0e, ~1),              "1,i,d", 0, v8 },
+{ "udiv",       F3(2, 0x0e, 1), F3(~2, ~0x0e, ~1),              "i,1,d", 0, v8 },
+{ "udivcc",     F3(2, 0x1e, 0), F3(~2, ~0x1e, ~0)|ASI(~0),      "1,2,d", 0, v8 },
+{ "udivcc",     F3(2, 0x1e, 1), F3(~2, ~0x1e, ~1),              "1,i,d", 0, v8 },
+{ "udivcc",     F3(2, 0x1e, 1), F3(~2, ~0x1e, ~1),              "i,1,d", 0, v8 },
 
-{ "mulx",	F3(2, 0x09, 0), F3(~2, ~0x09, ~0)|ASI(~0),	"1,2,d", 0, v9 },
-{ "mulx",	F3(2, 0x09, 1), F3(~2, ~0x09, ~1),		"1,i,d", 0, v9 },
-{ "sdivx",	F3(2, 0x2d, 0), F3(~2, ~0x2d, ~0)|ASI(~0),	"1,2,d", 0, v9 },
-{ "sdivx",	F3(2, 0x2d, 1), F3(~2, ~0x2d, ~1),		"1,i,d", 0, v9 },
-{ "udivx",	F3(2, 0x0d, 0), F3(~2, ~0x0d, ~0)|ASI(~0),	"1,2,d", 0, v9 },
-{ "udivx",	F3(2, 0x0d, 1), F3(~2, ~0x0d, ~1),		"1,i,d", 0, v9 },
+{ "mulx",       F3(2, 0x09, 0), F3(~2, ~0x09, ~0)|ASI(~0),      "1,2,d", 0, v9 },
+{ "mulx",       F3(2, 0x09, 1), F3(~2, ~0x09, ~1),              "1,i,d", 0, v9 },
+{ "sdivx",      F3(2, 0x2d, 0), F3(~2, ~0x2d, ~0)|ASI(~0),      "1,2,d", 0, v9 },
+{ "sdivx",      F3(2, 0x2d, 1), F3(~2, ~0x2d, ~1),              "1,i,d", 0, v9 },
+{ "udivx",      F3(2, 0x0d, 0), F3(~2, ~0x0d, ~0)|ASI(~0),      "1,2,d", 0, v9 },
+{ "udivx",      F3(2, 0x0d, 1), F3(~2, ~0x0d, ~1),              "1,i,d", 0, v9 },
 
-{ "call",	F1(0x1), F1(~0x1), "L", F_JSR|F_DELAYED, v6 },
-{ "call",	F1(0x1), F1(~0x1), "L,#", F_JSR|F_DELAYED, v6 },
+{ "call",       F1(0x1), F1(~0x1), "L", F_JSR|F_DELAYED, v6 },
+{ "call",       F1(0x1), F1(~0x1), "L,#", F_JSR|F_DELAYED, v6 },
 
-{ "call",	F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI(~0),	"1+2", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+rs2,%o7 */
-{ "call",	F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI(~0),	"1+2,#", F_JSR|F_DELAYED, v6 },
-{ "call",	F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI_RS2(~0),	"1", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+%g0,%o7 */
-{ "call",	F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI_RS2(~0),	"1,#", F_JSR|F_DELAYED, v6 },
-{ "call",	F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf),		"1+i", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+i,%o7 */
-{ "call",	F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf),		"1+i,#", F_JSR|F_DELAYED, v6 },
-{ "call",	F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf),		"i+1", F_JSR|F_DELAYED, v6 }, /* jmpl i+rs1,%o7 */
-{ "call",	F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf),		"i+1,#", F_JSR|F_DELAYED, v6 },
-{ "call",	F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|RS1_G0,	"i", F_JSR|F_DELAYED, v6 }, /* jmpl %g0+i,%o7 */
-{ "call",	F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|RS1_G0,	"i,#", F_JSR|F_DELAYED, v6 },
-{ "call",	F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|SIMM13(~0),	"1", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+0,%o7 */
-{ "call",	F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|SIMM13(~0),	"1,#", F_JSR|F_DELAYED, v6 },
+{ "call",       F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI(~0),     "1+2", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+rs2,%o7 */
+{ "call",       F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI(~0),     "1+2,#", F_JSR|F_DELAYED, v6 },
+{ "call",       F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI_RS2(~0), "1", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+%g0,%o7 */
+{ "call",       F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI_RS2(~0), "1,#", F_JSR|F_DELAYED, v6 },
+{ "call",       F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf),             "1+i", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+i,%o7 */
+{ "call",       F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf),             "1+i,#", F_JSR|F_DELAYED, v6 },
+{ "call",       F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf),             "i+1", F_JSR|F_DELAYED, v6 }, /* jmpl i+rs1,%o7 */
+{ "call",       F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf),             "i+1,#", F_JSR|F_DELAYED, v6 },
+{ "call",       F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|RS1_G0,      "i", F_JSR|F_DELAYED, v6 }, /* jmpl %g0+i,%o7 */
+{ "call",       F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|RS1_G0,      "i,#", F_JSR|F_DELAYED, v6 },
+{ "call",       F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|SIMM13(~0),  "1", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+0,%o7 */
+{ "call",       F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|SIMM13(~0),  "1,#", F_JSR|F_DELAYED, v6 },
 
 
 /* Conditional instructions.
@@ -1278,18 +1278,18 @@
 
 /* Define four traps: reg+reg, reg + immediate, immediate alone, reg alone. */
 #define tr(opcode, mask, lose, flags) \
- { opcode, (mask)|(2<<11)|IMMED, (lose)|RS1_G0,	"Z,i",   (flags), v9 }, /* %g0 + imm */ \
- { opcode, (mask)|(2<<11)|IMMED, (lose),	"Z,1+i", (flags), v9 }, /* rs1 + imm */ \
- { opcode, (mask)|(2<<11), IMMED|(lose),	"Z,1+2", (flags), v9 }, /* rs1 + rs2 */ \
- { opcode, (mask)|(2<<11), IMMED|(lose)|RS2_G0,	"Z,1",   (flags), v9 }, /* rs1 + %g0 */ \
- { opcode, (mask)|IMMED, (lose)|RS1_G0,	"z,i",   (flags)|F_ALIAS, v9 }, /* %g0 + imm */ \
- { opcode, (mask)|IMMED, (lose),	"z,1+i", (flags)|F_ALIAS, v9 }, /* rs1 + imm */ \
- { opcode, (mask), IMMED|(lose),	"z,1+2", (flags)|F_ALIAS, v9 }, /* rs1 + rs2 */ \
- { opcode, (mask), IMMED|(lose)|RS2_G0,	"z,1",   (flags)|F_ALIAS, v9 }, /* rs1 + %g0 */ \
- { opcode, (mask)|IMMED, (lose)|RS1_G0,		"i",     (flags), v6 }, /* %g0 + imm */ \
- { opcode, (mask)|IMMED, (lose),		"1+i",   (flags), v6 }, /* rs1 + imm */ \
- { opcode, (mask), IMMED|(lose),		"1+2",   (flags), v6 }, /* rs1 + rs2 */ \
- { opcode, (mask), IMMED|(lose)|RS2_G0,		"1",     (flags), v6 } /* rs1 + %g0 */
+ { opcode, (mask)|(2<<11)|IMMED, (lose)|RS1_G0, "Z,i",   (flags), v9 }, /* %g0 + imm */ \
+ { opcode, (mask)|(2<<11)|IMMED, (lose),        "Z,1+i", (flags), v9 }, /* rs1 + imm */ \
+ { opcode, (mask)|(2<<11), IMMED|(lose),        "Z,1+2", (flags), v9 }, /* rs1 + rs2 */ \
+ { opcode, (mask)|(2<<11), IMMED|(lose)|RS2_G0, "Z,1",   (flags), v9 }, /* rs1 + %g0 */ \
+ { opcode, (mask)|IMMED, (lose)|RS1_G0, "z,i",   (flags)|F_ALIAS, v9 }, /* %g0 + imm */ \
+ { opcode, (mask)|IMMED, (lose),        "z,1+i", (flags)|F_ALIAS, v9 }, /* rs1 + imm */ \
+ { opcode, (mask), IMMED|(lose),        "z,1+2", (flags)|F_ALIAS, v9 }, /* rs1 + rs2 */ \
+ { opcode, (mask), IMMED|(lose)|RS2_G0, "z,1",   (flags)|F_ALIAS, v9 }, /* rs1 + %g0 */ \
+ { opcode, (mask)|IMMED, (lose)|RS1_G0,         "i",     (flags), v6 }, /* %g0 + imm */ \
+ { opcode, (mask)|IMMED, (lose),                "1+i",   (flags), v6 }, /* rs1 + imm */ \
+ { opcode, (mask), IMMED|(lose),                "1+2",   (flags), v6 }, /* rs1 + rs2 */ \
+ { opcode, (mask), IMMED|(lose)|RS2_G0,         "1",     (flags), v6 } /* rs1 + %g0 */
 
 /* v9: We must put `brx' before `br', to ensure that we never match something
    v9: against an expression unless it is an expression.  Otherwise, we end
@@ -1305,32 +1305,32 @@
 /* Define all the conditions, all the branches, all the traps.  */
 
 /* Standard branch, trap mnemonics */
-cond ("b",	"ta",   CONDA, F_UNBR),
+cond ("b",      "ta",   CONDA, F_UNBR),
 /* Alternative form (just for assembly, not for disassembly) */
-cond ("ba",	"t",    CONDA, F_UNBR|F_ALIAS),
+cond ("ba",     "t",    CONDA, F_UNBR|F_ALIAS),
 
-cond ("bcc",	"tcc",  CONDCC, F_CONDBR),
-cond ("bcs",	"tcs",  CONDCS, F_CONDBR),
-cond ("be",	"te",   CONDE, F_CONDBR),
-cond ("beq",	"teq",  CONDE, F_CONDBR|F_ALIAS),
-cond ("bg",	"tg",   CONDG, F_CONDBR),
-cond ("bgt",	"tgt",  CONDG, F_CONDBR|F_ALIAS),
-cond ("bge",	"tge",  CONDGE, F_CONDBR),
-cond ("bgeu",	"tgeu", CONDGEU, F_CONDBR|F_ALIAS), /* for cc */
-cond ("bgu",	"tgu",  CONDGU, F_CONDBR),
-cond ("bl",	"tl",   CONDL, F_CONDBR),
-cond ("blt",	"tlt",  CONDL, F_CONDBR|F_ALIAS),
-cond ("ble",	"tle",  CONDLE, F_CONDBR),
-cond ("bleu",	"tleu", CONDLEU, F_CONDBR),
-cond ("blu",	"tlu",  CONDLU, F_CONDBR|F_ALIAS), /* for cs */
-cond ("bn",	"tn",   CONDN, F_CONDBR),
-cond ("bne",	"tne",  CONDNE, F_CONDBR),
-cond ("bneg",	"tneg", CONDNEG, F_CONDBR),
-cond ("bnz",	"tnz",  CONDNZ, F_CONDBR|F_ALIAS), /* for ne */
-cond ("bpos",	"tpos", CONDPOS, F_CONDBR),
-cond ("bvc",	"tvc",  CONDVC, F_CONDBR),
-cond ("bvs",	"tvs",  CONDVS, F_CONDBR),
-cond ("bz",	"tz",   CONDZ, F_CONDBR|F_ALIAS), /* for e */
+cond ("bcc",    "tcc",  CONDCC, F_CONDBR),
+cond ("bcs",    "tcs",  CONDCS, F_CONDBR),
+cond ("be",     "te",   CONDE, F_CONDBR),
+cond ("beq",    "teq",  CONDE, F_CONDBR|F_ALIAS),
+cond ("bg",     "tg",   CONDG, F_CONDBR),
+cond ("bgt",    "tgt",  CONDG, F_CONDBR|F_ALIAS),
+cond ("bge",    "tge",  CONDGE, F_CONDBR),
+cond ("bgeu",   "tgeu", CONDGEU, F_CONDBR|F_ALIAS), /* for cc */
+cond ("bgu",    "tgu",  CONDGU, F_CONDBR),
+cond ("bl",     "tl",   CONDL, F_CONDBR),
+cond ("blt",    "tlt",  CONDL, F_CONDBR|F_ALIAS),
+cond ("ble",    "tle",  CONDLE, F_CONDBR),
+cond ("bleu",   "tleu", CONDLEU, F_CONDBR),
+cond ("blu",    "tlu",  CONDLU, F_CONDBR|F_ALIAS), /* for cs */
+cond ("bn",     "tn",   CONDN, F_CONDBR),
+cond ("bne",    "tne",  CONDNE, F_CONDBR),
+cond ("bneg",   "tneg", CONDNEG, F_CONDBR),
+cond ("bnz",    "tnz",  CONDNZ, F_CONDBR|F_ALIAS), /* for ne */
+cond ("bpos",   "tpos", CONDPOS, F_CONDBR),
+cond ("bvc",    "tvc",  CONDVC, F_CONDBR),
+cond ("bvs",    "tvs",  CONDVS, F_CONDBR),
+cond ("bz",     "tz",   CONDZ, F_CONDBR|F_ALIAS), /* for e */
 
 #undef cond
 #undef br
@@ -1436,42 +1436,42 @@
   movfcc (opcode, fcond, flags), /* v9 */ \
   movicc (opcode, cond, flags) /* v9 */
 
-/* v9 */ movcc  ("mova",	CONDA, FCONDA, 0),
-/* v9 */ movicc ("movcc",	CONDCC, 0),
-/* v9 */ movicc ("movgeu",	CONDGEU, F_ALIAS),
-/* v9 */ movicc ("movcs",	CONDCS, 0),
-/* v9 */ movicc ("movlu",	CONDLU, F_ALIAS),
-/* v9 */ movcc  ("move",	CONDE, FCONDE, 0),
-/* v9 */ movcc  ("movg",	CONDG, FCONDG, 0),
-/* v9 */ movcc  ("movge",	CONDGE, FCONDGE, 0),
-/* v9 */ movicc ("movgu",	CONDGU, 0),
-/* v9 */ movcc  ("movl",	CONDL, FCONDL, 0),
-/* v9 */ movcc  ("movle",	CONDLE, FCONDLE, 0),
-/* v9 */ movicc ("movleu",	CONDLEU, 0),
-/* v9 */ movfcc ("movlg",	FCONDLG, 0),
-/* v9 */ movcc  ("movn",	CONDN, FCONDN, 0),
-/* v9 */ movcc  ("movne",	CONDNE, FCONDNE, 0),
-/* v9 */ movicc ("movneg",	CONDNEG, 0),
-/* v9 */ movcc  ("movnz",	CONDNZ, FCONDNZ, F_ALIAS),
-/* v9 */ movfcc ("movo",	FCONDO, 0),
-/* v9 */ movicc ("movpos",	CONDPOS, 0),
-/* v9 */ movfcc ("movu",	FCONDU, 0),
-/* v9 */ movfcc ("movue",	FCONDUE, 0),
-/* v9 */ movfcc ("movug",	FCONDUG, 0),
-/* v9 */ movfcc ("movuge",	FCONDUGE, 0),
-/* v9 */ movfcc ("movul",	FCONDUL, 0),
-/* v9 */ movfcc ("movule",	FCONDULE, 0),
-/* v9 */ movicc ("movvc",	CONDVC, 0),
-/* v9 */ movicc ("movvs",	CONDVS, 0),
-/* v9 */ movcc  ("movz",	CONDZ, FCONDZ, F_ALIAS),
+/* v9 */ movcc  ("mova",        CONDA, FCONDA, 0),
+/* v9 */ movicc ("movcc",       CONDCC, 0),
+/* v9 */ movicc ("movgeu",      CONDGEU, F_ALIAS),
+/* v9 */ movicc ("movcs",       CONDCS, 0),
+/* v9 */ movicc ("movlu",       CONDLU, F_ALIAS),
+/* v9 */ movcc  ("move",        CONDE, FCONDE, 0),
+/* v9 */ movcc  ("movg",        CONDG, FCONDG, 0),
+/* v9 */ movcc  ("movge",       CONDGE, FCONDGE, 0),
+/* v9 */ movicc ("movgu",       CONDGU, 0),
+/* v9 */ movcc  ("movl",        CONDL, FCONDL, 0),
+/* v9 */ movcc  ("movle",       CONDLE, FCONDLE, 0),
+/* v9 */ movicc ("movleu",      CONDLEU, 0),
+/* v9 */ movfcc ("movlg",       FCONDLG, 0),
+/* v9 */ movcc  ("movn",        CONDN, FCONDN, 0),
+/* v9 */ movcc  ("movne",       CONDNE, FCONDNE, 0),
+/* v9 */ movicc ("movneg",      CONDNEG, 0),
+/* v9 */ movcc  ("movnz",       CONDNZ, FCONDNZ, F_ALIAS),
+/* v9 */ movfcc ("movo",        FCONDO, 0),
+/* v9 */ movicc ("movpos",      CONDPOS, 0),
+/* v9 */ movfcc ("movu",        FCONDU, 0),
+/* v9 */ movfcc ("movue",       FCONDUE, 0),
+/* v9 */ movfcc ("movug",       FCONDUG, 0),
+/* v9 */ movfcc ("movuge",      FCONDUGE, 0),
+/* v9 */ movfcc ("movul",       FCONDUL, 0),
+/* v9 */ movfcc ("movule",      FCONDULE, 0),
+/* v9 */ movicc ("movvc",       CONDVC, 0),
+/* v9 */ movicc ("movvs",       CONDVS, 0),
+/* v9 */ movcc  ("movz",        CONDZ, FCONDZ, F_ALIAS),
 
 #undef movicc /* v9 */
 #undef movfcc /* v9 */
 #undef movcc /* v9 */
 
-#define FM_SF 1		/* v9 - values for fpsize */
-#define FM_DF 2		/* v9 */
-#define FM_QF 3		/* v9 */
+#define FM_SF 1         /* v9 - values for fpsize */
+#define FM_DF 2         /* v9 */
+#define FM_QF 3         /* v9 */
 
 #define fmovicc(opcode, fpsize, cond, flags) /* v9 */ \
 { opcode, F3F(2, 0x35, 0x100+fpsize)|MCOND(cond,0),  F3F(~2, ~0x35, ~(0x100+fpsize))|MCOND(~cond,~0),  "z,f,g", flags, v9 }, \
@@ -1492,90 +1492,90 @@
 { opcode, F3F(2, 0x35, 0x080+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x080+fpsize))|MCOND(~fcond,~0), "8,f,g", flags | F_FLOAT, v9 }, \
 { opcode, F3F(2, 0x35, 0x0c0+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x0c0+fpsize))|MCOND(~fcond,~0), "9,f,g", flags | F_FLOAT, v9 }
 
-/* v9 */ fmovcc  ("fmovda",	FM_DF, CONDA, FCONDA, 0),
-/* v9 */ fmovcc  ("fmovqa",	FM_QF, CONDA, FCONDA, 0),
-/* v9 */ fmovcc  ("fmovsa",	FM_SF, CONDA, FCONDA, 0),
-/* v9 */ fmovicc ("fmovdcc",	FM_DF, CONDCC, 0),
-/* v9 */ fmovicc ("fmovqcc",	FM_QF, CONDCC, 0),
-/* v9 */ fmovicc ("fmovscc",	FM_SF, CONDCC, 0),
-/* v9 */ fmovicc ("fmovdcs",	FM_DF, CONDCS, 0),
-/* v9 */ fmovicc ("fmovqcs",	FM_QF, CONDCS, 0),
-/* v9 */ fmovicc ("fmovscs",	FM_SF, CONDCS, 0),
-/* v9 */ fmovcc  ("fmovde",	FM_DF, CONDE, FCONDE, 0),
-/* v9 */ fmovcc  ("fmovqe",	FM_QF, CONDE, FCONDE, 0),
-/* v9 */ fmovcc  ("fmovse",	FM_SF, CONDE, FCONDE, 0),
-/* v9 */ fmovcc  ("fmovdg",	FM_DF, CONDG, FCONDG, 0),
-/* v9 */ fmovcc  ("fmovqg",	FM_QF, CONDG, FCONDG, 0),
-/* v9 */ fmovcc  ("fmovsg",	FM_SF, CONDG, FCONDG, 0),
-/* v9 */ fmovcc  ("fmovdge",	FM_DF, CONDGE, FCONDGE, 0),
-/* v9 */ fmovcc  ("fmovqge",	FM_QF, CONDGE, FCONDGE, 0),
-/* v9 */ fmovcc  ("fmovsge",	FM_SF, CONDGE, FCONDGE, 0),
-/* v9 */ fmovicc ("fmovdgeu",	FM_DF, CONDGEU, F_ALIAS),
-/* v9 */ fmovicc ("fmovqgeu",	FM_QF, CONDGEU, F_ALIAS),
-/* v9 */ fmovicc ("fmovsgeu",	FM_SF, CONDGEU, F_ALIAS),
-/* v9 */ fmovicc ("fmovdgu",	FM_DF, CONDGU, 0),
-/* v9 */ fmovicc ("fmovqgu",	FM_QF, CONDGU, 0),
-/* v9 */ fmovicc ("fmovsgu",	FM_SF, CONDGU, 0),
-/* v9 */ fmovcc  ("fmovdl",	FM_DF, CONDL, FCONDL, 0),
-/* v9 */ fmovcc  ("fmovql",	FM_QF, CONDL, FCONDL, 0),
-/* v9 */ fmovcc  ("fmovsl",	FM_SF, CONDL, FCONDL, 0),
-/* v9 */ fmovcc  ("fmovdle",	FM_DF, CONDLE, FCONDLE, 0),
-/* v9 */ fmovcc  ("fmovqle",	FM_QF, CONDLE, FCONDLE, 0),
-/* v9 */ fmovcc  ("fmovsle",	FM_SF, CONDLE, FCONDLE, 0),
-/* v9 */ fmovicc ("fmovdleu",	FM_DF, CONDLEU, 0),
-/* v9 */ fmovicc ("fmovqleu",	FM_QF, CONDLEU, 0),
-/* v9 */ fmovicc ("fmovsleu",	FM_SF, CONDLEU, 0),
-/* v9 */ fmovfcc ("fmovdlg",	FM_DF, FCONDLG, 0),
-/* v9 */ fmovfcc ("fmovqlg",	FM_QF, FCONDLG, 0),
-/* v9 */ fmovfcc ("fmovslg",	FM_SF, FCONDLG, 0),
-/* v9 */ fmovicc ("fmovdlu",	FM_DF, CONDLU, F_ALIAS),
-/* v9 */ fmovicc ("fmovqlu",	FM_QF, CONDLU, F_ALIAS),
-/* v9 */ fmovicc ("fmovslu",	FM_SF, CONDLU, F_ALIAS),
-/* v9 */ fmovcc  ("fmovdn",	FM_DF, CONDN, FCONDN, 0),
-/* v9 */ fmovcc  ("fmovqn",	FM_QF, CONDN, FCONDN, 0),
-/* v9 */ fmovcc  ("fmovsn",	FM_SF, CONDN, FCONDN, 0),
-/* v9 */ fmovcc  ("fmovdne",	FM_DF, CONDNE, FCONDNE, 0),
-/* v9 */ fmovcc  ("fmovqne",	FM_QF, CONDNE, FCONDNE, 0),
-/* v9 */ fmovcc  ("fmovsne",	FM_SF, CONDNE, FCONDNE, 0),
-/* v9 */ fmovicc ("fmovdneg",	FM_DF, CONDNEG, 0),
-/* v9 */ fmovicc ("fmovqneg",	FM_QF, CONDNEG, 0),
-/* v9 */ fmovicc ("fmovsneg",	FM_SF, CONDNEG, 0),
-/* v9 */ fmovcc  ("fmovdnz",	FM_DF, CONDNZ, FCONDNZ, F_ALIAS),
-/* v9 */ fmovcc  ("fmovqnz",	FM_QF, CONDNZ, FCONDNZ, F_ALIAS),
-/* v9 */ fmovcc  ("fmovsnz",	FM_SF, CONDNZ, FCONDNZ, F_ALIAS),
-/* v9 */ fmovfcc ("fmovdo",	FM_DF, FCONDO, 0),
-/* v9 */ fmovfcc ("fmovqo",	FM_QF, FCONDO, 0),
-/* v9 */ fmovfcc ("fmovso",	FM_SF, FCONDO, 0),
-/* v9 */ fmovicc ("fmovdpos",	FM_DF, CONDPOS, 0),
-/* v9 */ fmovicc ("fmovqpos",	FM_QF, CONDPOS, 0),
-/* v9 */ fmovicc ("fmovspos",	FM_SF, CONDPOS, 0),
-/* v9 */ fmovfcc ("fmovdu",	FM_DF, FCONDU, 0),
-/* v9 */ fmovfcc ("fmovqu",	FM_QF, FCONDU, 0),
-/* v9 */ fmovfcc ("fmovsu",	FM_SF, FCONDU, 0),
-/* v9 */ fmovfcc ("fmovdue",	FM_DF, FCONDUE, 0),
-/* v9 */ fmovfcc ("fmovque",	FM_QF, FCONDUE, 0),
-/* v9 */ fmovfcc ("fmovsue",	FM_SF, FCONDUE, 0),
-/* v9 */ fmovfcc ("fmovdug",	FM_DF, FCONDUG, 0),
-/* v9 */ fmovfcc ("fmovqug",	FM_QF, FCONDUG, 0),
-/* v9 */ fmovfcc ("fmovsug",	FM_SF, FCONDUG, 0),
-/* v9 */ fmovfcc ("fmovduge",	FM_DF, FCONDUGE, 0),
-/* v9 */ fmovfcc ("fmovquge",	FM_QF, FCONDUGE, 0),
-/* v9 */ fmovfcc ("fmovsuge",	FM_SF, FCONDUGE, 0),
-/* v9 */ fmovfcc ("fmovdul",	FM_DF, FCONDUL, 0),
-/* v9 */ fmovfcc ("fmovqul",	FM_QF, FCONDUL, 0),
-/* v9 */ fmovfcc ("fmovsul",	FM_SF, FCONDUL, 0),
-/* v9 */ fmovfcc ("fmovdule",	FM_DF, FCONDULE, 0),
-/* v9 */ fmovfcc ("fmovqule",	FM_QF, FCONDULE, 0),
-/* v9 */ fmovfcc ("fmovsule",	FM_SF, FCONDULE, 0),
-/* v9 */ fmovicc ("fmovdvc",	FM_DF, CONDVC, 0),
-/* v9 */ fmovicc ("fmovqvc",	FM_QF, CONDVC, 0),
-/* v9 */ fmovicc ("fmovsvc",	FM_SF, CONDVC, 0),
-/* v9 */ fmovicc ("fmovdvs",	FM_DF, CONDVS, 0),
-/* v9 */ fmovicc ("fmovqvs",	FM_QF, CONDVS, 0),
-/* v9 */ fmovicc ("fmovsvs",	FM_SF, CONDVS, 0),
-/* v9 */ fmovcc  ("fmovdz",	FM_DF, CONDZ, FCONDZ, F_ALIAS),
-/* v9 */ fmovcc  ("fmovqz",	FM_QF, CONDZ, FCONDZ, F_ALIAS),
-/* v9 */ fmovcc  ("fmovsz",	FM_SF, CONDZ, FCONDZ, F_ALIAS),
+/* v9 */ fmovcc  ("fmovda",     FM_DF, CONDA, FCONDA, 0),
+/* v9 */ fmovcc  ("fmovqa",     FM_QF, CONDA, FCONDA, 0),
+/* v9 */ fmovcc  ("fmovsa",     FM_SF, CONDA, FCONDA, 0),
+/* v9 */ fmovicc ("fmovdcc",    FM_DF, CONDCC, 0),
+/* v9 */ fmovicc ("fmovqcc",    FM_QF, CONDCC, 0),
+/* v9 */ fmovicc ("fmovscc",    FM_SF, CONDCC, 0),
+/* v9 */ fmovicc ("fmovdcs",    FM_DF, CONDCS, 0),
+/* v9 */ fmovicc ("fmovqcs",    FM_QF, CONDCS, 0),
+/* v9 */ fmovicc ("fmovscs",    FM_SF, CONDCS, 0),
+/* v9 */ fmovcc  ("fmovde",     FM_DF, CONDE, FCONDE, 0),
+/* v9 */ fmovcc  ("fmovqe",     FM_QF, CONDE, FCONDE, 0),
+/* v9 */ fmovcc  ("fmovse",     FM_SF, CONDE, FCONDE, 0),
+/* v9 */ fmovcc  ("fmovdg",     FM_DF, CONDG, FCONDG, 0),
+/* v9 */ fmovcc  ("fmovqg",     FM_QF, CONDG, FCONDG, 0),
+/* v9 */ fmovcc  ("fmovsg",     FM_SF, CONDG, FCONDG, 0),
+/* v9 */ fmovcc  ("fmovdge",    FM_DF, CONDGE, FCONDGE, 0),
+/* v9 */ fmovcc  ("fmovqge",    FM_QF, CONDGE, FCONDGE, 0),
+/* v9 */ fmovcc  ("fmovsge",    FM_SF, CONDGE, FCONDGE, 0),
+/* v9 */ fmovicc ("fmovdgeu",   FM_DF, CONDGEU, F_ALIAS),
+/* v9 */ fmovicc ("fmovqgeu",   FM_QF, CONDGEU, F_ALIAS),
+/* v9 */ fmovicc ("fmovsgeu",   FM_SF, CONDGEU, F_ALIAS),
+/* v9 */ fmovicc ("fmovdgu",    FM_DF, CONDGU, 0),
+/* v9 */ fmovicc ("fmovqgu",    FM_QF, CONDGU, 0),
+/* v9 */ fmovicc ("fmovsgu",    FM_SF, CONDGU, 0),
+/* v9 */ fmovcc  ("fmovdl",     FM_DF, CONDL, FCONDL, 0),
+/* v9 */ fmovcc  ("fmovql",     FM_QF, CONDL, FCONDL, 0),
+/* v9 */ fmovcc  ("fmovsl",     FM_SF, CONDL, FCONDL, 0),
+/* v9 */ fmovcc  ("fmovdle",    FM_DF, CONDLE, FCONDLE, 0),
+/* v9 */ fmovcc  ("fmovqle",    FM_QF, CONDLE, FCONDLE, 0),
+/* v9 */ fmovcc  ("fmovsle",    FM_SF, CONDLE, FCONDLE, 0),
+/* v9 */ fmovicc ("fmovdleu",   FM_DF, CONDLEU, 0),
+/* v9 */ fmovicc ("fmovqleu",   FM_QF, CONDLEU, 0),
+/* v9 */ fmovicc ("fmovsleu",   FM_SF, CONDLEU, 0),
+/* v9 */ fmovfcc ("fmovdlg",    FM_DF, FCONDLG, 0),
+/* v9 */ fmovfcc ("fmovqlg",    FM_QF, FCONDLG, 0),
+/* v9 */ fmovfcc ("fmovslg",    FM_SF, FCONDLG, 0),
+/* v9 */ fmovicc ("fmovdlu",    FM_DF, CONDLU, F_ALIAS),
+/* v9 */ fmovicc ("fmovqlu",    FM_QF, CONDLU, F_ALIAS),
+/* v9 */ fmovicc ("fmovslu",    FM_SF, CONDLU, F_ALIAS),
+/* v9 */ fmovcc  ("fmovdn",     FM_DF, CONDN, FCONDN, 0),
+/* v9 */ fmovcc  ("fmovqn",     FM_QF, CONDN, FCONDN, 0),
+/* v9 */ fmovcc  ("fmovsn",     FM_SF, CONDN, FCONDN, 0),
+/* v9 */ fmovcc  ("fmovdne",    FM_DF, CONDNE, FCONDNE, 0),
+/* v9 */ fmovcc  ("fmovqne",    FM_QF, CONDNE, FCONDNE, 0),
+/* v9 */ fmovcc  ("fmovsne",    FM_SF, CONDNE, FCONDNE, 0),
+/* v9 */ fmovicc ("fmovdneg",   FM_DF, CONDNEG, 0),
+/* v9 */ fmovicc ("fmovqneg",   FM_QF, CONDNEG, 0),
+/* v9 */ fmovicc ("fmovsneg",   FM_SF, CONDNEG, 0),
+/* v9 */ fmovcc  ("fmovdnz",    FM_DF, CONDNZ, FCONDNZ, F_ALIAS),
+/* v9 */ fmovcc  ("fmovqnz",    FM_QF, CONDNZ, FCONDNZ, F_ALIAS),
+/* v9 */ fmovcc  ("fmovsnz",    FM_SF, CONDNZ, FCONDNZ, F_ALIAS),
+/* v9 */ fmovfcc ("fmovdo",     FM_DF, FCONDO, 0),
+/* v9 */ fmovfcc ("fmovqo",     FM_QF, FCONDO, 0),
+/* v9 */ fmovfcc ("fmovso",     FM_SF, FCONDO, 0),
+/* v9 */ fmovicc ("fmovdpos",   FM_DF, CONDPOS, 0),
+/* v9 */ fmovicc ("fmovqpos",   FM_QF, CONDPOS, 0),
+/* v9 */ fmovicc ("fmovspos",   FM_SF, CONDPOS, 0),
+/* v9 */ fmovfcc ("fmovdu",     FM_DF, FCONDU, 0),
+/* v9 */ fmovfcc ("fmovqu",     FM_QF, FCONDU, 0),
+/* v9 */ fmovfcc ("fmovsu",     FM_SF, FCONDU, 0),
+/* v9 */ fmovfcc ("fmovdue",    FM_DF, FCONDUE, 0),
+/* v9 */ fmovfcc ("fmovque",    FM_QF, FCONDUE, 0),
+/* v9 */ fmovfcc ("fmovsue",    FM_SF, FCONDUE, 0),
+/* v9 */ fmovfcc ("fmovdug",    FM_DF, FCONDUG, 0),
+/* v9 */ fmovfcc ("fmovqug",    FM_QF, FCONDUG, 0),
+/* v9 */ fmovfcc ("fmovsug",    FM_SF, FCONDUG, 0),
+/* v9 */ fmovfcc ("fmovduge",   FM_DF, FCONDUGE, 0),
+/* v9 */ fmovfcc ("fmovquge",   FM_QF, FCONDUGE, 0),
+/* v9 */ fmovfcc ("fmovsuge",   FM_SF, FCONDUGE, 0),
+/* v9 */ fmovfcc ("fmovdul",    FM_DF, FCONDUL, 0),
+/* v9 */ fmovfcc ("fmovqul",    FM_QF, FCONDUL, 0),
+/* v9 */ fmovfcc ("fmovsul",    FM_SF, FCONDUL, 0),
+/* v9 */ fmovfcc ("fmovdule",   FM_DF, FCONDULE, 0),
+/* v9 */ fmovfcc ("fmovqule",   FM_QF, FCONDULE, 0),
+/* v9 */ fmovfcc ("fmovsule",   FM_SF, FCONDULE, 0),
+/* v9 */ fmovicc ("fmovdvc",    FM_DF, CONDVC, 0),
+/* v9 */ fmovicc ("fmovqvc",    FM_QF, CONDVC, 0),
+/* v9 */ fmovicc ("fmovsvc",    FM_SF, CONDVC, 0),
+/* v9 */ fmovicc ("fmovdvs",    FM_DF, CONDVS, 0),
+/* v9 */ fmovicc ("fmovqvs",    FM_QF, CONDVS, 0),
+/* v9 */ fmovicc ("fmovsvs",    FM_SF, CONDVS, 0),
+/* v9 */ fmovcc  ("fmovdz",     FM_DF, CONDZ, FCONDZ, F_ALIAS),
+/* v9 */ fmovcc  ("fmovqz",     FM_QF, CONDZ, FCONDZ, F_ALIAS),
+/* v9 */ fmovcc  ("fmovsz",     FM_SF, CONDZ, FCONDZ, F_ALIAS),
 
 #undef fmovicc /* v9 */
 #undef fmovfcc /* v9 */
@@ -1641,19 +1641,19 @@
   FBR(fop, F2(0, 6)|COND(mask), F2(~0, ~6)|COND(~(mask)), flags)
 
 CONDFC  ("fb",    "cb",    0x8, F_UNBR),
-CONDFCL ("fba",	  "cba",   0x8, F_UNBR|F_ALIAS),
-CONDFC  ("fbe",	  "cb0",   0x9, F_CONDBR),
+CONDFCL ("fba",   "cba",   0x8, F_UNBR|F_ALIAS),
+CONDFC  ("fbe",   "cb0",   0x9, F_CONDBR),
 CONDF   ("fbz",            0x9, F_CONDBR|F_ALIAS),
-CONDFC  ("fbg",	  "cb2",   0x6, F_CONDBR),
+CONDFC  ("fbg",   "cb2",   0x6, F_CONDBR),
 CONDFC  ("fbge",  "cb02",  0xb, F_CONDBR),
-CONDFC  ("fbl",	  "cb1",   0x4, F_CONDBR),
+CONDFC  ("fbl",   "cb1",   0x4, F_CONDBR),
 CONDFC  ("fble",  "cb01",  0xd, F_CONDBR),
 CONDFC  ("fblg",  "cb12",  0x2, F_CONDBR),
-CONDFCL ("fbn",	  "cbn",   0x0, F_UNBR),
+CONDFCL ("fbn",   "cbn",   0x0, F_UNBR),
 CONDFC  ("fbne",  "cb123", 0x1, F_CONDBR),
 CONDF   ("fbnz",           0x1, F_CONDBR|F_ALIAS),
-CONDFC  ("fbo",	  "cb012", 0xf, F_CONDBR),
-CONDFC  ("fbu",	  "cb3",   0x7, F_CONDBR),
+CONDFC  ("fbo",   "cb012", 0xf, F_CONDBR),
+CONDFC  ("fbu",   "cb3",   0x7, F_CONDBR),
 CONDFC  ("fbue",  "cb03",  0xa, F_CONDBR),
 CONDFC  ("fbug",  "cb23",  0x5, F_CONDBR),
 CONDFC  ("fbuge", "cb023", 0xc, F_CONDBR),
@@ -1665,167 +1665,167 @@
 #undef CONDF
 #undef CBR
 #undef FBR
-#undef FBRX	/* v9 */
+#undef FBRX     /* v9 */
 
-{ "jmp",	F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|RD_G0|ASI(~0),	"1+2", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+rs2,%g0 */
-{ "jmp",	F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|RD_G0|ASI_RS2(~0),	"1", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+%g0,%g0 */
-{ "jmp",	F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0,		"1+i", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+i,%g0 */
-{ "jmp",	F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0,		"i+1", F_UNBR|F_DELAYED, v6 }, /* jmpl i+rs1,%g0 */
-{ "jmp",	F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0|RS1_G0,		"i", F_UNBR|F_DELAYED, v6 }, /* jmpl %g0+i,%g0 */
-{ "jmp",	F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0|SIMM13(~0),	"1", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+0,%g0 */
+{ "jmp",        F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|RD_G0|ASI(~0),        "1+2", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+rs2,%g0 */
+{ "jmp",        F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|RD_G0|ASI_RS2(~0),    "1", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+%g0,%g0 */
+{ "jmp",        F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0,                "1+i", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+i,%g0 */
+{ "jmp",        F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0,                "i+1", F_UNBR|F_DELAYED, v6 }, /* jmpl i+rs1,%g0 */
+{ "jmp",        F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0|RS1_G0,         "i", F_UNBR|F_DELAYED, v6 }, /* jmpl %g0+i,%g0 */
+{ "jmp",        F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0|SIMM13(~0),     "1", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+0,%g0 */
 
-{ "nop",	F2(0, 4), 0xfeffffff, "", 0, v6 }, /* sethi 0, %g0 */
+{ "nop",        F2(0, 4), 0xfeffffff, "", 0, v6 }, /* sethi 0, %g0 */
 
-{ "set",	F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,d", F_ALIAS, v6 },
-{ "setuw",	F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,d", F_ALIAS, v9 },
-{ "setsw",	F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,d", F_ALIAS, v9 },
-{ "setx",	F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,1,d", F_ALIAS, v9 },
+{ "set",        F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,d", F_ALIAS, v6 },
+{ "setuw",      F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,d", F_ALIAS, v9 },
+{ "setsw",      F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,d", F_ALIAS, v9 },
+{ "setx",       F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,1,d", F_ALIAS, v9 },
 
-{ "sethi",	F2(0x0, 0x4), F2(~0x0, ~0x4), "h,d", 0, v6 },
+{ "sethi",      F2(0x0, 0x4), F2(~0x0, ~0x4), "h,d", 0, v6 },
 
-{ "taddcc",	F3(2, 0x20, 0), F3(~2, ~0x20, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "taddcc",	F3(2, 0x20, 1), F3(~2, ~0x20, ~1),		"1,i,d", 0, v6 },
-{ "taddcc",	F3(2, 0x20, 1), F3(~2, ~0x20, ~1),		"i,1,d", 0, v6 },
-{ "taddcctv",	F3(2, 0x22, 0), F3(~2, ~0x22, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "taddcctv",	F3(2, 0x22, 1), F3(~2, ~0x22, ~1),		"1,i,d", 0, v6 },
-{ "taddcctv",	F3(2, 0x22, 1), F3(~2, ~0x22, ~1),		"i,1,d", 0, v6 },
+{ "taddcc",     F3(2, 0x20, 0), F3(~2, ~0x20, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "taddcc",     F3(2, 0x20, 1), F3(~2, ~0x20, ~1),              "1,i,d", 0, v6 },
+{ "taddcc",     F3(2, 0x20, 1), F3(~2, ~0x20, ~1),              "i,1,d", 0, v6 },
+{ "taddcctv",   F3(2, 0x22, 0), F3(~2, ~0x22, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "taddcctv",   F3(2, 0x22, 1), F3(~2, ~0x22, ~1),              "1,i,d", 0, v6 },
+{ "taddcctv",   F3(2, 0x22, 1), F3(~2, ~0x22, ~1),              "i,1,d", 0, v6 },
 
-{ "tsubcc",	F3(2, 0x21, 0), F3(~2, ~0x21, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "tsubcc",	F3(2, 0x21, 1), F3(~2, ~0x21, ~1),		"1,i,d", 0, v6 },
-{ "tsubcctv",	F3(2, 0x23, 0), F3(~2, ~0x23, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "tsubcctv",	F3(2, 0x23, 1), F3(~2, ~0x23, ~1),		"1,i,d", 0, v6 },
+{ "tsubcc",     F3(2, 0x21, 0), F3(~2, ~0x21, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "tsubcc",     F3(2, 0x21, 1), F3(~2, ~0x21, ~1),              "1,i,d", 0, v6 },
+{ "tsubcctv",   F3(2, 0x23, 0), F3(~2, ~0x23, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "tsubcctv",   F3(2, 0x23, 1), F3(~2, ~0x23, ~1),              "1,i,d", 0, v6 },
 
-{ "unimp",	F2(0x0, 0x0), 0xffc00000, "n", 0, v6notv9 },
-{ "illtrap",	F2(0, 0), F2(~0, ~0)|RD_G0, "n", 0, v9 },
+{ "unimp",      F2(0x0, 0x0), 0xffc00000, "n", 0, v6notv9 },
+{ "illtrap",    F2(0, 0), F2(~0, ~0)|RD_G0, "n", 0, v9 },
 
 /* This *is* a commutative instruction.  */
-{ "xnor",	F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "xnor",	F3(2, 0x07, 1), F3(~2, ~0x07, ~1),		"1,i,d", 0, v6 },
-{ "xnor",	F3(2, 0x07, 1), F3(~2, ~0x07, ~1),		"i,1,d", 0, v6 },
+{ "xnor",       F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "xnor",       F3(2, 0x07, 1), F3(~2, ~0x07, ~1),              "1,i,d", 0, v6 },
+{ "xnor",       F3(2, 0x07, 1), F3(~2, ~0x07, ~1),              "i,1,d", 0, v6 },
 /* This *is* a commutative instruction.  */
-{ "xnorcc",	F3(2, 0x17, 0), F3(~2, ~0x17, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "xnorcc",	F3(2, 0x17, 1), F3(~2, ~0x17, ~1),		"1,i,d", 0, v6 },
-{ "xnorcc",	F3(2, 0x17, 1), F3(~2, ~0x17, ~1),		"i,1,d", 0, v6 },
-{ "xor",	F3(2, 0x03, 0), F3(~2, ~0x03, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "xor",	F3(2, 0x03, 1), F3(~2, ~0x03, ~1),		"1,i,d", 0, v6 },
-{ "xor",	F3(2, 0x03, 1), F3(~2, ~0x03, ~1),		"i,1,d", 0, v6 },
-{ "xorcc",	F3(2, 0x13, 0), F3(~2, ~0x13, ~0)|ASI(~0),	"1,2,d", 0, v6 },
-{ "xorcc",	F3(2, 0x13, 1), F3(~2, ~0x13, ~1),		"1,i,d", 0, v6 },
-{ "xorcc",	F3(2, 0x13, 1), F3(~2, ~0x13, ~1),		"i,1,d", 0, v6 },
+{ "xnorcc",     F3(2, 0x17, 0), F3(~2, ~0x17, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "xnorcc",     F3(2, 0x17, 1), F3(~2, ~0x17, ~1),              "1,i,d", 0, v6 },
+{ "xnorcc",     F3(2, 0x17, 1), F3(~2, ~0x17, ~1),              "i,1,d", 0, v6 },
+{ "xor",        F3(2, 0x03, 0), F3(~2, ~0x03, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "xor",        F3(2, 0x03, 1), F3(~2, ~0x03, ~1),              "1,i,d", 0, v6 },
+{ "xor",        F3(2, 0x03, 1), F3(~2, ~0x03, ~1),              "i,1,d", 0, v6 },
+{ "xorcc",      F3(2, 0x13, 0), F3(~2, ~0x13, ~0)|ASI(~0),      "1,2,d", 0, v6 },
+{ "xorcc",      F3(2, 0x13, 1), F3(~2, ~0x13, ~1),              "1,i,d", 0, v6 },
+{ "xorcc",      F3(2, 0x13, 1), F3(~2, ~0x13, ~1),              "i,1,d", 0, v6 },
 
-{ "not",	F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0), "1,d", F_ALIAS, v6 }, /* xnor rs1,%0,rd */
-{ "not",	F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0), "r", F_ALIAS, v6 }, /* xnor rd,%0,rd */
+{ "not",        F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0), "1,d", F_ALIAS, v6 }, /* xnor rs1,%0,rd */
+{ "not",        F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0), "r", F_ALIAS, v6 }, /* xnor rd,%0,rd */
 
-{ "btog",	F3(2, 0x03, 0), F3(~2, ~0x03, ~0)|ASI(~0),	"2,r", F_ALIAS, v6 }, /* xor rd,rs2,rd */
-{ "btog",	F3(2, 0x03, 1), F3(~2, ~0x03, ~1),		"i,r", F_ALIAS, v6 }, /* xor rd,i,rd */
+{ "btog",       F3(2, 0x03, 0), F3(~2, ~0x03, ~0)|ASI(~0),      "2,r", F_ALIAS, v6 }, /* xor rd,rs2,rd */
+{ "btog",       F3(2, 0x03, 1), F3(~2, ~0x03, ~1),              "i,r", F_ALIAS, v6 }, /* xor rd,i,rd */
 
 /* FPop1 and FPop2 are not instructions.  Don't accept them.  */
 
-{ "fdtoi",	F3F(2, 0x34, 0x0d2), F3F(~2, ~0x34, ~0x0d2)|RS1_G0, "B,g", F_FLOAT, v6 },
-{ "fstoi",	F3F(2, 0x34, 0x0d1), F3F(~2, ~0x34, ~0x0d1)|RS1_G0, "f,g", F_FLOAT, v6 },
-{ "fqtoi",	F3F(2, 0x34, 0x0d3), F3F(~2, ~0x34, ~0x0d3)|RS1_G0, "R,g", F_FLOAT, v8 },
+{ "fdtoi",      F3F(2, 0x34, 0x0d2), F3F(~2, ~0x34, ~0x0d2)|RS1_G0, "B,g", F_FLOAT, v6 },
+{ "fstoi",      F3F(2, 0x34, 0x0d1), F3F(~2, ~0x34, ~0x0d1)|RS1_G0, "f,g", F_FLOAT, v6 },
+{ "fqtoi",      F3F(2, 0x34, 0x0d3), F3F(~2, ~0x34, ~0x0d3)|RS1_G0, "R,g", F_FLOAT, v8 },
 
-{ "fdtox",	F3F(2, 0x34, 0x082), F3F(~2, ~0x34, ~0x082)|RS1_G0, "B,g", F_FLOAT, v9 },
-{ "fstox",	F3F(2, 0x34, 0x081), F3F(~2, ~0x34, ~0x081)|RS1_G0, "f,g", F_FLOAT, v9 },
-{ "fqtox",	F3F(2, 0x34, 0x083), F3F(~2, ~0x34, ~0x083)|RS1_G0, "R,g", F_FLOAT, v9 },
+{ "fdtox",      F3F(2, 0x34, 0x082), F3F(~2, ~0x34, ~0x082)|RS1_G0, "B,g", F_FLOAT, v9 },
+{ "fstox",      F3F(2, 0x34, 0x081), F3F(~2, ~0x34, ~0x081)|RS1_G0, "f,g", F_FLOAT, v9 },
+{ "fqtox",      F3F(2, 0x34, 0x083), F3F(~2, ~0x34, ~0x083)|RS1_G0, "R,g", F_FLOAT, v9 },
 
-{ "fitod",	F3F(2, 0x34, 0x0c8), F3F(~2, ~0x34, ~0x0c8)|RS1_G0, "f,H", F_FLOAT, v6 },
-{ "fitos",	F3F(2, 0x34, 0x0c4), F3F(~2, ~0x34, ~0x0c4)|RS1_G0, "f,g", F_FLOAT, v6 },
-{ "fitoq",	F3F(2, 0x34, 0x0cc), F3F(~2, ~0x34, ~0x0cc)|RS1_G0, "f,J", F_FLOAT, v8 },
+{ "fitod",      F3F(2, 0x34, 0x0c8), F3F(~2, ~0x34, ~0x0c8)|RS1_G0, "f,H", F_FLOAT, v6 },
+{ "fitos",      F3F(2, 0x34, 0x0c4), F3F(~2, ~0x34, ~0x0c4)|RS1_G0, "f,g", F_FLOAT, v6 },
+{ "fitoq",      F3F(2, 0x34, 0x0cc), F3F(~2, ~0x34, ~0x0cc)|RS1_G0, "f,J", F_FLOAT, v8 },
 
-{ "fxtod",	F3F(2, 0x34, 0x088), F3F(~2, ~0x34, ~0x088)|RS1_G0, "f,H", F_FLOAT, v9 },
-{ "fxtos",	F3F(2, 0x34, 0x084), F3F(~2, ~0x34, ~0x084)|RS1_G0, "f,g", F_FLOAT, v9 },
-{ "fxtoq",	F3F(2, 0x34, 0x08c), F3F(~2, ~0x34, ~0x08c)|RS1_G0, "f,J", F_FLOAT, v9 },
+{ "fxtod",      F3F(2, 0x34, 0x088), F3F(~2, ~0x34, ~0x088)|RS1_G0, "f,H", F_FLOAT, v9 },
+{ "fxtos",      F3F(2, 0x34, 0x084), F3F(~2, ~0x34, ~0x084)|RS1_G0, "f,g", F_FLOAT, v9 },
+{ "fxtoq",      F3F(2, 0x34, 0x08c), F3F(~2, ~0x34, ~0x08c)|RS1_G0, "f,J", F_FLOAT, v9 },
 
-{ "fdtoq",	F3F(2, 0x34, 0x0ce), F3F(~2, ~0x34, ~0x0ce)|RS1_G0, "B,J", F_FLOAT, v8 },
-{ "fdtos",	F3F(2, 0x34, 0x0c6), F3F(~2, ~0x34, ~0x0c6)|RS1_G0, "B,g", F_FLOAT, v6 },
-{ "fqtod",	F3F(2, 0x34, 0x0cb), F3F(~2, ~0x34, ~0x0cb)|RS1_G0, "R,H", F_FLOAT, v8 },
-{ "fqtos",	F3F(2, 0x34, 0x0c7), F3F(~2, ~0x34, ~0x0c7)|RS1_G0, "R,g", F_FLOAT, v8 },
-{ "fstod",	F3F(2, 0x34, 0x0c9), F3F(~2, ~0x34, ~0x0c9)|RS1_G0, "f,H", F_FLOAT, v6 },
-{ "fstoq",	F3F(2, 0x34, 0x0cd), F3F(~2, ~0x34, ~0x0cd)|RS1_G0, "f,J", F_FLOAT, v8 },
+{ "fdtoq",      F3F(2, 0x34, 0x0ce), F3F(~2, ~0x34, ~0x0ce)|RS1_G0, "B,J", F_FLOAT, v8 },
+{ "fdtos",      F3F(2, 0x34, 0x0c6), F3F(~2, ~0x34, ~0x0c6)|RS1_G0, "B,g", F_FLOAT, v6 },
+{ "fqtod",      F3F(2, 0x34, 0x0cb), F3F(~2, ~0x34, ~0x0cb)|RS1_G0, "R,H", F_FLOAT, v8 },
+{ "fqtos",      F3F(2, 0x34, 0x0c7), F3F(~2, ~0x34, ~0x0c7)|RS1_G0, "R,g", F_FLOAT, v8 },
+{ "fstod",      F3F(2, 0x34, 0x0c9), F3F(~2, ~0x34, ~0x0c9)|RS1_G0, "f,H", F_FLOAT, v6 },
+{ "fstoq",      F3F(2, 0x34, 0x0cd), F3F(~2, ~0x34, ~0x0cd)|RS1_G0, "f,J", F_FLOAT, v8 },
 
-{ "fdivd",	F3F(2, 0x34, 0x04e), F3F(~2, ~0x34, ~0x04e), "v,B,H", F_FLOAT, v6 },
-{ "fdivq",	F3F(2, 0x34, 0x04f), F3F(~2, ~0x34, ~0x04f), "V,R,J", F_FLOAT, v8 },
-{ "fdivx",	F3F(2, 0x34, 0x04f), F3F(~2, ~0x34, ~0x04f), "V,R,J", F_FLOAT|F_ALIAS, v8 },
-{ "fdivs",	F3F(2, 0x34, 0x04d), F3F(~2, ~0x34, ~0x04d), "e,f,g", F_FLOAT, v6 },
-{ "fmuld",	F3F(2, 0x34, 0x04a), F3F(~2, ~0x34, ~0x04a), "v,B,H", F_FLOAT, v6 },
-{ "fmulq",	F3F(2, 0x34, 0x04b), F3F(~2, ~0x34, ~0x04b), "V,R,J", F_FLOAT, v8 },
-{ "fmulx",	F3F(2, 0x34, 0x04b), F3F(~2, ~0x34, ~0x04b), "V,R,J", F_FLOAT|F_ALIAS, v8 },
-{ "fmuls",	F3F(2, 0x34, 0x049), F3F(~2, ~0x34, ~0x049), "e,f,g", F_FLOAT, v6 },
+{ "fdivd",      F3F(2, 0x34, 0x04e), F3F(~2, ~0x34, ~0x04e), "v,B,H", F_FLOAT, v6 },
+{ "fdivq",      F3F(2, 0x34, 0x04f), F3F(~2, ~0x34, ~0x04f), "V,R,J", F_FLOAT, v8 },
+{ "fdivx",      F3F(2, 0x34, 0x04f), F3F(~2, ~0x34, ~0x04f), "V,R,J", F_FLOAT|F_ALIAS, v8 },
+{ "fdivs",      F3F(2, 0x34, 0x04d), F3F(~2, ~0x34, ~0x04d), "e,f,g", F_FLOAT, v6 },
+{ "fmuld",      F3F(2, 0x34, 0x04a), F3F(~2, ~0x34, ~0x04a), "v,B,H", F_FLOAT, v6 },
+{ "fmulq",      F3F(2, 0x34, 0x04b), F3F(~2, ~0x34, ~0x04b), "V,R,J", F_FLOAT, v8 },
+{ "fmulx",      F3F(2, 0x34, 0x04b), F3F(~2, ~0x34, ~0x04b), "V,R,J", F_FLOAT|F_ALIAS, v8 },
+{ "fmuls",      F3F(2, 0x34, 0x049), F3F(~2, ~0x34, ~0x049), "e,f,g", F_FLOAT, v6 },
 
-{ "fdmulq",	F3F(2, 0x34, 0x06e), F3F(~2, ~0x34, ~0x06e), "v,B,J", F_FLOAT, v8 },
-{ "fdmulx",	F3F(2, 0x34, 0x06e), F3F(~2, ~0x34, ~0x06e), "v,B,J", F_FLOAT|F_ALIAS, v8 },
-{ "fsmuld",	F3F(2, 0x34, 0x069), F3F(~2, ~0x34, ~0x069), "e,f,H", F_FLOAT, v8 },
+{ "fdmulq",     F3F(2, 0x34, 0x06e), F3F(~2, ~0x34, ~0x06e), "v,B,J", F_FLOAT, v8 },
+{ "fdmulx",     F3F(2, 0x34, 0x06e), F3F(~2, ~0x34, ~0x06e), "v,B,J", F_FLOAT|F_ALIAS, v8 },
+{ "fsmuld",     F3F(2, 0x34, 0x069), F3F(~2, ~0x34, ~0x069), "e,f,H", F_FLOAT, v8 },
 
-{ "fsqrtd",	F3F(2, 0x34, 0x02a), F3F(~2, ~0x34, ~0x02a)|RS1_G0, "B,H", F_FLOAT, v7 },
-{ "fsqrtq",	F3F(2, 0x34, 0x02b), F3F(~2, ~0x34, ~0x02b)|RS1_G0, "R,J", F_FLOAT, v8 },
-{ "fsqrtx",	F3F(2, 0x34, 0x02b), F3F(~2, ~0x34, ~0x02b)|RS1_G0, "R,J", F_FLOAT|F_ALIAS, v8 },
-{ "fsqrts",	F3F(2, 0x34, 0x029), F3F(~2, ~0x34, ~0x029)|RS1_G0, "f,g", F_FLOAT, v7 },
+{ "fsqrtd",     F3F(2, 0x34, 0x02a), F3F(~2, ~0x34, ~0x02a)|RS1_G0, "B,H", F_FLOAT, v7 },
+{ "fsqrtq",     F3F(2, 0x34, 0x02b), F3F(~2, ~0x34, ~0x02b)|RS1_G0, "R,J", F_FLOAT, v8 },
+{ "fsqrtx",     F3F(2, 0x34, 0x02b), F3F(~2, ~0x34, ~0x02b)|RS1_G0, "R,J", F_FLOAT|F_ALIAS, v8 },
+{ "fsqrts",     F3F(2, 0x34, 0x029), F3F(~2, ~0x34, ~0x029)|RS1_G0, "f,g", F_FLOAT, v7 },
 
-{ "fabsd",	F3F(2, 0x34, 0x00a), F3F(~2, ~0x34, ~0x00a)|RS1_G0, "B,H", F_FLOAT, v9 },
-{ "fabsq",	F3F(2, 0x34, 0x00b), F3F(~2, ~0x34, ~0x00b)|RS1_G0, "R,J", F_FLOAT, v9 },
-{ "fabsx",	F3F(2, 0x34, 0x00b), F3F(~2, ~0x34, ~0x00b)|RS1_G0, "R,J", F_FLOAT|F_ALIAS, v9 },
-{ "fabss",	F3F(2, 0x34, 0x009), F3F(~2, ~0x34, ~0x009)|RS1_G0, "f,g", F_FLOAT, v6 },
-{ "fmovd",	F3F(2, 0x34, 0x002), F3F(~2, ~0x34, ~0x002)|RS1_G0, "B,H", F_FLOAT, v9 },
-{ "fmovq",	F3F(2, 0x34, 0x003), F3F(~2, ~0x34, ~0x003)|RS1_G0, "R,J", F_FLOAT, v9 },
-{ "fmovx",	F3F(2, 0x34, 0x003), F3F(~2, ~0x34, ~0x003)|RS1_G0, "R,J", F_FLOAT|F_ALIAS, v9 },
-{ "fmovs",	F3F(2, 0x34, 0x001), F3F(~2, ~0x34, ~0x001)|RS1_G0, "f,g", F_FLOAT, v6 },
-{ "fnegd",	F3F(2, 0x34, 0x006), F3F(~2, ~0x34, ~0x006)|RS1_G0, "B,H", F_FLOAT, v9 },
-{ "fnegq",	F3F(2, 0x34, 0x007), F3F(~2, ~0x34, ~0x007)|RS1_G0, "R,J", F_FLOAT, v9 },
-{ "fnegx",	F3F(2, 0x34, 0x007), F3F(~2, ~0x34, ~0x007)|RS1_G0, "R,J", F_FLOAT|F_ALIAS, v9 },
-{ "fnegs",	F3F(2, 0x34, 0x005), F3F(~2, ~0x34, ~0x005)|RS1_G0, "f,g", F_FLOAT, v6 },
+{ "fabsd",      F3F(2, 0x34, 0x00a), F3F(~2, ~0x34, ~0x00a)|RS1_G0, "B,H", F_FLOAT, v9 },
+{ "fabsq",      F3F(2, 0x34, 0x00b), F3F(~2, ~0x34, ~0x00b)|RS1_G0, "R,J", F_FLOAT, v9 },
+{ "fabsx",      F3F(2, 0x34, 0x00b), F3F(~2, ~0x34, ~0x00b)|RS1_G0, "R,J", F_FLOAT|F_ALIAS, v9 },
+{ "fabss",      F3F(2, 0x34, 0x009), F3F(~2, ~0x34, ~0x009)|RS1_G0, "f,g", F_FLOAT, v6 },
+{ "fmovd",      F3F(2, 0x34, 0x002), F3F(~2, ~0x34, ~0x002)|RS1_G0, "B,H", F_FLOAT, v9 },
+{ "fmovq",      F3F(2, 0x34, 0x003), F3F(~2, ~0x34, ~0x003)|RS1_G0, "R,J", F_FLOAT, v9 },
+{ "fmovx",      F3F(2, 0x34, 0x003), F3F(~2, ~0x34, ~0x003)|RS1_G0, "R,J", F_FLOAT|F_ALIAS, v9 },
+{ "fmovs",      F3F(2, 0x34, 0x001), F3F(~2, ~0x34, ~0x001)|RS1_G0, "f,g", F_FLOAT, v6 },
+{ "fnegd",      F3F(2, 0x34, 0x006), F3F(~2, ~0x34, ~0x006)|RS1_G0, "B,H", F_FLOAT, v9 },
+{ "fnegq",      F3F(2, 0x34, 0x007), F3F(~2, ~0x34, ~0x007)|RS1_G0, "R,J", F_FLOAT, v9 },
+{ "fnegx",      F3F(2, 0x34, 0x007), F3F(~2, ~0x34, ~0x007)|RS1_G0, "R,J", F_FLOAT|F_ALIAS, v9 },
+{ "fnegs",      F3F(2, 0x34, 0x005), F3F(~2, ~0x34, ~0x005)|RS1_G0, "f,g", F_FLOAT, v6 },
 
-{ "faddd",	F3F(2, 0x34, 0x042), F3F(~2, ~0x34, ~0x042), "v,B,H", F_FLOAT, v6 },
-{ "faddq",	F3F(2, 0x34, 0x043), F3F(~2, ~0x34, ~0x043), "V,R,J", F_FLOAT, v8 },
-{ "faddx",	F3F(2, 0x34, 0x043), F3F(~2, ~0x34, ~0x043), "V,R,J", F_FLOAT|F_ALIAS, v8 },
-{ "fadds",	F3F(2, 0x34, 0x041), F3F(~2, ~0x34, ~0x041), "e,f,g", F_FLOAT, v6 },
-{ "fsubd",	F3F(2, 0x34, 0x046), F3F(~2, ~0x34, ~0x046), "v,B,H", F_FLOAT, v6 },
-{ "fsubq",	F3F(2, 0x34, 0x047), F3F(~2, ~0x34, ~0x047), "V,R,J", F_FLOAT, v8 },
-{ "fsubx",	F3F(2, 0x34, 0x047), F3F(~2, ~0x34, ~0x047), "V,R,J", F_FLOAT|F_ALIAS, v8 },
-{ "fsubs",	F3F(2, 0x34, 0x045), F3F(~2, ~0x34, ~0x045), "e,f,g", F_FLOAT, v6 },
+{ "faddd",      F3F(2, 0x34, 0x042), F3F(~2, ~0x34, ~0x042), "v,B,H", F_FLOAT, v6 },
+{ "faddq",      F3F(2, 0x34, 0x043), F3F(~2, ~0x34, ~0x043), "V,R,J", F_FLOAT, v8 },
+{ "faddx",      F3F(2, 0x34, 0x043), F3F(~2, ~0x34, ~0x043), "V,R,J", F_FLOAT|F_ALIAS, v8 },
+{ "fadds",      F3F(2, 0x34, 0x041), F3F(~2, ~0x34, ~0x041), "e,f,g", F_FLOAT, v6 },
+{ "fsubd",      F3F(2, 0x34, 0x046), F3F(~2, ~0x34, ~0x046), "v,B,H", F_FLOAT, v6 },
+{ "fsubq",      F3F(2, 0x34, 0x047), F3F(~2, ~0x34, ~0x047), "V,R,J", F_FLOAT, v8 },
+{ "fsubx",      F3F(2, 0x34, 0x047), F3F(~2, ~0x34, ~0x047), "V,R,J", F_FLOAT|F_ALIAS, v8 },
+{ "fsubs",      F3F(2, 0x34, 0x045), F3F(~2, ~0x34, ~0x045), "e,f,g", F_FLOAT, v6 },
 
-#define CMPFCC(x)	(((x)&0x3)<<25)
+#define CMPFCC(x)       (((x)&0x3)<<25)
 
-{ "fcmpd",	          F3F(2, 0x35, 0x052),            F3F(~2, ~0x35, ~0x052)|RD_G0,  "v,B",   F_FLOAT, v6 },
-{ "fcmpd",	CMPFCC(0)|F3F(2, 0x35, 0x052), CMPFCC(~0)|F3F(~2, ~0x35, ~0x052),	 "6,v,B", F_FLOAT, v9 },
-{ "fcmpd",	CMPFCC(1)|F3F(2, 0x35, 0x052), CMPFCC(~1)|F3F(~2, ~0x35, ~0x052),	 "7,v,B", F_FLOAT, v9 },
-{ "fcmpd",	CMPFCC(2)|F3F(2, 0x35, 0x052), CMPFCC(~2)|F3F(~2, ~0x35, ~0x052),	 "8,v,B", F_FLOAT, v9 },
-{ "fcmpd",	CMPFCC(3)|F3F(2, 0x35, 0x052), CMPFCC(~3)|F3F(~2, ~0x35, ~0x052),	 "9,v,B", F_FLOAT, v9 },
-{ "fcmped",	          F3F(2, 0x35, 0x056),            F3F(~2, ~0x35, ~0x056)|RD_G0,  "v,B",   F_FLOAT, v6 },
-{ "fcmped",	CMPFCC(0)|F3F(2, 0x35, 0x056), CMPFCC(~0)|F3F(~2, ~0x35, ~0x056),	 "6,v,B", F_FLOAT, v9 },
-{ "fcmped",	CMPFCC(1)|F3F(2, 0x35, 0x056), CMPFCC(~1)|F3F(~2, ~0x35, ~0x056),	 "7,v,B", F_FLOAT, v9 },
-{ "fcmped",	CMPFCC(2)|F3F(2, 0x35, 0x056), CMPFCC(~2)|F3F(~2, ~0x35, ~0x056),	 "8,v,B", F_FLOAT, v9 },
-{ "fcmped",	CMPFCC(3)|F3F(2, 0x35, 0x056), CMPFCC(~3)|F3F(~2, ~0x35, ~0x056),	 "9,v,B", F_FLOAT, v9 },
-{ "fcmpq",	          F3F(2, 0x35, 0x053),            F3F(~2, ~0x35, ~0x053)|RD_G0,	 "V,R", F_FLOAT, v8 },
-{ "fcmpq",	CMPFCC(0)|F3F(2, 0x35, 0x053), CMPFCC(~0)|F3F(~2, ~0x35, ~0x053),	 "6,V,R", F_FLOAT, v9 },
-{ "fcmpq",	CMPFCC(1)|F3F(2, 0x35, 0x053), CMPFCC(~1)|F3F(~2, ~0x35, ~0x053),	 "7,V,R", F_FLOAT, v9 },
-{ "fcmpq",	CMPFCC(2)|F3F(2, 0x35, 0x053), CMPFCC(~2)|F3F(~2, ~0x35, ~0x053),	 "8,V,R", F_FLOAT, v9 },
-{ "fcmpq",	CMPFCC(3)|F3F(2, 0x35, 0x053), CMPFCC(~3)|F3F(~2, ~0x35, ~0x053),	 "9,V,R", F_FLOAT, v9 },
-{ "fcmpeq",	          F3F(2, 0x35, 0x057),            F3F(~2, ~0x35, ~0x057)|RD_G0,	 "V,R", F_FLOAT, v8 },
-{ "fcmpeq",	CMPFCC(0)|F3F(2, 0x35, 0x057), CMPFCC(~0)|F3F(~2, ~0x35, ~0x057),	 "6,V,R", F_FLOAT, v9 },
-{ "fcmpeq",	CMPFCC(1)|F3F(2, 0x35, 0x057), CMPFCC(~1)|F3F(~2, ~0x35, ~0x057),	 "7,V,R", F_FLOAT, v9 },
-{ "fcmpeq",	CMPFCC(2)|F3F(2, 0x35, 0x057), CMPFCC(~2)|F3F(~2, ~0x35, ~0x057),	 "8,V,R", F_FLOAT, v9 },
-{ "fcmpeq",	CMPFCC(3)|F3F(2, 0x35, 0x057), CMPFCC(~3)|F3F(~2, ~0x35, ~0x057),	 "9,V,R", F_FLOAT, v9 },
-{ "fcmpx",	          F3F(2, 0x35, 0x053),            F3F(~2, ~0x35, ~0x053)|RD_G0,	 "V,R", F_FLOAT|F_ALIAS, v8 },
-{ "fcmpx",	CMPFCC(0)|F3F(2, 0x35, 0x053), CMPFCC(~0)|F3F(~2, ~0x35, ~0x053),	 "6,V,R", F_FLOAT|F_ALIAS, v9 },
-{ "fcmpx",	CMPFCC(1)|F3F(2, 0x35, 0x053), CMPFCC(~1)|F3F(~2, ~0x35, ~0x053),	 "7,V,R", F_FLOAT|F_ALIAS, v9 },
-{ "fcmpx",	CMPFCC(2)|F3F(2, 0x35, 0x053), CMPFCC(~2)|F3F(~2, ~0x35, ~0x053),	 "8,V,R", F_FLOAT|F_ALIAS, v9 },
-{ "fcmpx",	CMPFCC(3)|F3F(2, 0x35, 0x053), CMPFCC(~3)|F3F(~2, ~0x35, ~0x053),	 "9,V,R", F_FLOAT|F_ALIAS, v9 },
-{ "fcmpex",	          F3F(2, 0x35, 0x057),            F3F(~2, ~0x35, ~0x057)|RD_G0,	 "V,R", F_FLOAT|F_ALIAS, v8 },
-{ "fcmpex",	CMPFCC(0)|F3F(2, 0x35, 0x057), CMPFCC(~0)|F3F(~2, ~0x35, ~0x057),	 "6,V,R", F_FLOAT|F_ALIAS, v9 },
-{ "fcmpex",	CMPFCC(1)|F3F(2, 0x35, 0x057), CMPFCC(~1)|F3F(~2, ~0x35, ~0x057),	 "7,V,R", F_FLOAT|F_ALIAS, v9 },
-{ "fcmpex",	CMPFCC(2)|F3F(2, 0x35, 0x057), CMPFCC(~2)|F3F(~2, ~0x35, ~0x057),	 "8,V,R", F_FLOAT|F_ALIAS, v9 },
-{ "fcmpex",	CMPFCC(3)|F3F(2, 0x35, 0x057), CMPFCC(~3)|F3F(~2, ~0x35, ~0x057),	 "9,V,R", F_FLOAT|F_ALIAS, v9 },
-{ "fcmps",	          F3F(2, 0x35, 0x051),            F3F(~2, ~0x35, ~0x051)|RD_G0, "e,f",   F_FLOAT, v6 },
-{ "fcmps",	CMPFCC(0)|F3F(2, 0x35, 0x051), CMPFCC(~0)|F3F(~2, ~0x35, ~0x051),	 "6,e,f", F_FLOAT, v9 },
-{ "fcmps",	CMPFCC(1)|F3F(2, 0x35, 0x051), CMPFCC(~1)|F3F(~2, ~0x35, ~0x051),	 "7,e,f", F_FLOAT, v9 },
-{ "fcmps",	CMPFCC(2)|F3F(2, 0x35, 0x051), CMPFCC(~2)|F3F(~2, ~0x35, ~0x051),	 "8,e,f", F_FLOAT, v9 },
-{ "fcmps",	CMPFCC(3)|F3F(2, 0x35, 0x051), CMPFCC(~3)|F3F(~2, ~0x35, ~0x051),	 "9,e,f", F_FLOAT, v9 },
-{ "fcmpes",	          F3F(2, 0x35, 0x055),            F3F(~2, ~0x35, ~0x055)|RD_G0, "e,f",   F_FLOAT, v6 },
-{ "fcmpes",	CMPFCC(0)|F3F(2, 0x35, 0x055), CMPFCC(~0)|F3F(~2, ~0x35, ~0x055),	 "6,e,f", F_FLOAT, v9 },
-{ "fcmpes",	CMPFCC(1)|F3F(2, 0x35, 0x055), CMPFCC(~1)|F3F(~2, ~0x35, ~0x055),	 "7,e,f", F_FLOAT, v9 },
-{ "fcmpes",	CMPFCC(2)|F3F(2, 0x35, 0x055), CMPFCC(~2)|F3F(~2, ~0x35, ~0x055),	 "8,e,f", F_FLOAT, v9 },
-{ "fcmpes",	CMPFCC(3)|F3F(2, 0x35, 0x055), CMPFCC(~3)|F3F(~2, ~0x35, ~0x055),	 "9,e,f", F_FLOAT, v9 },
+{ "fcmpd",                F3F(2, 0x35, 0x052),            F3F(~2, ~0x35, ~0x052)|RD_G0,  "v,B",   F_FLOAT, v6 },
+{ "fcmpd",      CMPFCC(0)|F3F(2, 0x35, 0x052), CMPFCC(~0)|F3F(~2, ~0x35, ~0x052),        "6,v,B", F_FLOAT, v9 },
+{ "fcmpd",      CMPFCC(1)|F3F(2, 0x35, 0x052), CMPFCC(~1)|F3F(~2, ~0x35, ~0x052),        "7,v,B", F_FLOAT, v9 },
+{ "fcmpd",      CMPFCC(2)|F3F(2, 0x35, 0x052), CMPFCC(~2)|F3F(~2, ~0x35, ~0x052),        "8,v,B", F_FLOAT, v9 },
+{ "fcmpd",      CMPFCC(3)|F3F(2, 0x35, 0x052), CMPFCC(~3)|F3F(~2, ~0x35, ~0x052),        "9,v,B", F_FLOAT, v9 },
+{ "fcmped",               F3F(2, 0x35, 0x056),            F3F(~2, ~0x35, ~0x056)|RD_G0,  "v,B",   F_FLOAT, v6 },
+{ "fcmped",     CMPFCC(0)|F3F(2, 0x35, 0x056), CMPFCC(~0)|F3F(~2, ~0x35, ~0x056),        "6,v,B", F_FLOAT, v9 },
+{ "fcmped",     CMPFCC(1)|F3F(2, 0x35, 0x056), CMPFCC(~1)|F3F(~2, ~0x35, ~0x056),        "7,v,B", F_FLOAT, v9 },
+{ "fcmped",     CMPFCC(2)|F3F(2, 0x35, 0x056), CMPFCC(~2)|F3F(~2, ~0x35, ~0x056),        "8,v,B", F_FLOAT, v9 },
+{ "fcmped",     CMPFCC(3)|F3F(2, 0x35, 0x056), CMPFCC(~3)|F3F(~2, ~0x35, ~0x056),        "9,v,B", F_FLOAT, v9 },
+{ "fcmpq",                F3F(2, 0x35, 0x053),            F3F(~2, ~0x35, ~0x053)|RD_G0,  "V,R", F_FLOAT, v8 },
+{ "fcmpq",      CMPFCC(0)|F3F(2, 0x35, 0x053), CMPFCC(~0)|F3F(~2, ~0x35, ~0x053),        "6,V,R", F_FLOAT, v9 },
+{ "fcmpq",      CMPFCC(1)|F3F(2, 0x35, 0x053), CMPFCC(~1)|F3F(~2, ~0x35, ~0x053),        "7,V,R", F_FLOAT, v9 },
+{ "fcmpq",      CMPFCC(2)|F3F(2, 0x35, 0x053), CMPFCC(~2)|F3F(~2, ~0x35, ~0x053),        "8,V,R", F_FLOAT, v9 },
+{ "fcmpq",      CMPFCC(3)|F3F(2, 0x35, 0x053), CMPFCC(~3)|F3F(~2, ~0x35, ~0x053),        "9,V,R", F_FLOAT, v9 },
+{ "fcmpeq",               F3F(2, 0x35, 0x057),            F3F(~2, ~0x35, ~0x057)|RD_G0,  "V,R", F_FLOAT, v8 },
+{ "fcmpeq",     CMPFCC(0)|F3F(2, 0x35, 0x057), CMPFCC(~0)|F3F(~2, ~0x35, ~0x057),        "6,V,R", F_FLOAT, v9 },
+{ "fcmpeq",     CMPFCC(1)|F3F(2, 0x35, 0x057), CMPFCC(~1)|F3F(~2, ~0x35, ~0x057),        "7,V,R", F_FLOAT, v9 },
+{ "fcmpeq",     CMPFCC(2)|F3F(2, 0x35, 0x057), CMPFCC(~2)|F3F(~2, ~0x35, ~0x057),        "8,V,R", F_FLOAT, v9 },
+{ "fcmpeq",     CMPFCC(3)|F3F(2, 0x35, 0x057), CMPFCC(~3)|F3F(~2, ~0x35, ~0x057),        "9,V,R", F_FLOAT, v9 },
+{ "fcmpx",                F3F(2, 0x35, 0x053),            F3F(~2, ~0x35, ~0x053)|RD_G0,  "V,R", F_FLOAT|F_ALIAS, v8 },
+{ "fcmpx",      CMPFCC(0)|F3F(2, 0x35, 0x053), CMPFCC(~0)|F3F(~2, ~0x35, ~0x053),        "6,V,R", F_FLOAT|F_ALIAS, v9 },
+{ "fcmpx",      CMPFCC(1)|F3F(2, 0x35, 0x053), CMPFCC(~1)|F3F(~2, ~0x35, ~0x053),        "7,V,R", F_FLOAT|F_ALIAS, v9 },
+{ "fcmpx",      CMPFCC(2)|F3F(2, 0x35, 0x053), CMPFCC(~2)|F3F(~2, ~0x35, ~0x053),        "8,V,R", F_FLOAT|F_ALIAS, v9 },
+{ "fcmpx",      CMPFCC(3)|F3F(2, 0x35, 0x053), CMPFCC(~3)|F3F(~2, ~0x35, ~0x053),        "9,V,R", F_FLOAT|F_ALIAS, v9 },
+{ "fcmpex",               F3F(2, 0x35, 0x057),            F3F(~2, ~0x35, ~0x057)|RD_G0,  "V,R", F_FLOAT|F_ALIAS, v8 },
+{ "fcmpex",     CMPFCC(0)|F3F(2, 0x35, 0x057), CMPFCC(~0)|F3F(~2, ~0x35, ~0x057),        "6,V,R", F_FLOAT|F_ALIAS, v9 },
+{ "fcmpex",     CMPFCC(1)|F3F(2, 0x35, 0x057), CMPFCC(~1)|F3F(~2, ~0x35, ~0x057),        "7,V,R", F_FLOAT|F_ALIAS, v9 },
+{ "fcmpex",     CMPFCC(2)|F3F(2, 0x35, 0x057), CMPFCC(~2)|F3F(~2, ~0x35, ~0x057),        "8,V,R", F_FLOAT|F_ALIAS, v9 },
+{ "fcmpex",     CMPFCC(3)|F3F(2, 0x35, 0x057), CMPFCC(~3)|F3F(~2, ~0x35, ~0x057),        "9,V,R", F_FLOAT|F_ALIAS, v9 },
+{ "fcmps",                F3F(2, 0x35, 0x051),            F3F(~2, ~0x35, ~0x051)|RD_G0, "e,f",   F_FLOAT, v6 },
+{ "fcmps",      CMPFCC(0)|F3F(2, 0x35, 0x051), CMPFCC(~0)|F3F(~2, ~0x35, ~0x051),        "6,e,f", F_FLOAT, v9 },
+{ "fcmps",      CMPFCC(1)|F3F(2, 0x35, 0x051), CMPFCC(~1)|F3F(~2, ~0x35, ~0x051),        "7,e,f", F_FLOAT, v9 },
+{ "fcmps",      CMPFCC(2)|F3F(2, 0x35, 0x051), CMPFCC(~2)|F3F(~2, ~0x35, ~0x051),        "8,e,f", F_FLOAT, v9 },
+{ "fcmps",      CMPFCC(3)|F3F(2, 0x35, 0x051), CMPFCC(~3)|F3F(~2, ~0x35, ~0x051),        "9,e,f", F_FLOAT, v9 },
+{ "fcmpes",               F3F(2, 0x35, 0x055),            F3F(~2, ~0x35, ~0x055)|RD_G0, "e,f",   F_FLOAT, v6 },
+{ "fcmpes",     CMPFCC(0)|F3F(2, 0x35, 0x055), CMPFCC(~0)|F3F(~2, ~0x35, ~0x055),        "6,e,f", F_FLOAT, v9 },
+{ "fcmpes",     CMPFCC(1)|F3F(2, 0x35, 0x055), CMPFCC(~1)|F3F(~2, ~0x35, ~0x055),        "7,e,f", F_FLOAT, v9 },
+{ "fcmpes",     CMPFCC(2)|F3F(2, 0x35, 0x055), CMPFCC(~2)|F3F(~2, ~0x35, ~0x055),        "8,e,f", F_FLOAT, v9 },
+{ "fcmpes",     CMPFCC(3)|F3F(2, 0x35, 0x055), CMPFCC(~3)|F3F(~2, ~0x35, ~0x055),        "9,e,f", F_FLOAT, v9 },
 
 /* These Extended FPop (FIFO) instructions are new in the Fujitsu
    MB86934, replacing the CPop instructions from v6 and later
@@ -1835,30 +1835,30 @@
 #define EFPOP1_3(name, op, args) { name, F3F(2, 0x36, op), F3F(~2, ~0x36, ~op),        args, 0, sparclite }
 #define EFPOP2_2(name, op, args) { name, F3F(2, 0x37, op), F3F(~2, ~0x37, ~op)|RD_G0,  args, 0, sparclite }
 
-EFPOP1_2 ("efitod",	0x0c8, "f,H"),
-EFPOP1_2 ("efitos",	0x0c4, "f,g"),
-EFPOP1_2 ("efdtoi",	0x0d2, "B,g"),
-EFPOP1_2 ("efstoi",	0x0d1, "f,g"),
-EFPOP1_2 ("efstod",	0x0c9, "f,H"),
-EFPOP1_2 ("efdtos",	0x0c6, "B,g"),
-EFPOP1_2 ("efmovs",	0x001, "f,g"),
-EFPOP1_2 ("efnegs",	0x005, "f,g"),
-EFPOP1_2 ("efabss",	0x009, "f,g"),
-EFPOP1_2 ("efsqrtd",	0x02a, "B,H"),
-EFPOP1_2 ("efsqrts",	0x029, "f,g"),
-EFPOP1_3 ("efaddd",	0x042, "v,B,H"),
-EFPOP1_3 ("efadds",	0x041, "e,f,g"),
-EFPOP1_3 ("efsubd",	0x046, "v,B,H"),
-EFPOP1_3 ("efsubs",	0x045, "e,f,g"),
-EFPOP1_3 ("efdivd",	0x04e, "v,B,H"),
-EFPOP1_3 ("efdivs",	0x04d, "e,f,g"),
-EFPOP1_3 ("efmuld",	0x04a, "v,B,H"),
-EFPOP1_3 ("efmuls",	0x049, "e,f,g"),
-EFPOP1_3 ("efsmuld",	0x069, "e,f,H"),
-EFPOP2_2 ("efcmpd",	0x052, "v,B"),
-EFPOP2_2 ("efcmped",	0x056, "v,B"),
-EFPOP2_2 ("efcmps",	0x051, "e,f"),
-EFPOP2_2 ("efcmpes",	0x055, "e,f"),
+EFPOP1_2 ("efitod",     0x0c8, "f,H"),
+EFPOP1_2 ("efitos",     0x0c4, "f,g"),
+EFPOP1_2 ("efdtoi",     0x0d2, "B,g"),
+EFPOP1_2 ("efstoi",     0x0d1, "f,g"),
+EFPOP1_2 ("efstod",     0x0c9, "f,H"),
+EFPOP1_2 ("efdtos",     0x0c6, "B,g"),
+EFPOP1_2 ("efmovs",     0x001, "f,g"),
+EFPOP1_2 ("efnegs",     0x005, "f,g"),
+EFPOP1_2 ("efabss",     0x009, "f,g"),
+EFPOP1_2 ("efsqrtd",    0x02a, "B,H"),
+EFPOP1_2 ("efsqrts",    0x029, "f,g"),
+EFPOP1_3 ("efaddd",     0x042, "v,B,H"),
+EFPOP1_3 ("efadds",     0x041, "e,f,g"),
+EFPOP1_3 ("efsubd",     0x046, "v,B,H"),
+EFPOP1_3 ("efsubs",     0x045, "e,f,g"),
+EFPOP1_3 ("efdivd",     0x04e, "v,B,H"),
+EFPOP1_3 ("efdivs",     0x04d, "e,f,g"),
+EFPOP1_3 ("efmuld",     0x04a, "v,B,H"),
+EFPOP1_3 ("efmuls",     0x049, "e,f,g"),
+EFPOP1_3 ("efsmuld",    0x069, "e,f,H"),
+EFPOP2_2 ("efcmpd",     0x052, "v,B"),
+EFPOP2_2 ("efcmped",    0x056, "v,B"),
+EFPOP2_2 ("efcmps",     0x051, "e,f"),
+EFPOP2_2 ("efcmpes",    0x055, "e,f"),
 
 #undef EFPOP1_2
 #undef EFPOP1_3
@@ -1866,8 +1866,8 @@
 
 /* These are marked F_ALIAS, so that they won't conflict with sparclite insns
    present.  Otherwise, the F_ALIAS flag is ignored.  */
-{ "cpop1",	F3(2, 0x36, 0), F3(~2, ~0x36, ~1), "[1+2],d", F_ALIAS, v6notv9 },
-{ "cpop2",	F3(2, 0x37, 0), F3(~2, ~0x37, ~1), "[1+2],d", F_ALIAS, v6notv9 },
+{ "cpop1",      F3(2, 0x36, 0), F3(~2, ~0x36, ~1), "[1+2],d", F_ALIAS, v6notv9 },
+{ "cpop2",      F3(2, 0x37, 0), F3(~2, ~0x37, ~1), "[1+2],d", F_ALIAS, v6notv9 },
 
 /* sparclet specific insns */
 
@@ -1878,20 +1878,20 @@
 COMMUTEOP ("umuld", 0x09, sparclet),
 COMMUTEOP ("smuld", 0x0d, sparclet),
 
-{ "shuffle",	F3(2, 0x2d, 0), F3(~2, ~0x2d, ~0)|ASI(~0),	"1,2,d", 0, sparclet },
-{ "shuffle",	F3(2, 0x2d, 1), F3(~2, ~0x2d, ~1),		"1,i,d", 0, sparclet },
+{ "shuffle",    F3(2, 0x2d, 0), F3(~2, ~0x2d, ~0)|ASI(~0),      "1,2,d", 0, sparclet },
+{ "shuffle",    F3(2, 0x2d, 1), F3(~2, ~0x2d, ~1),              "1,i,d", 0, sparclet },
 
 /* The manual isn't completely accurate on these insns.  The `rs2' field is
    treated as being 6 bits to account for 6 bit immediates to cpush.  It is
    assumed that it is intended that bit 5 is 0 when rs2 contains a reg.  */
 #define BIT5 (1<<5)
-{ "crdcxt",	F3(2, 0x36, 0)|SLCPOP(4), F3(~2, ~0x36, ~0)|SLCPOP(~4)|BIT5|RS2(~0),	"U,d", 0, sparclet },
-{ "cwrcxt",	F3(2, 0x36, 0)|SLCPOP(3), F3(~2, ~0x36, ~0)|SLCPOP(~3)|BIT5|RS2(~0),	"1,u", 0, sparclet },
-{ "cpush",	F3(2, 0x36, 0)|SLCPOP(0), F3(~2, ~0x36, ~0)|SLCPOP(~0)|BIT5|RD(~0),	"1,2", 0, sparclet },
-{ "cpush",	F3(2, 0x36, 1)|SLCPOP(0), F3(~2, ~0x36, ~1)|SLCPOP(~0)|RD(~0),		"1,Y", 0, sparclet },
-{ "cpusha",	F3(2, 0x36, 0)|SLCPOP(1), F3(~2, ~0x36, ~0)|SLCPOP(~1)|BIT5|RD(~0),	"1,2", 0, sparclet },
-{ "cpusha",	F3(2, 0x36, 1)|SLCPOP(1), F3(~2, ~0x36, ~1)|SLCPOP(~1)|RD(~0),		"1,Y", 0, sparclet },
-{ "cpull",	F3(2, 0x36, 0)|SLCPOP(2), F3(~2, ~0x36, ~0)|SLCPOP(~2)|BIT5|RS1(~0)|RS2(~0), "d", 0, sparclet },
+{ "crdcxt",     F3(2, 0x36, 0)|SLCPOP(4), F3(~2, ~0x36, ~0)|SLCPOP(~4)|BIT5|RS2(~0),    "U,d", 0, sparclet },
+{ "cwrcxt",     F3(2, 0x36, 0)|SLCPOP(3), F3(~2, ~0x36, ~0)|SLCPOP(~3)|BIT5|RS2(~0),    "1,u", 0, sparclet },
+{ "cpush",      F3(2, 0x36, 0)|SLCPOP(0), F3(~2, ~0x36, ~0)|SLCPOP(~0)|BIT5|RD(~0),     "1,2", 0, sparclet },
+{ "cpush",      F3(2, 0x36, 1)|SLCPOP(0), F3(~2, ~0x36, ~1)|SLCPOP(~0)|RD(~0),          "1,Y", 0, sparclet },
+{ "cpusha",     F3(2, 0x36, 0)|SLCPOP(1), F3(~2, ~0x36, ~0)|SLCPOP(~1)|BIT5|RD(~0),     "1,2", 0, sparclet },
+{ "cpusha",     F3(2, 0x36, 1)|SLCPOP(1), F3(~2, ~0x36, ~1)|SLCPOP(~1)|RD(~0),          "1,Y", 0, sparclet },
+{ "cpull",      F3(2, 0x36, 0)|SLCPOP(2), F3(~2, ~0x36, ~0)|SLCPOP(~2)|BIT5|RS1(~0)|RS2(~0), "d", 0, sparclet },
 #undef BIT5
 
 /* sparclet coprocessor branch insns */
@@ -1923,108 +1923,108 @@
 #undef SLCBCC2
 #undef SLCBCC
 
-{ "casa",	F3(3, 0x3c, 0), F3(~3, ~0x3c, ~0), "[1]A,2,d", 0, v9 },
-{ "casa",	F3(3, 0x3c, 1), F3(~3, ~0x3c, ~1), "[1]o,2,d", 0, v9 },
-{ "casxa",	F3(3, 0x3e, 0), F3(~3, ~0x3e, ~0), "[1]A,2,d", 0, v9 },
-{ "casxa",	F3(3, 0x3e, 1), F3(~3, ~0x3e, ~1), "[1]o,2,d", 0, v9 },
+{ "casa",       F3(3, 0x3c, 0), F3(~3, ~0x3c, ~0), "[1]A,2,d", 0, v9 },
+{ "casa",       F3(3, 0x3c, 1), F3(~3, ~0x3c, ~1), "[1]o,2,d", 0, v9 },
+{ "casxa",      F3(3, 0x3e, 0), F3(~3, ~0x3e, ~0), "[1]A,2,d", 0, v9 },
+{ "casxa",      F3(3, 0x3e, 1), F3(~3, ~0x3e, ~1), "[1]o,2,d", 0, v9 },
 
 /* v9 synthetic insns */
-{ "iprefetch",	F2(0, 1)|(2<<20)|BPRED, F2(~0, ~1)|(1<<20)|ANNUL|COND(~0), "G", 0, v9 }, /* bn,a,pt %xcc,label */
-{ "signx",	F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|ASI(~0)|RS2_G0, "1,d", F_ALIAS, v9 }, /* sra rs1,%g0,rd */
-{ "signx",	F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|ASI(~0)|RS2_G0, "r", F_ALIAS, v9 }, /* sra rd,%g0,rd */
-{ "clruw",	F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|ASI(~0)|RS2_G0, "1,d", F_ALIAS, v9 }, /* srl rs1,%g0,rd */
-{ "clruw",	F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|ASI(~0)|RS2_G0, "r", F_ALIAS, v9 }, /* srl rd,%g0,rd */
-{ "cas",	F3(3, 0x3c, 0)|ASI(0x80), F3(~3, ~0x3c, ~0)|ASI(~0x80), "[1],2,d", F_ALIAS, v9 }, /* casa [rs1]ASI_P,rs2,rd */
-{ "casl",	F3(3, 0x3c, 0)|ASI(0x88), F3(~3, ~0x3c, ~0)|ASI(~0x88), "[1],2,d", F_ALIAS, v9 }, /* casa [rs1]ASI_P_L,rs2,rd */
-{ "casx",	F3(3, 0x3e, 0)|ASI(0x80), F3(~3, ~0x3e, ~0)|ASI(~0x80), "[1],2,d", F_ALIAS, v9 }, /* casxa [rs1]ASI_P,rs2,rd */
-{ "casxl",	F3(3, 0x3e, 0)|ASI(0x88), F3(~3, ~0x3e, ~0)|ASI(~0x88), "[1],2,d", F_ALIAS, v9 }, /* casxa [rs1]ASI_P_L,rs2,rd */
+{ "iprefetch",  F2(0, 1)|(2<<20)|BPRED, F2(~0, ~1)|(1<<20)|ANNUL|COND(~0), "G", 0, v9 }, /* bn,a,pt %xcc,label */
+{ "signx",      F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|ASI(~0)|RS2_G0, "1,d", F_ALIAS, v9 }, /* sra rs1,%g0,rd */
+{ "signx",      F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|ASI(~0)|RS2_G0, "r", F_ALIAS, v9 }, /* sra rd,%g0,rd */
+{ "clruw",      F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|ASI(~0)|RS2_G0, "1,d", F_ALIAS, v9 }, /* srl rs1,%g0,rd */
+{ "clruw",      F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|ASI(~0)|RS2_G0, "r", F_ALIAS, v9 }, /* srl rd,%g0,rd */
+{ "cas",        F3(3, 0x3c, 0)|ASI(0x80), F3(~3, ~0x3c, ~0)|ASI(~0x80), "[1],2,d", F_ALIAS, v9 }, /* casa [rs1]ASI_P,rs2,rd */
+{ "casl",       F3(3, 0x3c, 0)|ASI(0x88), F3(~3, ~0x3c, ~0)|ASI(~0x88), "[1],2,d", F_ALIAS, v9 }, /* casa [rs1]ASI_P_L,rs2,rd */
+{ "casx",       F3(3, 0x3e, 0)|ASI(0x80), F3(~3, ~0x3e, ~0)|ASI(~0x80), "[1],2,d", F_ALIAS, v9 }, /* casxa [rs1]ASI_P,rs2,rd */
+{ "casxl",      F3(3, 0x3e, 0)|ASI(0x88), F3(~3, ~0x3e, ~0)|ASI(~0x88), "[1],2,d", F_ALIAS, v9 }, /* casxa [rs1]ASI_P_L,rs2,rd */
 
 /* Ultrasparc extensions */
-{ "shutdown",	F3F(2, 0x36, 0x080), F3F(~2, ~0x36, ~0x080)|RD_G0|RS1_G0|RS2_G0, "", 0, v9a },
+{ "shutdown",   F3F(2, 0x36, 0x080), F3F(~2, ~0x36, ~0x080)|RD_G0|RS1_G0|RS2_G0, "", 0, v9a },
 
 /* FIXME: Do we want to mark these as F_FLOAT, or something similar?  */
-{ "fpadd16",	F3F(2, 0x36, 0x050), F3F(~2, ~0x36, ~0x050), "v,B,H", 0, v9a },
-{ "fpadd16s",	F3F(2, 0x36, 0x051), F3F(~2, ~0x36, ~0x051), "e,f,g", 0, v9a },
-{ "fpadd32",	F3F(2, 0x36, 0x052), F3F(~2, ~0x36, ~0x052), "v,B,H", 0, v9a },
-{ "fpadd32s",	F3F(2, 0x36, 0x053), F3F(~2, ~0x36, ~0x053), "e,f,g", 0, v9a },
-{ "fpsub16",	F3F(2, 0x36, 0x054), F3F(~2, ~0x36, ~0x054), "v,B,H", 0, v9a },
-{ "fpsub16s",	F3F(2, 0x36, 0x055), F3F(~2, ~0x36, ~0x055), "e,f,g", 0, v9a },
-{ "fpsub32",	F3F(2, 0x36, 0x056), F3F(~2, ~0x36, ~0x056), "v,B,H", 0, v9a },
-{ "fpsub32s",	F3F(2, 0x36, 0x057), F3F(~2, ~0x36, ~0x057), "e,f,g", 0, v9a },
+{ "fpadd16",    F3F(2, 0x36, 0x050), F3F(~2, ~0x36, ~0x050), "v,B,H", 0, v9a },
+{ "fpadd16s",   F3F(2, 0x36, 0x051), F3F(~2, ~0x36, ~0x051), "e,f,g", 0, v9a },
+{ "fpadd32",    F3F(2, 0x36, 0x052), F3F(~2, ~0x36, ~0x052), "v,B,H", 0, v9a },
+{ "fpadd32s",   F3F(2, 0x36, 0x053), F3F(~2, ~0x36, ~0x053), "e,f,g", 0, v9a },
+{ "fpsub16",    F3F(2, 0x36, 0x054), F3F(~2, ~0x36, ~0x054), "v,B,H", 0, v9a },
+{ "fpsub16s",   F3F(2, 0x36, 0x055), F3F(~2, ~0x36, ~0x055), "e,f,g", 0, v9a },
+{ "fpsub32",    F3F(2, 0x36, 0x056), F3F(~2, ~0x36, ~0x056), "v,B,H", 0, v9a },
+{ "fpsub32s",   F3F(2, 0x36, 0x057), F3F(~2, ~0x36, ~0x057), "e,f,g", 0, v9a },
 
-{ "fpack32",	F3F(2, 0x36, 0x03a), F3F(~2, ~0x36, ~0x03a), "v,B,H", 0, v9a },
-{ "fpack16",	F3F(2, 0x36, 0x03b), F3F(~2, ~0x36, ~0x03b)|RS1_G0, "B,g", 0, v9a },
-{ "fpackfix",	F3F(2, 0x36, 0x03d), F3F(~2, ~0x36, ~0x03d)|RS1_G0, "B,g", 0, v9a },
-{ "fexpand",	F3F(2, 0x36, 0x04d), F3F(~2, ~0x36, ~0x04d)|RS1_G0, "f,H", 0, v9a },
-{ "fpmerge",	F3F(2, 0x36, 0x04b), F3F(~2, ~0x36, ~0x04b), "e,f,H", 0, v9a },
+{ "fpack32",    F3F(2, 0x36, 0x03a), F3F(~2, ~0x36, ~0x03a), "v,B,H", 0, v9a },
+{ "fpack16",    F3F(2, 0x36, 0x03b), F3F(~2, ~0x36, ~0x03b)|RS1_G0, "B,g", 0, v9a },
+{ "fpackfix",   F3F(2, 0x36, 0x03d), F3F(~2, ~0x36, ~0x03d)|RS1_G0, "B,g", 0, v9a },
+{ "fexpand",    F3F(2, 0x36, 0x04d), F3F(~2, ~0x36, ~0x04d)|RS1_G0, "f,H", 0, v9a },
+{ "fpmerge",    F3F(2, 0x36, 0x04b), F3F(~2, ~0x36, ~0x04b), "e,f,H", 0, v9a },
 
 /* Note that the mixing of 32/64 bit regs is intentional.  */
-{ "fmul8x16",		F3F(2, 0x36, 0x031), F3F(~2, ~0x36, ~0x031), "e,B,H", 0, v9a },
-{ "fmul8x16au",		F3F(2, 0x36, 0x033), F3F(~2, ~0x36, ~0x033), "e,f,H", 0, v9a },
-{ "fmul8x16al",		F3F(2, 0x36, 0x035), F3F(~2, ~0x36, ~0x035), "e,f,H", 0, v9a },
-{ "fmul8sux16",		F3F(2, 0x36, 0x036), F3F(~2, ~0x36, ~0x036), "v,B,H", 0, v9a },
-{ "fmul8ulx16",		F3F(2, 0x36, 0x037), F3F(~2, ~0x36, ~0x037), "v,B,H", 0, v9a },
-{ "fmuld8sux16",	F3F(2, 0x36, 0x038), F3F(~2, ~0x36, ~0x038), "e,f,H", 0, v9a },
-{ "fmuld8ulx16",	F3F(2, 0x36, 0x039), F3F(~2, ~0x36, ~0x039), "e,f,H", 0, v9a },
+{ "fmul8x16",           F3F(2, 0x36, 0x031), F3F(~2, ~0x36, ~0x031), "e,B,H", 0, v9a },
+{ "fmul8x16au",         F3F(2, 0x36, 0x033), F3F(~2, ~0x36, ~0x033), "e,f,H", 0, v9a },
+{ "fmul8x16al",         F3F(2, 0x36, 0x035), F3F(~2, ~0x36, ~0x035), "e,f,H", 0, v9a },
+{ "fmul8sux16",         F3F(2, 0x36, 0x036), F3F(~2, ~0x36, ~0x036), "v,B,H", 0, v9a },
+{ "fmul8ulx16",         F3F(2, 0x36, 0x037), F3F(~2, ~0x36, ~0x037), "v,B,H", 0, v9a },
+{ "fmuld8sux16",        F3F(2, 0x36, 0x038), F3F(~2, ~0x36, ~0x038), "e,f,H", 0, v9a },
+{ "fmuld8ulx16",        F3F(2, 0x36, 0x039), F3F(~2, ~0x36, ~0x039), "e,f,H", 0, v9a },
 
-{ "alignaddr",	F3F(2, 0x36, 0x018), F3F(~2, ~0x36, ~0x018), "1,2,d", 0, v9a },
-{ "alignaddrl",	F3F(2, 0x36, 0x01a), F3F(~2, ~0x36, ~0x01a), "1,2,d", 0, v9a },
-{ "faligndata",	F3F(2, 0x36, 0x048), F3F(~2, ~0x36, ~0x048), "v,B,H", 0, v9a },
+{ "alignaddr",  F3F(2, 0x36, 0x018), F3F(~2, ~0x36, ~0x018), "1,2,d", 0, v9a },
+{ "alignaddrl", F3F(2, 0x36, 0x01a), F3F(~2, ~0x36, ~0x01a), "1,2,d", 0, v9a },
+{ "faligndata", F3F(2, 0x36, 0x048), F3F(~2, ~0x36, ~0x048), "v,B,H", 0, v9a },
 
-{ "fzero",	F3F(2, 0x36, 0x060), F3F(~2, ~0x36, ~0x060), "H", 0, v9a },
-{ "fzeros",	F3F(2, 0x36, 0x061), F3F(~2, ~0x36, ~0x061), "g", 0, v9a },
-{ "fone",	F3F(2, 0x36, 0x07e), F3F(~2, ~0x36, ~0x07e), "H", 0, v9a },
-{ "fones",	F3F(2, 0x36, 0x07f), F3F(~2, ~0x36, ~0x07f), "g", 0, v9a },
-{ "fsrc1",	F3F(2, 0x36, 0x074), F3F(~2, ~0x36, ~0x074), "v,H", 0, v9a },
-{ "fsrc1s",	F3F(2, 0x36, 0x075), F3F(~2, ~0x36, ~0x075), "e,g", 0, v9a },
-{ "fsrc2",	F3F(2, 0x36, 0x078), F3F(~2, ~0x36, ~0x078), "B,H", 0, v9a },
-{ "fsrc2s",	F3F(2, 0x36, 0x079), F3F(~2, ~0x36, ~0x079), "f,g", 0, v9a },
-{ "fnot1",	F3F(2, 0x36, 0x06a), F3F(~2, ~0x36, ~0x06a), "v,H", 0, v9a },
-{ "fnot1s",	F3F(2, 0x36, 0x06b), F3F(~2, ~0x36, ~0x06b), "e,g", 0, v9a },
-{ "fnot2",	F3F(2, 0x36, 0x066), F3F(~2, ~0x36, ~0x066), "B,H", 0, v9a },
-{ "fnot2s",	F3F(2, 0x36, 0x067), F3F(~2, ~0x36, ~0x067), "f,g", 0, v9a },
-{ "for",	F3F(2, 0x36, 0x07c), F3F(~2, ~0x36, ~0x07c), "v,B,H", 0, v9a },
-{ "fors",	F3F(2, 0x36, 0x07d), F3F(~2, ~0x36, ~0x07d), "e,f,g", 0, v9a },
-{ "fnor",	F3F(2, 0x36, 0x062), F3F(~2, ~0x36, ~0x062), "v,B,H", 0, v9a },
-{ "fnors",	F3F(2, 0x36, 0x063), F3F(~2, ~0x36, ~0x063), "e,f,g", 0, v9a },
-{ "fand",	F3F(2, 0x36, 0x070), F3F(~2, ~0x36, ~0x070), "v,B,H", 0, v9a },
-{ "fands",	F3F(2, 0x36, 0x071), F3F(~2, ~0x36, ~0x071), "e,f,g", 0, v9a },
-{ "fnand",	F3F(2, 0x36, 0x06e), F3F(~2, ~0x36, ~0x06e), "v,B,H", 0, v9a },
-{ "fnands",	F3F(2, 0x36, 0x06f), F3F(~2, ~0x36, ~0x06f), "e,f,g", 0, v9a },
-{ "fxor",	F3F(2, 0x36, 0x06c), F3F(~2, ~0x36, ~0x06c), "v,B,H", 0, v9a },
-{ "fxors",	F3F(2, 0x36, 0x06d), F3F(~2, ~0x36, ~0x06d), "e,f,g", 0, v9a },
-{ "fxnor",	F3F(2, 0x36, 0x072), F3F(~2, ~0x36, ~0x072), "v,B,H", 0, v9a },
-{ "fxnors",	F3F(2, 0x36, 0x073), F3F(~2, ~0x36, ~0x073), "e,f,g", 0, v9a },
-{ "fornot1",	F3F(2, 0x36, 0x07a), F3F(~2, ~0x36, ~0x07a), "v,B,H", 0, v9a },
-{ "fornot1s",	F3F(2, 0x36, 0x07b), F3F(~2, ~0x36, ~0x07b), "e,f,g", 0, v9a },
-{ "fornot2",	F3F(2, 0x36, 0x076), F3F(~2, ~0x36, ~0x076), "v,B,H", 0, v9a },
-{ "fornot2s",	F3F(2, 0x36, 0x077), F3F(~2, ~0x36, ~0x077), "e,f,g", 0, v9a },
-{ "fandnot1",	F3F(2, 0x36, 0x068), F3F(~2, ~0x36, ~0x068), "v,B,H", 0, v9a },
-{ "fandnot1s",	F3F(2, 0x36, 0x069), F3F(~2, ~0x36, ~0x069), "e,f,g", 0, v9a },
-{ "fandnot2",	F3F(2, 0x36, 0x064), F3F(~2, ~0x36, ~0x064), "v,B,H", 0, v9a },
-{ "fandnot2s",	F3F(2, 0x36, 0x065), F3F(~2, ~0x36, ~0x065), "e,f,g", 0, v9a },
+{ "fzero",      F3F(2, 0x36, 0x060), F3F(~2, ~0x36, ~0x060), "H", 0, v9a },
+{ "fzeros",     F3F(2, 0x36, 0x061), F3F(~2, ~0x36, ~0x061), "g", 0, v9a },
+{ "fone",       F3F(2, 0x36, 0x07e), F3F(~2, ~0x36, ~0x07e), "H", 0, v9a },
+{ "fones",      F3F(2, 0x36, 0x07f), F3F(~2, ~0x36, ~0x07f), "g", 0, v9a },
+{ "fsrc1",      F3F(2, 0x36, 0x074), F3F(~2, ~0x36, ~0x074), "v,H", 0, v9a },
+{ "fsrc1s",     F3F(2, 0x36, 0x075), F3F(~2, ~0x36, ~0x075), "e,g", 0, v9a },
+{ "fsrc2",      F3F(2, 0x36, 0x078), F3F(~2, ~0x36, ~0x078), "B,H", 0, v9a },
+{ "fsrc2s",     F3F(2, 0x36, 0x079), F3F(~2, ~0x36, ~0x079), "f,g", 0, v9a },
+{ "fnot1",      F3F(2, 0x36, 0x06a), F3F(~2, ~0x36, ~0x06a), "v,H", 0, v9a },
+{ "fnot1s",     F3F(2, 0x36, 0x06b), F3F(~2, ~0x36, ~0x06b), "e,g", 0, v9a },
+{ "fnot2",      F3F(2, 0x36, 0x066), F3F(~2, ~0x36, ~0x066), "B,H", 0, v9a },
+{ "fnot2s",     F3F(2, 0x36, 0x067), F3F(~2, ~0x36, ~0x067), "f,g", 0, v9a },
+{ "for",        F3F(2, 0x36, 0x07c), F3F(~2, ~0x36, ~0x07c), "v,B,H", 0, v9a },
+{ "fors",       F3F(2, 0x36, 0x07d), F3F(~2, ~0x36, ~0x07d), "e,f,g", 0, v9a },
+{ "fnor",       F3F(2, 0x36, 0x062), F3F(~2, ~0x36, ~0x062), "v,B,H", 0, v9a },
+{ "fnors",      F3F(2, 0x36, 0x063), F3F(~2, ~0x36, ~0x063), "e,f,g", 0, v9a },
+{ "fand",       F3F(2, 0x36, 0x070), F3F(~2, ~0x36, ~0x070), "v,B,H", 0, v9a },
+{ "fands",      F3F(2, 0x36, 0x071), F3F(~2, ~0x36, ~0x071), "e,f,g", 0, v9a },
+{ "fnand",      F3F(2, 0x36, 0x06e), F3F(~2, ~0x36, ~0x06e), "v,B,H", 0, v9a },
+{ "fnands",     F3F(2, 0x36, 0x06f), F3F(~2, ~0x36, ~0x06f), "e,f,g", 0, v9a },
+{ "fxor",       F3F(2, 0x36, 0x06c), F3F(~2, ~0x36, ~0x06c), "v,B,H", 0, v9a },
+{ "fxors",      F3F(2, 0x36, 0x06d), F3F(~2, ~0x36, ~0x06d), "e,f,g", 0, v9a },
+{ "fxnor",      F3F(2, 0x36, 0x072), F3F(~2, ~0x36, ~0x072), "v,B,H", 0, v9a },
+{ "fxnors",     F3F(2, 0x36, 0x073), F3F(~2, ~0x36, ~0x073), "e,f,g", 0, v9a },
+{ "fornot1",    F3F(2, 0x36, 0x07a), F3F(~2, ~0x36, ~0x07a), "v,B,H", 0, v9a },
+{ "fornot1s",   F3F(2, 0x36, 0x07b), F3F(~2, ~0x36, ~0x07b), "e,f,g", 0, v9a },
+{ "fornot2",    F3F(2, 0x36, 0x076), F3F(~2, ~0x36, ~0x076), "v,B,H", 0, v9a },
+{ "fornot2s",   F3F(2, 0x36, 0x077), F3F(~2, ~0x36, ~0x077), "e,f,g", 0, v9a },
+{ "fandnot1",   F3F(2, 0x36, 0x068), F3F(~2, ~0x36, ~0x068), "v,B,H", 0, v9a },
+{ "fandnot1s",  F3F(2, 0x36, 0x069), F3F(~2, ~0x36, ~0x069), "e,f,g", 0, v9a },
+{ "fandnot2",   F3F(2, 0x36, 0x064), F3F(~2, ~0x36, ~0x064), "v,B,H", 0, v9a },
+{ "fandnot2s",  F3F(2, 0x36, 0x065), F3F(~2, ~0x36, ~0x065), "e,f,g", 0, v9a },
 
-{ "fcmpgt16",	F3F(2, 0x36, 0x028), F3F(~2, ~0x36, ~0x028), "v,B,d", 0, v9a },
-{ "fcmpgt32",	F3F(2, 0x36, 0x02c), F3F(~2, ~0x36, ~0x02c), "v,B,d", 0, v9a },
-{ "fcmple16",	F3F(2, 0x36, 0x020), F3F(~2, ~0x36, ~0x020), "v,B,d", 0, v9a },
-{ "fcmple32",	F3F(2, 0x36, 0x024), F3F(~2, ~0x36, ~0x024), "v,B,d", 0, v9a },
-{ "fcmpne16",	F3F(2, 0x36, 0x022), F3F(~2, ~0x36, ~0x022), "v,B,d", 0, v9a },
-{ "fcmpne32",	F3F(2, 0x36, 0x026), F3F(~2, ~0x36, ~0x026), "v,B,d", 0, v9a },
-{ "fcmpeq16",	F3F(2, 0x36, 0x02a), F3F(~2, ~0x36, ~0x02a), "v,B,d", 0, v9a },
-{ "fcmpeq32",	F3F(2, 0x36, 0x02e), F3F(~2, ~0x36, ~0x02e), "v,B,d", 0, v9a },
+{ "fcmpgt16",   F3F(2, 0x36, 0x028), F3F(~2, ~0x36, ~0x028), "v,B,d", 0, v9a },
+{ "fcmpgt32",   F3F(2, 0x36, 0x02c), F3F(~2, ~0x36, ~0x02c), "v,B,d", 0, v9a },
+{ "fcmple16",   F3F(2, 0x36, 0x020), F3F(~2, ~0x36, ~0x020), "v,B,d", 0, v9a },
+{ "fcmple32",   F3F(2, 0x36, 0x024), F3F(~2, ~0x36, ~0x024), "v,B,d", 0, v9a },
+{ "fcmpne16",   F3F(2, 0x36, 0x022), F3F(~2, ~0x36, ~0x022), "v,B,d", 0, v9a },
+{ "fcmpne32",   F3F(2, 0x36, 0x026), F3F(~2, ~0x36, ~0x026), "v,B,d", 0, v9a },
+{ "fcmpeq16",   F3F(2, 0x36, 0x02a), F3F(~2, ~0x36, ~0x02a), "v,B,d", 0, v9a },
+{ "fcmpeq32",   F3F(2, 0x36, 0x02e), F3F(~2, ~0x36, ~0x02e), "v,B,d", 0, v9a },
 
-{ "edge8",	F3F(2, 0x36, 0x000), F3F(~2, ~0x36, ~0x000), "1,2,d", 0, v9a },
-{ "edge8l",	F3F(2, 0x36, 0x002), F3F(~2, ~0x36, ~0x002), "1,2,d", 0, v9a },
-{ "edge16",	F3F(2, 0x36, 0x004), F3F(~2, ~0x36, ~0x004), "1,2,d", 0, v9a },
-{ "edge16l",	F3F(2, 0x36, 0x006), F3F(~2, ~0x36, ~0x006), "1,2,d", 0, v9a },
-{ "edge32",	F3F(2, 0x36, 0x008), F3F(~2, ~0x36, ~0x008), "1,2,d", 0, v9a },
-{ "edge32l",	F3F(2, 0x36, 0x00a), F3F(~2, ~0x36, ~0x00a), "1,2,d", 0, v9a },
+{ "edge8",      F3F(2, 0x36, 0x000), F3F(~2, ~0x36, ~0x000), "1,2,d", 0, v9a },
+{ "edge8l",     F3F(2, 0x36, 0x002), F3F(~2, ~0x36, ~0x002), "1,2,d", 0, v9a },
+{ "edge16",     F3F(2, 0x36, 0x004), F3F(~2, ~0x36, ~0x004), "1,2,d", 0, v9a },
+{ "edge16l",    F3F(2, 0x36, 0x006), F3F(~2, ~0x36, ~0x006), "1,2,d", 0, v9a },
+{ "edge32",     F3F(2, 0x36, 0x008), F3F(~2, ~0x36, ~0x008), "1,2,d", 0, v9a },
+{ "edge32l",    F3F(2, 0x36, 0x00a), F3F(~2, ~0x36, ~0x00a), "1,2,d", 0, v9a },
 
-{ "pdist",	F3F(2, 0x36, 0x03e), F3F(~2, ~0x36, ~0x03e), "v,B,H", 0, v9a },
+{ "pdist",      F3F(2, 0x36, 0x03e), F3F(~2, ~0x36, ~0x03e), "v,B,H", 0, v9a },
 
-{ "array8",	F3F(2, 0x36, 0x010), F3F(~2, ~0x36, ~0x010), "1,2,d", 0, v9a },
-{ "array16",	F3F(2, 0x36, 0x012), F3F(~2, ~0x36, ~0x012), "1,2,d", 0, v9a },
-{ "array32",	F3F(2, 0x36, 0x014), F3F(~2, ~0x36, ~0x014), "1,2,d", 0, v9a },
+{ "array8",     F3F(2, 0x36, 0x010), F3F(~2, ~0x36, ~0x010), "1,2,d", 0, v9a },
+{ "array16",    F3F(2, 0x36, 0x012), F3F(~2, ~0x36, ~0x012), "1,2,d", 0, v9a },
+{ "array32",    F3F(2, 0x36, 0x014), F3F(~2, ~0x36, ~0x014), "1,2,d", 0, v9a },
 
 /* Cheetah instructions */
 { "edge8n",    F3F(2, 0x36, 0x001), F3F(~2, ~0x36, ~0x001), "1,2,d", 0, v9b },
@@ -2043,8 +2043,8 @@
    with v9a instructions such as "edge8" which looks like impdep1. */
 
 #define IMPDEP(name, code) \
-{ name,	F3(2, code, 0), F3(~2, ~code, ~0)|ASI(~0), "1,2,d", 0, v9notv9a }, \
-{ name,	F3(2, code, 1), F3(~2, ~code, ~1),	   "1,i,d", 0, v9notv9a }, \
+{ name, F3(2, code, 0), F3(~2, ~code, ~0)|ASI(~0), "1,2,d", 0, v9notv9a }, \
+{ name, F3(2, code, 1), F3(~2, ~code, ~1),         "1,i,d", 0, v9notv9a }, \
 { name, F3(2, code, 0), F3(~2, ~code, ~0),         "x,1,2,d", 0, v9notv9a }, \
 { name, F3(2, code, 0), F3(~2, ~code, ~0),         "x,e,f,g", 0, v9notv9a }
 
@@ -2303,8 +2303,8 @@
 
 /* Bitmask of v9 architectures.  */
 #define MASK_V9 ((1 << SPARC_OPCODE_ARCH_V9) \
-		 | (1 << SPARC_OPCODE_ARCH_V9A) \
-		 | (1 << SPARC_OPCODE_ARCH_V9B))
+                 | (1 << SPARC_OPCODE_ARCH_V9A) \
+                 | (1 << SPARC_OPCODE_ARCH_V9B))
 /* 1 if INSN is for v9 only.  */
 #define V9_ONLY_P(insn) (! ((insn)->architecture & ~MASK_V9))
 /* 1 if INSN is for v9.  */
@@ -2336,9 +2336,9 @@
 static int compute_arch_mask PARAMS ((unsigned long));
 
 /* Sign-extend a value which is N bits long.  */
-#define	SEX(value, bits) \
-	((((int)(value)) << ((8 * sizeof (int)) - bits))	\
-			 >> ((8 * sizeof (int)) - bits) )
+#define SEX(value, bits) \
+        ((((int)(value)) << ((8 * sizeof (int)) - bits))        \
+                         >> ((8 * sizeof (int)) - bits) )
 
 static const char * const reg_names[] =
 { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
@@ -2357,7 +2357,7 @@
   "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr"
 };
 
-#define	freg_names	(&reg_names[4 * 8])
+#define freg_names      (&reg_names[4 * 8])
 
 /* These are ordered according to there register number in
    rdpr and wrpr insns.  */
@@ -2403,55 +2403,55 @@
      {
        unsigned long int code;
        struct
-	 {
-	   unsigned int anop:2;
-	   #define	op	ldst.anop
-	   unsigned int anrd:5;
-	   #define	rd	ldst.anrd
-	   unsigned int op3:6;
-	   unsigned int anrs1:5;
-	   #define	rs1	ldst.anrs1
-	   unsigned int i:1;
-	   unsigned int anasi:8;
-	   #define	asi	ldst.anasi
-	   unsigned int anrs2:5;
-	   #define	rs2	ldst.anrs2
-	   #define	shcnt	rs2
-	 } ldst;
+         {
+           unsigned int anop:2;
+           #define      op      ldst.anop
+           unsigned int anrd:5;
+           #define      rd      ldst.anrd
+           unsigned int op3:6;
+           unsigned int anrs1:5;
+           #define      rs1     ldst.anrs1
+           unsigned int i:1;
+           unsigned int anasi:8;
+           #define      asi     ldst.anasi
+           unsigned int anrs2:5;
+           #define      rs2     ldst.anrs2
+           #define      shcnt   rs2
+         } ldst;
        struct
-	 {
-	   unsigned int anop:2, anrd:5, op3:6, anrs1:5, i:1;
-	   unsigned int IMM13:13;
-	   #define	imm13	IMM13.IMM13
-	 } IMM13;
+         {
+           unsigned int anop:2, anrd:5, op3:6, anrs1:5, i:1;
+           unsigned int IMM13:13;
+           #define      imm13   IMM13.IMM13
+         } IMM13;
        struct
-	 {
-	   unsigned int anop:2;
-	   unsigned int a:1;
-	   unsigned int cond:4;
-	   unsigned int op2:3;
-	   unsigned int DISP22:22;
-	   #define	disp22	branch.DISP22
-	   #define	imm22	disp22
-	 } branch;
+         {
+           unsigned int anop:2;
+           unsigned int a:1;
+           unsigned int cond:4;
+           unsigned int op2:3;
+           unsigned int DISP22:22;
+           #define      disp22  branch.DISP22
+           #define      imm22   disp22
+         } branch;
        struct
-	 {
-	   unsigned int anop:2;
-	   unsigned int a:1;
-	   unsigned int z:1;
-	   unsigned int rcond:3;
-	   unsigned int op2:3;
-	   unsigned int DISP16HI:2;
-	   unsigned int p:1;
-	   unsigned int _rs1:5;
-	   unsigned int DISP16LO:14;
-	 } branch16;
+         {
+           unsigned int anop:2;
+           unsigned int a:1;
+           unsigned int z:1;
+           unsigned int rcond:3;
+           unsigned int op2:3;
+           unsigned int DISP16HI:2;
+           unsigned int p:1;
+           unsigned int _rs1:5;
+           unsigned int DISP16LO:14;
+         } branch16;
        struct
-	 {
-	   unsigned int anop:2;
-	   unsigned int adisp30:30;
-	   #define	disp30	call.adisp30
-	 } call;
+         {
+           unsigned int anop:2;
+           unsigned int adisp30:30;
+           #define      disp30  call.adisp30
+         } call;
      };
 
    */
@@ -2467,8 +2467,8 @@
     {
       const struct sparc_opcode *opcode = op->opcode;
       if ((opcode->match & insn) == opcode->match
-	  && (opcode->lose & insn) == 0)
-	return (opcode->flags & F_DELAYED);
+          && (opcode->lose & insn) == 0)
+        return (opcode->flags & F_DELAYED);
     }
   return 0;
 }
@@ -2510,13 +2510,13 @@
       current_arch_mask = compute_arch_mask (info->mach);
 
       if (!opcodes_initialized)
-	sorted_opcodes = (const struct sparc_opcode **)
+        sorted_opcodes = (const struct sparc_opcode **)
             malloc (sparc_num_opcodes * sizeof (struct sparc_opcode *));
       /* Reset the sorted table so we can resort it.  */
       for (i = 0; i < sparc_num_opcodes; ++i)
-	sorted_opcodes[i] = &sparc_opcodes[i];
+        sorted_opcodes[i] = &sparc_opcodes[i];
       qsort ((char *) sorted_opcodes, sparc_num_opcodes,
-	     sizeof (sorted_opcodes[0]), compare_opcodes);
+             sizeof (sorted_opcodes[0]), compare_opcodes);
 
       build_hash_table (sorted_opcodes, opcode_hash_table, sparc_num_opcodes);
       current_mach = info->mach;
@@ -2528,8 +2528,8 @@
       (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);
     if (status != 0)
       {
-	(*info->memory_error_func) (status, memaddr, info);
-	return -1;
+        (*info->memory_error_func) (status, memaddr, info);
+        return -1;
       }
   }
 
@@ -2542,10 +2542,10 @@
 
   insn = getword (buffer);
 
-  info->insn_info_valid = 1;			/* We do return this info */
-  info->insn_type = dis_nonbranch;		/* Assume non branch insn */
-  info->branch_delay_insns = 0;			/* Assume no delay */
-  info->target = 0;				/* Assume no target known */
+  info->insn_info_valid = 1;                    /* We do return this info */
+  info->insn_type = dis_nonbranch;              /* Assume non branch insn */
+  info->branch_delay_insns = 0;                 /* Assume no delay */
+  info->target = 0;                             /* Assume no target known */
 
   for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next)
     {
@@ -2553,484 +2553,484 @@
 
       /* If the insn isn't supported by the current architecture, skip it.  */
       if (! (opcode->architecture & current_arch_mask))
-	continue;
+        continue;
 
       if ((opcode->match & insn) == opcode->match
-	  && (opcode->lose & insn) == 0)
-	{
-	  /* Nonzero means that we have found an instruction which has
-	     the effect of adding or or'ing the imm13 field to rs1.  */
-	  int imm_added_to_rs1 = 0;
-	  int imm_ored_to_rs1 = 0;
+          && (opcode->lose & insn) == 0)
+        {
+          /* Nonzero means that we have found an instruction which has
+             the effect of adding or or'ing the imm13 field to rs1.  */
+          int imm_added_to_rs1 = 0;
+          int imm_ored_to_rs1 = 0;
 
-	  /* Nonzero means that we have found a plus sign in the args
-	     field of the opcode table.  */
-	  int found_plus = 0;
+          /* Nonzero means that we have found a plus sign in the args
+             field of the opcode table.  */
+          int found_plus = 0;
 
-	  /* Nonzero means we have an annulled branch.  */
-	  int is_annulled = 0;
+          /* Nonzero means we have an annulled branch.  */
+          int is_annulled = 0;
 
-	  /* Do we have an `add' or `or' instruction combining an
+          /* Do we have an `add' or `or' instruction combining an
              immediate with rs1?  */
-	  if (opcode->match == 0x80102000) /* or */
-	    imm_ored_to_rs1 = 1;
-	  if (opcode->match == 0x80002000) /* add */
-	    imm_added_to_rs1 = 1;
+          if (opcode->match == 0x80102000) /* or */
+            imm_ored_to_rs1 = 1;
+          if (opcode->match == 0x80002000) /* add */
+            imm_added_to_rs1 = 1;
 
-	  if (X_RS1 (insn) != X_RD (insn)
-	      && strchr (opcode->args, 'r') != 0)
-	      /* Can't do simple format if source and dest are different.  */
-	      continue;
-	  if (X_RS2 (insn) != X_RD (insn)
-	      && strchr (opcode->args, 'O') != 0)
-	      /* Can't do simple format if source and dest are different.  */
-	      continue;
+          if (X_RS1 (insn) != X_RD (insn)
+              && strchr (opcode->args, 'r') != 0)
+              /* Can't do simple format if source and dest are different.  */
+              continue;
+          if (X_RS2 (insn) != X_RD (insn)
+              && strchr (opcode->args, 'O') != 0)
+              /* Can't do simple format if source and dest are different.  */
+              continue;
 
-	  (*info->fprintf_func) (stream, opcode->name);
+          (*info->fprintf_func) (stream, opcode->name);
 
-	  {
-	    register const char *s;
+          {
+            register const char *s;
 
-	    if (opcode->args[0] != ',')
-	      (*info->fprintf_func) (stream, " ");
-	    for (s = opcode->args; *s != '\0'; ++s)
-	      {
-		while (*s == ',')
-		  {
-		    (*info->fprintf_func) (stream, ",");
-		    ++s;
-		    switch (*s) {
-		    case 'a':
-		      (*info->fprintf_func) (stream, "a");
-		      is_annulled = 1;
-		      ++s;
-		      continue;
-		    case 'N':
-		      (*info->fprintf_func) (stream, "pn");
-		      ++s;
-		      continue;
+            if (opcode->args[0] != ',')
+              (*info->fprintf_func) (stream, " ");
+            for (s = opcode->args; *s != '\0'; ++s)
+              {
+                while (*s == ',')
+                  {
+                    (*info->fprintf_func) (stream, ",");
+                    ++s;
+                    switch (*s) {
+                    case 'a':
+                      (*info->fprintf_func) (stream, "a");
+                      is_annulled = 1;
+                      ++s;
+                      continue;
+                    case 'N':
+                      (*info->fprintf_func) (stream, "pn");
+                      ++s;
+                      continue;
 
-		    case 'T':
-		      (*info->fprintf_func) (stream, "pt");
-		      ++s;
-		      continue;
+                    case 'T':
+                      (*info->fprintf_func) (stream, "pt");
+                      ++s;
+                      continue;
 
-		    default:
-		      break;
-		    }		/* switch on arg */
-		  }		/* while there are comma started args */
+                    default:
+                      break;
+                    }           /* switch on arg */
+                  }             /* while there are comma started args */
 
-		(*info->fprintf_func) (stream, " ");
+                (*info->fprintf_func) (stream, " ");
 
-		switch (*s)
-		  {
-		  case '+':
-		    found_plus = 1;
+                switch (*s)
+                  {
+                  case '+':
+                    found_plus = 1;
 
-		    /* note fall-through */
-		  default:
-		    (*info->fprintf_func) (stream, "%c", *s);
-		    break;
+                    /* note fall-through */
+                  default:
+                    (*info->fprintf_func) (stream, "%c", *s);
+                    break;
 
-		  case '#':
-		    (*info->fprintf_func) (stream, "0");
-		    break;
+                  case '#':
+                    (*info->fprintf_func) (stream, "0");
+                    break;
 
-#define	reg(n)	(*info->fprintf_func) (stream, "%%%s", reg_names[n])
-		  case '1':
-		  case 'r':
-		    reg (X_RS1 (insn));
-		    break;
+#define reg(n)  (*info->fprintf_func) (stream, "%%%s", reg_names[n])
+                  case '1':
+                  case 'r':
+                    reg (X_RS1 (insn));
+                    break;
 
-		  case '2':
-		  case 'O':
-		    reg (X_RS2 (insn));
-		    break;
+                  case '2':
+                  case 'O':
+                    reg (X_RS2 (insn));
+                    break;
 
-		  case 'd':
-		    reg (X_RD (insn));
-		    break;
-#undef	reg
+                  case 'd':
+                    reg (X_RD (insn));
+                    break;
+#undef  reg
 
-#define	freg(n)		(*info->fprintf_func) (stream, "%%%s", freg_names[n])
-#define	fregx(n)	(*info->fprintf_func) (stream, "%%%s", freg_names[((n) & ~1) | (((n) & 1) << 5)])
-		  case 'e':
-		    freg (X_RS1 (insn));
-		    break;
-		  case 'v':	/* double/even */
-		  case 'V':	/* quad/multiple of 4 */
-		    fregx (X_RS1 (insn));
-		    break;
+#define freg(n)         (*info->fprintf_func) (stream, "%%%s", freg_names[n])
+#define fregx(n)        (*info->fprintf_func) (stream, "%%%s", freg_names[((n) & ~1) | (((n) & 1) << 5)])
+                  case 'e':
+                    freg (X_RS1 (insn));
+                    break;
+                  case 'v':     /* double/even */
+                  case 'V':     /* quad/multiple of 4 */
+                    fregx (X_RS1 (insn));
+                    break;
 
-		  case 'f':
-		    freg (X_RS2 (insn));
-		    break;
-		  case 'B':	/* double/even */
-		  case 'R':	/* quad/multiple of 4 */
-		    fregx (X_RS2 (insn));
-		    break;
+                  case 'f':
+                    freg (X_RS2 (insn));
+                    break;
+                  case 'B':     /* double/even */
+                  case 'R':     /* quad/multiple of 4 */
+                    fregx (X_RS2 (insn));
+                    break;
 
-		  case 'g':
-		    freg (X_RD (insn));
-		    break;
-		  case 'H':	/* double/even */
-		  case 'J':	/* quad/multiple of 4 */
-		    fregx (X_RD (insn));
-		    break;
-#undef	freg
-#undef	fregx
+                  case 'g':
+                    freg (X_RD (insn));
+                    break;
+                  case 'H':     /* double/even */
+                  case 'J':     /* quad/multiple of 4 */
+                    fregx (X_RD (insn));
+                    break;
+#undef  freg
+#undef  fregx
 
-#define	creg(n)	(*info->fprintf_func) (stream, "%%c%u", (unsigned int) (n))
-		  case 'b':
-		    creg (X_RS1 (insn));
-		    break;
+#define creg(n) (*info->fprintf_func) (stream, "%%c%u", (unsigned int) (n))
+                  case 'b':
+                    creg (X_RS1 (insn));
+                    break;
 
-		  case 'c':
-		    creg (X_RS2 (insn));
-		    break;
+                  case 'c':
+                    creg (X_RS2 (insn));
+                    break;
 
-		  case 'D':
-		    creg (X_RD (insn));
-		    break;
-#undef	creg
+                  case 'D':
+                    creg (X_RD (insn));
+                    break;
+#undef  creg
 
-		  case 'h':
-		    (*info->fprintf_func) (stream, "%%hi(%#x)",
-					   ((unsigned) 0xFFFFFFFF
-					    & ((int) X_IMM22 (insn) << 10)));
-		    break;
+                  case 'h':
+                    (*info->fprintf_func) (stream, "%%hi(%#x)",
+                                           ((unsigned) 0xFFFFFFFF
+                                            & ((int) X_IMM22 (insn) << 10)));
+                    break;
 
-		  case 'i':	/* 13 bit immediate */
-		  case 'I':	/* 11 bit immediate */
-		  case 'j':	/* 10 bit immediate */
-		    {
-		      int imm;
+                  case 'i':     /* 13 bit immediate */
+                  case 'I':     /* 11 bit immediate */
+                  case 'j':     /* 10 bit immediate */
+                    {
+                      int imm;
 
-		      if (*s == 'i')
-		        imm = X_SIMM (insn, 13);
-		      else if (*s == 'I')
-			imm = X_SIMM (insn, 11);
-		      else
-			imm = X_SIMM (insn, 10);
+                      if (*s == 'i')
+                        imm = X_SIMM (insn, 13);
+                      else if (*s == 'I')
+                        imm = X_SIMM (insn, 11);
+                      else
+                        imm = X_SIMM (insn, 10);
 
-		      /* Check to see whether we have a 1+i, and take
-			 note of that fact.
+                      /* Check to see whether we have a 1+i, and take
+                         note of that fact.
 
-			 Note: because of the way we sort the table,
-			 we will be matching 1+i rather than i+1,
-			 so it is OK to assume that i is after +,
-			 not before it.  */
-		      if (found_plus)
-			imm_added_to_rs1 = 1;
+                         Note: because of the way we sort the table,
+                         we will be matching 1+i rather than i+1,
+                         so it is OK to assume that i is after +,
+                         not before it.  */
+                      if (found_plus)
+                        imm_added_to_rs1 = 1;
 
-		      if (imm <= 9)
-			(*info->fprintf_func) (stream, "%d", imm);
-		      else
-			(*info->fprintf_func) (stream, "%#x", imm);
-		    }
-		    break;
+                      if (imm <= 9)
+                        (*info->fprintf_func) (stream, "%d", imm);
+                      else
+                        (*info->fprintf_func) (stream, "%#x", imm);
+                    }
+                    break;
 
-		  case 'X':	/* 5 bit unsigned immediate */
-		  case 'Y':	/* 6 bit unsigned immediate */
-		    {
-		      int imm = X_IMM (insn, *s == 'X' ? 5 : 6);
+                  case 'X':     /* 5 bit unsigned immediate */
+                  case 'Y':     /* 6 bit unsigned immediate */
+                    {
+                      int imm = X_IMM (insn, *s == 'X' ? 5 : 6);
 
-		      if (imm <= 9)
-			(info->fprintf_func) (stream, "%d", imm);
-		      else
-			(info->fprintf_func) (stream, "%#x", (unsigned) imm);
-		    }
-		    break;
+                      if (imm <= 9)
+                        (info->fprintf_func) (stream, "%d", imm);
+                      else
+                        (info->fprintf_func) (stream, "%#x", (unsigned) imm);
+                    }
+                    break;
 
-		  case '3':
-		    (info->fprintf_func) (stream, "%d", X_IMM (insn, 3));
-		    break;
+                  case '3':
+                    (info->fprintf_func) (stream, "%d", X_IMM (insn, 3));
+                    break;
 
-		  case 'K':
-		    {
-		      int mask = X_MEMBAR (insn);
-		      int bit = 0x40, printed_one = 0;
-		      const char *name;
+                  case 'K':
+                    {
+                      int mask = X_MEMBAR (insn);
+                      int bit = 0x40, printed_one = 0;
+                      const char *name;
 
-		      if (mask == 0)
-			(info->fprintf_func) (stream, "0");
-		      else
-			while (bit)
-			  {
-			    if (mask & bit)
-			      {
-				if (printed_one)
-				  (info->fprintf_func) (stream, "|");
-				name = sparc_decode_membar (bit);
-				(info->fprintf_func) (stream, "%s", name);
-				printed_one = 1;
-			      }
-			    bit >>= 1;
-			  }
-		      break;
-		    }
+                      if (mask == 0)
+                        (info->fprintf_func) (stream, "0");
+                      else
+                        while (bit)
+                          {
+                            if (mask & bit)
+                              {
+                                if (printed_one)
+                                  (info->fprintf_func) (stream, "|");
+                                name = sparc_decode_membar (bit);
+                                (info->fprintf_func) (stream, "%s", name);
+                                printed_one = 1;
+                              }
+                            bit >>= 1;
+                          }
+                      break;
+                    }
 
-		  case 'k':
-		    info->target = memaddr + SEX (X_DISP16 (insn), 16) * 4;
-		    (*info->print_address_func) (info->target, info);
-		    break;
+                  case 'k':
+                    info->target = memaddr + SEX (X_DISP16 (insn), 16) * 4;
+                    (*info->print_address_func) (info->target, info);
+                    break;
 
-		  case 'G':
-		    info->target = memaddr + SEX (X_DISP19 (insn), 19) * 4;
-		    (*info->print_address_func) (info->target, info);
-		    break;
+                  case 'G':
+                    info->target = memaddr + SEX (X_DISP19 (insn), 19) * 4;
+                    (*info->print_address_func) (info->target, info);
+                    break;
 
-		  case '6':
-		  case '7':
-		  case '8':
-		  case '9':
-		    (*info->fprintf_func) (stream, "%%fcc%c", *s - '6' + '0');
-		    break;
+                  case '6':
+                  case '7':
+                  case '8':
+                  case '9':
+                    (*info->fprintf_func) (stream, "%%fcc%c", *s - '6' + '0');
+                    break;
 
-		  case 'z':
-		    (*info->fprintf_func) (stream, "%%icc");
-		    break;
+                  case 'z':
+                    (*info->fprintf_func) (stream, "%%icc");
+                    break;
 
-		  case 'Z':
-		    (*info->fprintf_func) (stream, "%%xcc");
-		    break;
+                  case 'Z':
+                    (*info->fprintf_func) (stream, "%%xcc");
+                    break;
 
-		  case 'E':
-		    (*info->fprintf_func) (stream, "%%ccr");
-		    break;
+                  case 'E':
+                    (*info->fprintf_func) (stream, "%%ccr");
+                    break;
 
-		  case 's':
-		    (*info->fprintf_func) (stream, "%%fprs");
-		    break;
+                  case 's':
+                    (*info->fprintf_func) (stream, "%%fprs");
+                    break;
 
-		  case 'o':
-		    (*info->fprintf_func) (stream, "%%asi");
-		    break;
+                  case 'o':
+                    (*info->fprintf_func) (stream, "%%asi");
+                    break;
 
-		  case 'W':
-		    (*info->fprintf_func) (stream, "%%tick");
-		    break;
+                  case 'W':
+                    (*info->fprintf_func) (stream, "%%tick");
+                    break;
 
-		  case 'P':
-		    (*info->fprintf_func) (stream, "%%pc");
-		    break;
+                  case 'P':
+                    (*info->fprintf_func) (stream, "%%pc");
+                    break;
 
-		  case '?':
-		    if (X_RS1 (insn) == 31)
-		      (*info->fprintf_func) (stream, "%%ver");
-		    else if ((unsigned) X_RS1 (insn) < 16)
-		      (*info->fprintf_func) (stream, "%%%s",
-					     v9_priv_reg_names[X_RS1 (insn)]);
-		    else
-		      (*info->fprintf_func) (stream, "%%reserved");
-		    break;
+                  case '?':
+                    if (X_RS1 (insn) == 31)
+                      (*info->fprintf_func) (stream, "%%ver");
+                    else if ((unsigned) X_RS1 (insn) < 16)
+                      (*info->fprintf_func) (stream, "%%%s",
+                                             v9_priv_reg_names[X_RS1 (insn)]);
+                    else
+                      (*info->fprintf_func) (stream, "%%reserved");
+                    break;
 
-		  case '!':
-		    if ((unsigned) X_RD (insn) < 15)
-		      (*info->fprintf_func) (stream, "%%%s",
-					     v9_priv_reg_names[X_RD (insn)]);
-		    else
-		      (*info->fprintf_func) (stream, "%%reserved");
-		    break;
+                  case '!':
+                    if ((unsigned) X_RD (insn) < 15)
+                      (*info->fprintf_func) (stream, "%%%s",
+                                             v9_priv_reg_names[X_RD (insn)]);
+                    else
+                      (*info->fprintf_func) (stream, "%%reserved");
+                    break;
 
-		  case '/':
-		    if (X_RS1 (insn) < 16 || X_RS1 (insn) > 25)
-		      (*info->fprintf_func) (stream, "%%reserved");
-		    else
-		      (*info->fprintf_func) (stream, "%%%s",
-					     v9a_asr_reg_names[X_RS1 (insn)-16]);
-		    break;
+                  case '/':
+                    if (X_RS1 (insn) < 16 || X_RS1 (insn) > 25)
+                      (*info->fprintf_func) (stream, "%%reserved");
+                    else
+                      (*info->fprintf_func) (stream, "%%%s",
+                                             v9a_asr_reg_names[X_RS1 (insn)-16]);
+                    break;
 
-		  case '_':
-		    if (X_RD (insn) < 16 || X_RD (insn) > 25)
-		      (*info->fprintf_func) (stream, "%%reserved");
-		    else
-		      (*info->fprintf_func) (stream, "%%%s",
-					     v9a_asr_reg_names[X_RD (insn)-16]);
-		    break;
+                  case '_':
+                    if (X_RD (insn) < 16 || X_RD (insn) > 25)
+                      (*info->fprintf_func) (stream, "%%reserved");
+                    else
+                      (*info->fprintf_func) (stream, "%%%s",
+                                             v9a_asr_reg_names[X_RD (insn)-16]);
+                    break;
 
-		  case '*':
-		    {
-		      const char *name = sparc_decode_prefetch (X_RD (insn));
+                  case '*':
+                    {
+                      const char *name = sparc_decode_prefetch (X_RD (insn));
 
-		      if (name)
-			(*info->fprintf_func) (stream, "%s", name);
-		      else
-			(*info->fprintf_func) (stream, "%d", X_RD (insn));
-		      break;
-		    }
+                      if (name)
+                        (*info->fprintf_func) (stream, "%s", name);
+                      else
+                        (*info->fprintf_func) (stream, "%d", X_RD (insn));
+                      break;
+                    }
 
-		  case 'M':
-		    (*info->fprintf_func) (stream, "%%asr%d", X_RS1 (insn));
-		    break;
+                  case 'M':
+                    (*info->fprintf_func) (stream, "%%asr%d", X_RS1 (insn));
+                    break;
 
-		  case 'm':
-		    (*info->fprintf_func) (stream, "%%asr%d", X_RD (insn));
-		    break;
+                  case 'm':
+                    (*info->fprintf_func) (stream, "%%asr%d", X_RD (insn));
+                    break;
 
-		  case 'L':
-		    info->target = memaddr + SEX (X_DISP30 (insn), 30) * 4;
-		    (*info->print_address_func) (info->target, info);
-		    break;
+                  case 'L':
+                    info->target = memaddr + SEX (X_DISP30 (insn), 30) * 4;
+                    (*info->print_address_func) (info->target, info);
+                    break;
 
-		  case 'n':
-		    (*info->fprintf_func)
-		      (stream, "%#x", SEX (X_DISP22 (insn), 22));
-		    break;
+                  case 'n':
+                    (*info->fprintf_func)
+                      (stream, "%#x", SEX (X_DISP22 (insn), 22));
+                    break;
 
-		  case 'l':
-		    info->target = memaddr + SEX (X_DISP22 (insn), 22) * 4;
-		    (*info->print_address_func) (info->target, info);
-		    break;
+                  case 'l':
+                    info->target = memaddr + SEX (X_DISP22 (insn), 22) * 4;
+                    (*info->print_address_func) (info->target, info);
+                    break;
 
-		  case 'A':
-		    {
-		      const char *name;
+                  case 'A':
+                    {
+                      const char *name;
 
-		      if ((info->mach == bfd_mach_sparc_v8plusa) ||
+                      if ((info->mach == bfd_mach_sparc_v8plusa) ||
                           ((info->mach >= bfd_mach_sparc_v9) &&
                            (info->mach <= bfd_mach_sparc_v9b)))
-			name = sparc_decode_asi_v9 (X_ASI (insn));
-		      else
-			name = sparc_decode_asi_v8 (X_ASI (insn));
+                        name = sparc_decode_asi_v9 (X_ASI (insn));
+                      else
+                        name = sparc_decode_asi_v8 (X_ASI (insn));
 
-		      if (name)
-			(*info->fprintf_func) (stream, "%s", name);
-		      else
-			(*info->fprintf_func) (stream, "(%d)", X_ASI (insn));
-		      break;
-		    }
+                      if (name)
+                        (*info->fprintf_func) (stream, "%s", name);
+                      else
+                        (*info->fprintf_func) (stream, "(%d)", X_ASI (insn));
+                      break;
+                    }
 
-		  case 'C':
-		    (*info->fprintf_func) (stream, "%%csr");
-		    break;
+                  case 'C':
+                    (*info->fprintf_func) (stream, "%%csr");
+                    break;
 
-		  case 'F':
-		    (*info->fprintf_func) (stream, "%%fsr");
-		    break;
+                  case 'F':
+                    (*info->fprintf_func) (stream, "%%fsr");
+                    break;
 
-		  case 'p':
-		    (*info->fprintf_func) (stream, "%%psr");
-		    break;
+                  case 'p':
+                    (*info->fprintf_func) (stream, "%%psr");
+                    break;
 
-		  case 'q':
-		    (*info->fprintf_func) (stream, "%%fq");
-		    break;
+                  case 'q':
+                    (*info->fprintf_func) (stream, "%%fq");
+                    break;
 
-		  case 'Q':
-		    (*info->fprintf_func) (stream, "%%cq");
-		    break;
+                  case 'Q':
+                    (*info->fprintf_func) (stream, "%%cq");
+                    break;
 
-		  case 't':
-		    (*info->fprintf_func) (stream, "%%tbr");
-		    break;
+                  case 't':
+                    (*info->fprintf_func) (stream, "%%tbr");
+                    break;
 
-		  case 'w':
-		    (*info->fprintf_func) (stream, "%%wim");
-		    break;
+                  case 'w':
+                    (*info->fprintf_func) (stream, "%%wim");
+                    break;
 
-		  case 'x':
-		    (*info->fprintf_func) (stream, "%d",
-					   ((X_LDST_I (insn) << 8)
-					    + X_ASI (insn)));
-		    break;
+                  case 'x':
+                    (*info->fprintf_func) (stream, "%d",
+                                           ((X_LDST_I (insn) << 8)
+                                            + X_ASI (insn)));
+                    break;
 
-		  case 'y':
-		    (*info->fprintf_func) (stream, "%%y");
-		    break;
+                  case 'y':
+                    (*info->fprintf_func) (stream, "%%y");
+                    break;
 
-		  case 'u':
-		  case 'U':
-		    {
-		      int val = *s == 'U' ? X_RS1 (insn) : X_RD (insn);
-		      const char *name = sparc_decode_sparclet_cpreg (val);
+                  case 'u':
+                  case 'U':
+                    {
+                      int val = *s == 'U' ? X_RS1 (insn) : X_RD (insn);
+                      const char *name = sparc_decode_sparclet_cpreg (val);
 
-		      if (name)
-			(*info->fprintf_func) (stream, "%s", name);
-		      else
-			(*info->fprintf_func) (stream, "%%cpreg(%d)", val);
-		      break;
-		    }
-		  }
-	      }
-	  }
+                      if (name)
+                        (*info->fprintf_func) (stream, "%s", name);
+                      else
+                        (*info->fprintf_func) (stream, "%%cpreg(%d)", val);
+                      break;
+                    }
+                  }
+              }
+          }
 
-	  /* If we are adding or or'ing something to rs1, then
-	     check to see whether the previous instruction was
-	     a sethi to the same register as in the sethi.
-	     If so, attempt to print the result of the add or
-	     or (in this context add and or do the same thing)
-	     and its symbolic value.  */
-	  if (imm_ored_to_rs1 || imm_added_to_rs1)
-	    {
-	      unsigned long prev_insn;
-	      int errcode;
+          /* If we are adding or or'ing something to rs1, then
+             check to see whether the previous instruction was
+             a sethi to the same register as in the sethi.
+             If so, attempt to print the result of the add or
+             or (in this context add and or do the same thing)
+             and its symbolic value.  */
+          if (imm_ored_to_rs1 || imm_added_to_rs1)
+            {
+              unsigned long prev_insn;
+              int errcode;
 
-	      errcode =
-		(*info->read_memory_func)
-		  (memaddr - 4, buffer, sizeof (buffer), info);
-	      prev_insn = getword (buffer);
+              errcode =
+                (*info->read_memory_func)
+                  (memaddr - 4, buffer, sizeof (buffer), info);
+              prev_insn = getword (buffer);
 
-	      if (errcode == 0)
-		{
-		  /* If it is a delayed branch, we need to look at the
-		     instruction before the delayed branch.  This handles
-		     sequences such as
+              if (errcode == 0)
+                {
+                  /* If it is a delayed branch, we need to look at the
+                     instruction before the delayed branch.  This handles
+                     sequences such as
 
-		     sethi %o1, %hi(_foo), %o1
-		     call _printf
-		     or %o1, %lo(_foo), %o1
-		     */
+                     sethi %o1, %hi(_foo), %o1
+                     call _printf
+                     or %o1, %lo(_foo), %o1
+                     */
 
-		  if (is_delayed_branch (prev_insn))
-		    {
-		      errcode = (*info->read_memory_func)
-			(memaddr - 8, buffer, sizeof (buffer), info);
-		      prev_insn = getword (buffer);
-		    }
-		}
+                  if (is_delayed_branch (prev_insn))
+                    {
+                      errcode = (*info->read_memory_func)
+                        (memaddr - 8, buffer, sizeof (buffer), info);
+                      prev_insn = getword (buffer);
+                    }
+                }
 
-	      /* If there was a problem reading memory, then assume
-		 the previous instruction was not sethi.  */
-	      if (errcode == 0)
-		{
-		  /* Is it sethi to the same register?  */
-		  if ((prev_insn & 0xc1c00000) == 0x01000000
-		      && X_RD (prev_insn) == X_RS1 (insn))
-		    {
-		      (*info->fprintf_func) (stream, "\t! ");
-		      info->target =
-			((unsigned) 0xFFFFFFFF
-			 & ((int) X_IMM22 (prev_insn) << 10));
-		      if (imm_added_to_rs1)
-			info->target += X_SIMM (insn, 13);
-		      else
-			info->target |= X_SIMM (insn, 13);
-		      (*info->print_address_func) (info->target, info);
-		      info->insn_type = dis_dref;
-		      info->data_size = 4;  /* FIXME!!! */
-		    }
-		}
-	    }
+              /* If there was a problem reading memory, then assume
+                 the previous instruction was not sethi.  */
+              if (errcode == 0)
+                {
+                  /* Is it sethi to the same register?  */
+                  if ((prev_insn & 0xc1c00000) == 0x01000000
+                      && X_RD (prev_insn) == X_RS1 (insn))
+                    {
+                      (*info->fprintf_func) (stream, "\t! ");
+                      info->target =
+                        ((unsigned) 0xFFFFFFFF
+                         & ((int) X_IMM22 (prev_insn) << 10));
+                      if (imm_added_to_rs1)
+                        info->target += X_SIMM (insn, 13);
+                      else
+                        info->target |= X_SIMM (insn, 13);
+                      (*info->print_address_func) (info->target, info);
+                      info->insn_type = dis_dref;
+                      info->data_size = 4;  /* FIXME!!! */
+                    }
+                }
+            }
 
-	  if (opcode->flags & (F_UNBR|F_CONDBR|F_JSR))
-	    {
-		/* FIXME -- check is_annulled flag */
-	      if (opcode->flags & F_UNBR)
-		info->insn_type = dis_branch;
-	      if (opcode->flags & F_CONDBR)
-		info->insn_type = dis_condbranch;
-	      if (opcode->flags & F_JSR)
-		info->insn_type = dis_jsr;
-	      if (opcode->flags & F_DELAYED)
-		info->branch_delay_insns = 1;
-	    }
+          if (opcode->flags & (F_UNBR|F_CONDBR|F_JSR))
+            {
+                /* FIXME -- check is_annulled flag */
+              if (opcode->flags & F_UNBR)
+                info->insn_type = dis_branch;
+              if (opcode->flags & F_CONDBR)
+                info->insn_type = dis_condbranch;
+              if (opcode->flags & F_JSR)
+                info->insn_type = dis_jsr;
+              if (opcode->flags & F_DELAYED)
+                info->branch_delay_insns = 1;
+            }
 
-	  return sizeof (buffer);
-	}
+          return sizeof (buffer);
+        }
     }
 
-  info->insn_type = dis_noninsn;	/* Mark as non-valid instruction */
+  info->insn_type = dis_noninsn;        /* Mark as non-valid instruction */
   (*info->fprintf_func) (stream, _("unknown"));
   return sizeof (buffer);
 }
@@ -3051,10 +3051,10 @@
     case bfd_mach_sparc_sparclite :
     case bfd_mach_sparc_sparclite_le :
       /* sparclites insns are recognized by default (because that's how
-	 they've always been treated, for better or worse).  Kludge this by
-	 indicating generic v8 is also selected.  */
+         they've always been treated, for better or worse).  Kludge this by
+         indicating generic v8 is also selected.  */
       return (SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLITE)
-	      | SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8));
+              | SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8));
     case bfd_mach_sparc_v8plus :
     case bfd_mach_sparc_v9 :
       return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9);
@@ -3087,14 +3087,14 @@
   if (op0->architecture & current_arch_mask)
     {
       if (! (op1->architecture & current_arch_mask))
-	return -1;
+        return -1;
     }
   else
     {
       if (op1->architecture & current_arch_mask)
-	return 1;
+        return 1;
       else if (op0->architecture != op1->architecture)
-	return op0->architecture - op1->architecture;
+        return op0->architecture - op1->architecture;
     }
 
   /* If a bit is set in both match and lose, there is something
@@ -3102,10 +3102,10 @@
   if (match0 & lose0)
     {
       fprintf
-	(stderr,
-	 /* xgettext:c-format */
-	 _("Internal error:  bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
-	 op0->name, match0, lose0);
+        (stderr,
+         /* xgettext:c-format */
+         _("Internal error:  bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
+         op0->name, match0, lose0);
       op0->lose &= ~op0->match;
       lose0 = op0->lose;
     }
@@ -3113,10 +3113,10 @@
   if (match1 & lose1)
     {
       fprintf
-	(stderr,
-	 /* xgettext:c-format */
-	 _("Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
-	 op1->name, match1, lose1);
+        (stderr,
+         /* xgettext:c-format */
+         _("Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
+         op1->name, match1, lose1);
       op1->lose &= ~op1->match;
       lose1 = op1->lose;
     }
@@ -3130,7 +3130,7 @@
       int x1 = (match1 & x) != 0;
 
       if (x0 != x1)
-	return x1 - x0;
+        return x1 - x0;
     }
 
   for (i = 0; i < 32; ++i)
@@ -3140,7 +3140,7 @@
       int x1 = (lose1 & x) != 0;
 
       if (x0 != x1)
-	return x1 - x0;
+        return x1 - x0;
     }
 
   /* They are functionally equal.  So as long as the opcode table is
@@ -3160,12 +3160,12 @@
   if (i)
     {
       if (op0->flags & F_ALIAS) /* If they're both aliases, be arbitrary. */
-	return i;
+        return i;
       else
-	fprintf (stderr,
-		 /* xgettext:c-format */
-		 _("Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n"),
-		 op0->name, op1->name);
+        fprintf (stderr,
+                 /* xgettext:c-format */
+                 _("Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n"),
+                 op0->name, op1->name);
     }
 
   /* Fewer arguments are preferred.  */
@@ -3183,15 +3183,15 @@
 
     if (p0 && p1)
       {
-	/* There is a plus in both operands.  Note that a plus
-	   sign cannot be the first character in args,
-	   so the following [-1]'s are valid.  */
-	if (p0[-1] == 'i' && p1[1] == 'i')
-	  /* op0 is i+1 and op1 is 1+i, so op1 goes first.  */
-	  return 1;
-	if (p0[1] == 'i' && p1[-1] == 'i')
-	  /* op0 is 1+i and op1 is i+1, so op0 goes first.  */
-	  return -1;
+        /* There is a plus in both operands.  Note that a plus
+           sign cannot be the first character in args,
+           so the following [-1]'s are valid.  */
+        if (p0[-1] == 'i' && p1[1] == 'i')
+          /* op0 is i+1 and op1 is 1+i, so op1 goes first.  */
+          return 1;
+        if (p0[1] == 'i' && p1[-1] == 'i')
+          /* op0 is 1+i and op1 is i+1, so op0 goes first.  */
+          return -1;
       }
   }
 
@@ -3252,14 +3252,14 @@
     for (i = 0; i < HASH_SIZE; ++i)
       {
         if (hash_count[i] < min_count)
-	  min_count = hash_count[i];
-	if (hash_count[i] > max_count)
-	  max_count = hash_count[i];
-	total += hash_count[i];
+          min_count = hash_count[i];
+        if (hash_count[i] > max_count)
+          max_count = hash_count[i];
+        total += hash_count[i];
       }
 
     printf ("Opcode hash table stats: min %d, max %d, ave %f\n",
-	    min_count, max_count, (double) total / HASH_SIZE);
+            min_count, max_count, (double) total / HASH_SIZE);
   }
 #endif
 }

Modified: trunk/src/host/qemu-neo1973/sparc.ld
===================================================================
--- trunk/src/host/qemu-neo1973/sparc.ld	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/sparc.ld	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,5 +1,5 @@
 OUTPUT_FORMAT("elf32-sparc", "elf32-sparc",
-	      "elf32-sparc")
+              "elf32-sparc")
 OUTPUT_ARCH(sparc)
 SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/alpha-unknown-linux-gnu/lib);
 ENTRY(_start)
@@ -7,13 +7,13 @@
 {
   /* Read-only sections, merged into text segment: */
   . = 0x60000000 + SIZEOF_HEADERS;
-  .interp     : { *(.interp) 	}
-  .hash          : { *(.hash)		}
-  .dynsym        : { *(.dynsym)		}
-  .dynstr        : { *(.dynstr)		}
-  .gnu.version   : { *(.gnu.version)	}
-  .gnu.version_d   : { *(.gnu.version_d)	}
-  .gnu.version_r   : { *(.gnu.version_r)	}
+  .interp     : { *(.interp)    }
+  .hash          : { *(.hash)           }
+  .dynsym        : { *(.dynsym)         }
+  .dynstr        : { *(.dynstr)         }
+  .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     :
@@ -26,21 +26,21 @@
     { *(.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
+  .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      :
   {
     *(.text)
@@ -74,7 +74,7 @@
   {
     *(.dtors)
   }
-  .plt      : { *(.plt)	}
+  .plt      : { *(.plt) }
   .got           : { *(.got.plt) *(.got) }
   .dynamic       : { *(.dynamic) }
   /* We want the small data sections together, so single-instruction offsets

Modified: trunk/src/host/qemu-neo1973/sparc64.ld
===================================================================
--- trunk/src/host/qemu-neo1973/sparc64.ld	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/sparc64.ld	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,5 +1,5 @@
 OUTPUT_FORMAT("elf64-sparc", "elf64-sparc",
-	      "elf64-sparc")
+              "elf64-sparc")
 OUTPUT_ARCH(sparc:v9)
 SEARCH_DIR(/lib64); SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib64); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib64); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/alpha-unknown-linux-gnu/lib);
 ENTRY(_start)
@@ -7,13 +7,13 @@
 {
   /* Read-only sections, merged into text segment: */
   . = 0x60000000 + SIZEOF_HEADERS;
-  .interp     : { *(.interp) 	}
-  .hash          : { *(.hash)		}
-  .dynsym        : { *(.dynsym)		}
-  .dynstr        : { *(.dynstr)		}
-  .gnu.version   : { *(.gnu.version)	}
-  .gnu.version_d   : { *(.gnu.version_d)	}
-  .gnu.version_r   : { *(.gnu.version_r)	}
+  .interp     : { *(.interp)    }
+  .hash          : { *(.hash)           }
+  .dynsym        : { *(.dynsym)         }
+  .dynstr        : { *(.dynstr)         }
+  .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     :
@@ -26,21 +26,21 @@
     { *(.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
+  .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      :
   {
     *(.text)
@@ -82,7 +82,7 @@
   {
     *(.dtors)
   }
-  .plt      : { *(.plt)	}
+  .plt      : { *(.plt) }
   .got           : { *(.got.plt) *(.got) }
   .dynamic       : { *(.dynamic) }
   /* We want the small data sections together, so single-instruction offsets

Added: trunk/src/host/qemu-neo1973/target-alpha/STATUS
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/STATUS	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-alpha/STATUS	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,33 @@
+(to be completed)
+
+Alpha emulation structure:
+cpu.h           : CPU definitions globally exported
+exec.h          : CPU definitions used only for translated code execution
+helper.c        : helpers that can be called either by the translated code
+                  or the Qemu core, including the exception handler.
+op.c            : Alpha dedicated micro-operations used by the code translator
+op_helper.c     : helpers that can be called only from micro-operations
+op_helper.h     : micro-operations helpers prototypes
+op_helper_mem.h : micro-operations templates
+                  for load and stores accesses helpers
+op_mem.h        : micro-operations templates for load and stores accesses
+op_template.h   : micro-operation templates for register moves
+translate.c     : Alpha instructions to micro-operations translator
+
+Code translator status:
+The Alpha CPU instruction emulation should be quite complete with the
+limitation that the VAX floating-point load and stores are not implemented.
+The 4 MMU modes are implemented.
+
+Linux user mode emulation status:
+a few programs start to run. Most crash at a certain point, dereferencing a
+NULL pointer. It seems that the UNIQUE register is not initialized properly.
+It may appear that old executables, not relying on TLS support, run but
+this is to be prooved...
+
+Full system emulation status:
+* Alpha PALCode emulation is in a very early stage and is not sufficient
+  to run any real OS. The alpha-softmmu target is not enabled for now.
+* no hardware platform description is implemented
+* there might be problems in the Alpha PALCode dedicated instructions
+  that would prevent to use a native PALCode image.

Modified: trunk/src/host/qemu-neo1973/target-alpha/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/cpu.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-alpha/cpu.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -27,14 +27,13 @@
 
 #include "cpu-defs.h"
 
-
 #include <setjmp.h>
 
 #include "softfloat.h"
 
 #define TARGET_HAS_ICE 1
 
-#define ELF_MACHINE	EM_ALPHA
+#define ELF_MACHINE     EM_ALPHA
 
 #define ICACHE_LINE_SIZE 32
 #define DCACHE_LINE_SIZE 32
@@ -256,6 +255,8 @@
     void (*call_pal)(CPUAlphaState *env, uint32_t palcode);
 };
 
+#define NB_MMU_MODES 4
+
 struct CPUAlphaState {
     uint64_t ir[31];
     float64  fir[31];
@@ -302,6 +303,17 @@
 #define cpu_gen_code cpu_alpha_gen_code
 #define cpu_signal_handler cpu_alpha_signal_handler
 
+/* MMU modes definitions */
+#define MMU_MODE0_SUFFIX _kernel
+#define MMU_MODE1_SUFFIX _executive
+#define MMU_MODE2_SUFFIX _supervisor
+#define MMU_MODE3_SUFFIX _user
+#define MMU_USER_IDX 3
+static inline int cpu_mmu_index (CPUState *env)
+{
+    return (env->ps >> 3) & 3;
+}
+
 #include "cpu-all.h"
 
 enum {

Modified: trunk/src/host/qemu-neo1973/target-alpha/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/exec.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-alpha/exec.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -64,22 +64,22 @@
 #include "softmmu_exec.h"
 #endif /* !defined(CONFIG_USER_ONLY) */
 
-static inline void env_to_regs(void)
+static always_inline void env_to_regs(void)
 {
 }
 
-static inline void regs_to_env(void)
+static always_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 mmu_idx, 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);
 
-static inline int cpu_halted(CPUState *env) {
+static always_inline int cpu_halted(CPUState *env) {
     if (!env->halted)
         return 0;
     if (env->interrupt_request & CPU_INTERRUPT_HARD) {

Modified: trunk/src/host/qemu-neo1973/target-alpha/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-alpha/helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -28,7 +28,7 @@
 #if defined(CONFIG_USER_ONLY)
 
 int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                                int is_user, int is_softmmu)
+                                int mmu_idx, int is_softmmu)
 {
     if (rw == 2)
         env->exception_index = EXCP_ITB_MISS;
@@ -57,7 +57,7 @@
 }
 
 int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                                int is_user, int is_softmmu)
+                                int mmu_idx, int is_softmmu)
 {
     uint32_t opc;
 

Modified: trunk/src/host/qemu-neo1973/target-alpha/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/op.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-alpha/op.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -140,11 +140,15 @@
 #define MEMSUFFIX _raw
 #include "op_mem.h"
 #if !defined(CONFIG_USER_ONLY)
+#define MEMSUFFIX _kernel
+#include "op_mem.h"
+#define MEMSUFFIX _executive
+#include "op_mem.h"
+#define MEMSUFFIX _supervisor
+#include "op_mem.h"
 #define MEMSUFFIX _user
 #include "op_mem.h"
-#define MEMSUFFIX _kernel
-#include "op_mem.h"
-/* Those are used for supervisor, executive and pal modes */
+/* This is used for pal modes */
 #define MEMSUFFIX _data
 #include "op_mem.h"
 #endif
@@ -291,7 +295,7 @@
 
 void OPPROTO op_mulq (void)
 {
-    T0 *= T1;
+    T0 = (int64_t)T0 * (int64_t)T1;
     RETURN();
 }
 
@@ -303,7 +307,10 @@
 
 void OPPROTO op_umulh (void)
 {
-    helper_umulh();
+    uint64_t tl, th;
+
+    mulu64(&tl, &th, T0, T1);
+    T0 = th;
     RETURN();
 }
 

Modified: trunk/src/host/qemu-neo1973/target-alpha/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/op_helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-alpha/op_helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -19,6 +19,7 @@
  */
 
 #include "exec.h"
+#include "host-utils.h"
 #include "softfloat.h"
 
 #include "op_helper.h"
@@ -27,13 +28,19 @@
 #include "op_helper_mem.h"
 
 #if !defined(CONFIG_USER_ONLY)
-#define MEMSUFFIX _user
+#define MEMSUFFIX _kernel
 #include "op_helper_mem.h"
 
-#define MEMSUFFIX _kernel
+#define MEMSUFFIX _executive
 #include "op_helper_mem.h"
 
-/* Those are used for supervisor and executive modes */
+#define MEMSUFFIX _supervisor
+#include "op_helper_mem.h"
+
+#define MEMSUFFIX _user
+#include "op_helper_mem.h"
+
+/* This is used for pal modes */
 #define MEMSUFFIX _data
 #include "op_helper_mem.h"
 #endif
@@ -193,118 +200,32 @@
 
 void helper_mulqv ()
 {
-    uint64_t res, tmp0, tmp1;
+    uint64_t tl, th;
 
-    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)) {
+    muls64(&tl, &th, T0, T1);
+    /* If th != 0 && th != -1, then we had an overflow */
+    if (unlikely((th + 1) > 1)) {
         helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
     }
+    T0 = tl;
 }
 
-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;
+    T0 = ctpop64(T0);
 }
 
 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;
+    T0 = clz64(T0);
 }
 
 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;
+    T0 = ctz64(T0);
 }
 
-static inline uint64_t byte_zap (uint64_t op, uint8_t mskb)
+static always_inline uint64_t byte_zap (uint64_t op, uint8_t mskb)
 {
     uint64_t mask;
 
@@ -619,7 +540,7 @@
     FT0 = p.d;
 }
 
-static int vaxf_is_valid (float ff)
+static always_inline int vaxf_is_valid (float ff)
 {
     union {
         float f;
@@ -638,7 +559,7 @@
     return 1;
 }
 
-static float vaxf_to_ieee32 (float ff)
+static always_inline float vaxf_to_ieee32 (float ff)
 {
     union {
         float f;
@@ -658,7 +579,7 @@
     return p.f;
 }
 
-static float ieee32_to_vaxf (float fi)
+static always_inline float ieee32_to_vaxf (float fi)
 {
     union {
         float f;
@@ -761,7 +682,7 @@
     /* XXX: TODO */
 }
 
-static int vaxg_is_valid (double ff)
+static always_inline int vaxg_is_valid (double ff)
 {
     union {
         double f;
@@ -780,7 +701,7 @@
     return 1;
 }
 
-static double vaxg_to_ieee64 (double fg)
+static always_inline double vaxg_to_ieee64 (double fg)
 {
     union {
         double f;
@@ -800,7 +721,7 @@
     return p.f;
 }
 
-static double ieee64_to_vaxg (double fi)
+static always_inline double ieee64_to_vaxg (double fi)
 {
     union {
         double f;
@@ -1054,7 +975,7 @@
     FT0 = q.d;
 }
 
-static inline void __helper_cvtql (int s, int v)
+static always_inline void __helper_cvtql (int s, int v)
 {
     union {
         double d;
@@ -1155,7 +1076,11 @@
 /* Softmmu support */
 #if !defined (CONFIG_USER_ONLY)
 
-#define GETPC() (__builtin_return_address(0))
+#ifdef __s390__
+# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
+#else
+# define GETPC() (__builtin_return_address(0))
+#endif
 
 /* XXX: the two following helpers are pure hacks.
  *      Hopefully, we emulate the PALcode, then we should never see
@@ -1164,20 +1089,20 @@
 void helper_ld_phys_to_virt (void)
 {
     uint64_t tlb_addr, physaddr;
-    int index, is_user;
+    int index, mmu_idx;
     void *retaddr;
 
-    is_user = (env->ps >> 3) & 3;
+    mmu_idx = cpu_mmu_index(env);
     index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  redo:
-    tlb_addr = env->tlb_table[is_user][index].addr_read;
+    tlb_addr = env->tlb_table[mmu_idx][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;
+        physaddr = T0 + env->tlb_table[mmu_idx][index].addend;
     } else {
         /* the page is not in the TLB : fill it */
         retaddr = GETPC();
-        tlb_fill(T0, 0, is_user, retaddr);
+        tlb_fill(T0, 0, mmu_idx, retaddr);
         goto redo;
     }
     T0 = physaddr;
@@ -1186,20 +1111,20 @@
 void helper_st_phys_to_virt (void)
 {
     uint64_t tlb_addr, physaddr;
-    int index, is_user;
+    int index, mmu_idx;
     void *retaddr;
 
-    is_user = (env->ps >> 3) & 3;
+    mmu_idx = cpu_mmu_index(env);
     index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  redo:
-    tlb_addr = env->tlb_table[is_user][index].addr_write;
+    tlb_addr = env->tlb_table[mmu_idx][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;
+        physaddr = T0 + env->tlb_table[mmu_idx][index].addend;
     } else {
         /* the page is not in the TLB : fill it */
         retaddr = GETPC();
-        tlb_fill(T0, 1, is_user, retaddr);
+        tlb_fill(T0, 1, mmu_idx, retaddr);
         goto redo;
     }
     T0 = physaddr;
@@ -1223,7 +1148,7 @@
    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)
+void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 {
     TranslationBlock *tb;
     CPUState *saved_env;
@@ -1234,7 +1159,7 @@
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, is_user, 1);
+    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
     if (!likely(ret == 0)) {
         if (likely(retaddr)) {
             /* now we have a real cpu fault */

Modified: trunk/src/host/qemu-neo1973/target-alpha/op_helper.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/op_helper.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-alpha/op_helper.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -34,7 +34,6 @@
 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);

Modified: trunk/src/host/qemu-neo1973/target-alpha/op_mem.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/op_mem.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-alpha/op_mem.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -26,21 +26,22 @@
 #define print_mem_EA(EA) do { } while (0)
 #endif
 
-static inline uint32_t glue(ldl_l, MEMSUFFIX) (target_ulong EA)
+static always_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)
+static always_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)
+static always_inline void glue(stl_c, MEMSUFFIX) (target_ulong EA,
+                                                  uint32_t data)
 {
     if (EA == env->lock) {
         glue(stl, MEMSUFFIX)(EA, data);
@@ -51,7 +52,8 @@
     env->lock = -1;
 }
 
-static inline void glue(stq_c, MEMSUFFIX) (target_ulong EA, uint64_t data)
+static always_inline void glue(stq_c, MEMSUFFIX) (target_ulong EA,
+                                                  uint64_t data)
 {
     if (EA == env->lock) {
         glue(stq, MEMSUFFIX)(EA, data);

Modified: trunk/src/host/qemu-neo1973/target-alpha/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/translate.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-alpha/translate.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -59,7 +59,7 @@
 
 #include "gen-op.h"
 
-static inline void gen_op_nop (void)
+static always_inline void gen_op_nop (void)
 {
 #if defined(GENERATE_NOP)
     gen_op_no_op();
@@ -77,7 +77,7 @@
 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
 };                                                                            \
-static inline void func(int n)                                                \
+static always_inline void func (int n)                                        \
 {                                                                             \
     NAME ## _table[n]();                                                      \
 }
@@ -99,7 +99,7 @@
 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)
+static always_inline void gen_load_ir (DisasContext *ctx, int irn, int Tn)
 {
     switch (Tn) {
     case 0:
@@ -114,7 +114,7 @@
     }
 }
 
-static inline void gen_store_ir (DisasContext *ctx, int irn, int Tn)
+static always_inline void gen_store_ir (DisasContext *ctx, int irn, int Tn)
 {
     switch (Tn) {
     case 0:
@@ -146,7 +146,7 @@
 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)
+static always_inline void gen_load_fir (DisasContext *ctx, int firn, int Tn)
 {
     switch (Tn) {
     case 0:
@@ -161,7 +161,7 @@
     }
 }
 
-static inline void gen_store_fir (DisasContext *ctx, int firn, int Tn)
+static always_inline void gen_store_fir (DisasContext *ctx, int firn, int Tn)
 {
     switch (Tn) {
     case 0:
@@ -190,29 +190,29 @@
 #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 */                                      \
+    &gen_op_ld##width##_executive,                                            \
+    &gen_op_ld##width##_supervisor,                                           \
+    &gen_op_ld##width##_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 */                                      \
+    &gen_op_st##width##_executive,                                            \
+    &gen_op_st##width##_supervisor,                                           \
+    &gen_op_st##width##_user,                                                 \
 }
 #endif
 
 #define GEN_LD(width)                                                         \
 OP_LD_TABLE(width);                                                           \
-static void gen_ld##width (DisasContext *ctx)                                 \
+static always_inline 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)                                 \
+static always_inline void gen_st##width (DisasContext *ctx)                   \
 {                                                                             \
     (*gen_op_st##width[ctx->mem_idx])();                                      \
 }
@@ -244,28 +244,28 @@
 GEN_ST(t);
 
 #if defined(__i386__) || defined(__x86_64__)
-static inline void gen_op_set_s16_T0 (int16_t imm)
+static always_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)
+static always_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)
+static always_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)
+static always_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)
+static always_inline void gen_set_sT0 (DisasContext *ctx, int64_t imm)
 {
     int32_t imm32;
     int16_t imm16;
@@ -291,7 +291,7 @@
     }
 }
 
-static inline void gen_set_sT1 (DisasContext *ctx, int64_t imm)
+static always_inline void gen_set_sT1 (DisasContext *ctx, int64_t imm)
 {
     int32_t imm32;
     int16_t imm16;
@@ -317,7 +317,7 @@
     }
 }
 
-static inline void gen_set_uT0 (DisasContext *ctx, uint64_t imm)
+static always_inline void gen_set_uT0 (DisasContext *ctx, uint64_t imm)
 {
     if (!(imm >> 32)) {
         if ((!imm >> 16)) {
@@ -337,7 +337,7 @@
     }
 }
 
-static inline void gen_set_uT1 (DisasContext *ctx, uint64_t imm)
+static always_inline void gen_set_uT1 (DisasContext *ctx, uint64_t imm)
 {
     if (!(imm >> 32)) {
         if ((!imm >> 16)) {
@@ -357,7 +357,7 @@
     }
 }
 
-static inline void gen_update_pc (DisasContext *ctx)
+static always_inline void gen_update_pc (DisasContext *ctx)
 {
     if (!(ctx->pc >> 32)) {
         gen_op_update_pc32(ctx->pc);
@@ -370,7 +370,7 @@
     }
 }
 
-static inline void _gen_op_bcond (DisasContext *ctx)
+static always_inline void _gen_op_bcond (DisasContext *ctx)
 {
 #if 0 // Qemu does not know how to do this...
     gen_op_bcond(ctx->pc);
@@ -379,20 +379,22 @@
 #endif
 }
 
-static inline void gen_excp (DisasContext *ctx, int exception, int error_code)
+static always_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)
+static always_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)
+static always_inline 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 */
@@ -410,9 +412,10 @@
     }
 }
 
-static void gen_store_mem (DisasContext *ctx,
-                           void (*gen_store_op)(DisasContext *ctx),
-                           int ra, int rb, int32_t disp16, int clear)
+static always_inline 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) {
@@ -425,9 +428,9 @@
     (*gen_store_op)(ctx);
 }
 
-static void gen_load_fmem (DisasContext *ctx,
-                           void (*gen_load_fop)(DisasContext *ctx),
-                          int ra, int rb, int32_t disp16)
+static always_inline 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) {
@@ -438,9 +441,9 @@
     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)
+static always_inline 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) {
@@ -451,8 +454,9 @@
     (*gen_store_fop)(ctx);
 }
 
-static void gen_bcond (DisasContext *ctx, void (*gen_test_op)(void),
-                       int ra, int32_t disp16)
+static always_inline void gen_bcond (DisasContext *ctx,
+                                     void (*gen_test_op)(void),
+                                     int ra, int32_t disp16)
 {
     if (disp16 != 0) {
         gen_set_uT0(ctx, ctx->pc);
@@ -466,8 +470,9 @@
     _gen_op_bcond(ctx);
 }
 
-static void gen_fbcond (DisasContext *ctx, void (*gen_test_op)(void),
-                        int ra, int32_t disp16)
+static always_inline void gen_fbcond (DisasContext *ctx,
+                                      void (*gen_test_op)(void),
+                                      int ra, int32_t disp16)
 {
     if (disp16 != 0) {
         gen_set_uT0(ctx, ctx->pc);
@@ -481,8 +486,9 @@
     _gen_op_bcond(ctx);
 }
 
-static void gen_arith2 (DisasContext *ctx, void (*gen_arith_op)(void),
-                        int rb, int rc, int islit, int8_t lit)
+static always_inline 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);
@@ -492,8 +498,10 @@
     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)
+static always_inline 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)
@@ -504,8 +512,10 @@
     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)
+static always_inline 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)
@@ -516,16 +526,18 @@
     gen_op_cmov_ir(rc);
 }
 
-static void gen_farith2 (DisasContext *ctx, void (*gen_arith_fop)(void),
-                         int rb, int rc)
+static always_inline 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)
+static always_inline 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);
@@ -533,8 +545,9 @@
     gen_store_fir(ctx, rc, 0);
 }
 
-static void gen_fcmov (DisasContext *ctx, void (*gen_test_fop)(void),
-                       int ra, int rb, int rc)
+static always_inline 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);
@@ -542,77 +555,79 @@
     gen_op_cmov_fir(rc);
 }
 
-static void gen_fti (DisasContext *ctx, void (*gen_move_fop)(void),
-                     int ra, int rc)
+static always_inline 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)
+static always_inline 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)
+static always_inline void gen_s4addl (void)
 {
     gen_op_s4();
     gen_op_addl();
 }
 
-static void gen_s4subl (void)
+static always_inline void gen_s4subl (void)
 {
     gen_op_s4();
     gen_op_subl();
 }
 
-static void gen_s8addl (void)
+static always_inline void gen_s8addl (void)
 {
     gen_op_s8();
     gen_op_addl();
 }
 
-static void gen_s8subl (void)
+static always_inline void gen_s8subl (void)
 {
     gen_op_s8();
     gen_op_subl();
 }
 
-static void gen_s4addq (void)
+static always_inline void gen_s4addq (void)
 {
     gen_op_s4();
     gen_op_addq();
 }
 
-static void gen_s4subq (void)
+static always_inline void gen_s4subq (void)
 {
     gen_op_s4();
     gen_op_subq();
 }
 
-static void gen_s8addq (void)
+static always_inline void gen_s8addq (void)
 {
     gen_op_s8();
     gen_op_addq();
 }
 
-static void gen_s8subq (void)
+static always_inline void gen_s8subq (void)
 {
     gen_op_s8();
     gen_op_subq();
 }
 
-static void gen_amask (void)
+static always_inline void gen_amask (void)
 {
     gen_op_load_amask();
     gen_op_bic();
 }
 
-static int translate_one (DisasContext *ctx, uint32_t insn)
+static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
 {
     uint32_t palcode;
     int32_t disp21, disp16, disp12;
@@ -1958,8 +1973,9 @@
     return ret;
 }
 
-int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
-                                    int search_pc)
+static always_inline int gen_intermediate_code_internal (CPUState *env,
+                                                         TranslationBlock *tb,
+                                                         int search_pc)
 {
 #if defined ALPHA_DEBUG_DISAS
     static int insn_count;

Modified: trunk/src/host/qemu-neo1973/target-arm/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-arm/cpu.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-arm/cpu.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -43,6 +43,8 @@
 typedef uint32_t ARMReadCPFunc(void *opaque, int cp_info,
                                int dstreg, int operand);
 
+#define NB_MMU_MODES 2
+
 /* We currently assume float and double are IEEE single and double
    precision respectively.
    Doing runtime conversions is tricky because VFP registers may contain
@@ -261,7 +263,7 @@
     return (env->features & (1u << feature)) != 0;
 }
 
-void arm_cpu_list(void);
+void arm_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
 void cpu_arm_set_model(CPUARMState *env, const char *name);
 
 void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
@@ -301,7 +303,17 @@
 #define cpu_exec cpu_arm_exec
 #define cpu_gen_code cpu_arm_gen_code
 #define cpu_signal_handler cpu_arm_signal_handler
+#define cpu_list arm_cpu_list
 
+/* MMU modes definitions */
+#define MMU_MODE0_SUFFIX _kernel
+#define MMU_MODE1_SUFFIX _user
+#define MMU_USER_IDX 1
+static inline int cpu_mmu_index (CPUState *env)
+{
+    return (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR ? 1 : 0;
+}
+
 #include "cpu-all.h"
 
 #endif

Modified: trunk/src/host/qemu-neo1973/target-arm/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-arm/exec.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-arm/exec.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -46,7 +46,7 @@
 }
 
 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                              int is_user, int is_softmmu);
+                              int mmu_idx, int is_softmmu);
 
 static inline int cpu_halted(CPUState *env) {
     if (!env->halted)

Modified: trunk/src/host/qemu-neo1973/target-arm/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-arm/helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-arm/helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -132,13 +132,13 @@
     { 0, NULL}
 };
 
-void arm_cpu_list(void)
+void arm_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
 {
     int i;
 
-    printf ("Available CPUs:\n");
+    (*cpu_fprintf)(f, "Available CPUs:\n");
     for (i = 0; arm_cpu_names[i].name; i++) {
-        printf("  %s\n", arm_cpu_names[i].name);
+        (*cpu_fprintf)(f, "  %s\n", arm_cpu_names[i].name);
     }
 }
 
@@ -175,7 +175,7 @@
 }
 
 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                              int is_user, int is_softmmu)
+                              int mmu_idx, int is_softmmu)
 {
     if (rw == 2) {
         env->exception_index = EXCP_PREFETCH_ABORT;
@@ -553,18 +553,19 @@
 }
 
 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
-                              int access_type, int is_user, int is_softmmu)
+                              int access_type, int mmu_idx, int is_softmmu)
 {
     uint32_t phys_addr;
     int prot;
-    int ret;
+    int ret, is_user;
 
+    is_user = mmu_idx == MMU_USER_IDX;
     ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot);
     if (ret == 0) {
         /* Map a single [sub]page.  */
         phys_addr &= ~(uint32_t)0x3ff;
         address &= ~(uint32_t)0x3ff;
-        return tlb_set_page (env, address, phys_addr, prot, is_user,
+        return tlb_set_page (env, address, phys_addr, prot, mmu_idx,
                              is_softmmu);
     }
 

Modified: trunk/src/host/qemu-neo1973/target-arm/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-arm/op_helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-arm/op_helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -178,7 +178,11 @@
 #if !defined(CONFIG_USER_ONLY)
 
 #define MMUSUFFIX _mmu
-#define GETPC() (__builtin_return_address(0))
+#ifdef __s390__
+# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
+#else
+# define GETPC() (__builtin_return_address(0))
+#endif
 
 #define SHIFT 0
 #include "softmmu_template.h"
@@ -196,7 +200,7 @@
    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)
+void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 {
     TranslationBlock *tb;
     CPUState *saved_env;
@@ -207,7 +211,7 @@
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_arm_handle_mmu_fault(env, addr, is_write, is_user, 1);
+    ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
     if (__builtin_expect(ret, 0)) {
         if (retaddr) {
             /* now we have a real cpu fault */

Added: trunk/src/host/qemu-neo1973/target-cris/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-cris/cpu.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-cris/cpu.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,268 @@
+/*
+ *  CRIS virtual CPU header
+ *
+ *  Copyright (c) 2007 AXIS Communications AB
+ *  Written by Edgar E. Iglesias
+ *
+ * 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
+ * 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
+ */
+#ifndef CPU_CRIS_H
+#define CPU_CRIS_H
+
+#define TARGET_LONG_BITS 32
+
+#include "cpu-defs.h"
+
+#include "softfloat.h"
+
+#define TARGET_HAS_ICE 1
+
+#define ELF_MACHINE	EM_CRIS
+
+#define EXCP_MMU_EXEC    0
+#define EXCP_MMU_READ    1
+#define EXCP_MMU_WRITE   2
+#define EXCP_MMU_FLUSH   3
+#define EXCP_MMU_MISS    4
+#define EXCP_BREAK      16 /* trap.  */
+
+/* CPU flags.  */
+#define S_FLAG 0x200
+#define R_FLAG 0x100
+#define P_FLAG 0x80
+#define U_FLAG 0x40
+#define P_FLAG 0x80
+#define U_FLAG 0x40
+#define I_FLAG 0x20
+#define X_FLAG 0x10
+#define N_FLAG 0x08
+#define Z_FLAG 0x04
+#define V_FLAG 0x02
+#define C_FLAG 0x01
+#define ALU_FLAGS 0x1F
+
+/* Condition codes.  */
+#define CC_CC   0
+#define CC_CS   1
+#define CC_NE   2
+#define CC_EQ   3
+#define CC_VC   4
+#define CC_VS   5
+#define CC_PL   6
+#define CC_MI   7
+#define CC_LS   8
+#define CC_HI   9
+#define CC_GE  10
+#define CC_LT  11
+#define CC_GT  12
+#define CC_LE  13
+#define CC_A   14
+#define CC_P   15
+
+/* Internal flags for the implementation.  */
+#define F_DELAYSLOT 1
+
+#define NB_MMU_MODES 2
+
+typedef struct CPUCRISState {
+	uint32_t debug1;
+	uint32_t debug2;
+	uint32_t debug3;
+
+	/*
+	 * We just store the stores to the tlbset here for later evaluation
+	 * when the hw needs access to them.
+	 *
+	 * One for I and another for D.
+	 */
+	struct
+	{
+		uint32_t hi;
+		uint32_t lo;
+	} tlbsets[2][4][16];
+
+	uint32_t sregs[256][16]; /* grrr why so many??  */
+	uint32_t regs[16];
+	uint32_t pregs[16];
+	uint32_t pc;
+	uint32_t sr;
+	uint32_t flag_mask; /* Per insn mask of affected flags.  */
+
+	/* SSP and USP.  */
+	int current_sp;
+	uint32_t sp[2];
+
+	/* These are setup up by the guest code just before transfering the
+	   control back to the host.  */
+	int jmp;
+	uint32_t btarget;
+	int btaken;
+
+	/* for traps.  */
+	int trapnr;
+
+	/* Condition flag tracking.  */
+	uint32_t cc_op;
+	uint32_t cc_mask;
+	uint32_t cc_dest;
+	uint32_t cc_src;
+	uint32_t cc_result;
+
+	/* size of the operation, 1 = byte, 2 = word, 4 = dword.  */
+	int cc_size;
+
+	/* extended arithmetics.  */
+	int cc_x_live;
+	int cc_x;
+
+	int features;
+
+        uint64_t pending_interrupts;
+	int interrupt_request;
+	int exception_index;
+	int user_mode_only;
+	int halted;
+
+	struct
+	{
+		int exec_insns;
+		int exec_loads;
+		int exec_stores;
+	} stats;
+
+
+	jmp_buf jmp_env;
+	CPU_COMMON
+} CPUCRISState;
+
+CPUCRISState *cpu_cris_init(void);
+int cpu_cris_exec(CPUCRISState *s);
+void cpu_cris_close(CPUCRISState *s);
+void do_interrupt(CPUCRISState *env);
+/* 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_cris_signal_handler(int host_signum, void *pinfo,
+                           void *puc);
+void cpu_cris_flush_flags(CPUCRISState *, int);
+
+
+void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
+                          int is_asi);
+
+enum {
+    CC_OP_DYNAMIC, /* Use env->cc_op  */
+    CC_OP_FLAGS,
+    CC_OP_LOGIC,
+    CC_OP_CMP,
+    CC_OP_MOVE,
+    CC_OP_MOVE_PD,
+    CC_OP_MOVE_SD,
+    CC_OP_ADD,
+    CC_OP_ADDC,
+    CC_OP_MCP,
+    CC_OP_ADDU,
+    CC_OP_SUB,
+    CC_OP_SUBU,
+    CC_OP_NEG,
+    CC_OP_BTST,
+    CC_OP_MULS,
+    CC_OP_MULU,
+    CC_OP_DSTEP,
+    CC_OP_BOUND,
+
+    CC_OP_OR,
+    CC_OP_AND,
+    CC_OP_XOR,
+    CC_OP_LSL,
+    CC_OP_LSR,
+    CC_OP_ASR,
+    CC_OP_LZ
+};
+
+#define CCF_C 0x01
+#define CCF_V 0x02
+#define CCF_Z 0x04
+#define CCF_N 0x08
+#define CCF_X 0x10
+
+#define CRIS_SSP    0
+#define CRIS_USP    1
+
+typedef struct cris_def_t cris_def_t;
+
+int cpu_cris_set_model(CPUCRISState *env, const char * name);
+
+void cris_set_irq_level(CPUCRISState *env, int level, uint8_t vector);
+void cris_set_macsr(CPUCRISState *env, uint32_t val);
+void cris_switch_sp(CPUCRISState *env);
+
+void do_cris_semihosting(CPUCRISState *env, int nr);
+
+enum cris_features {
+    CRIS_FEATURE_CF_ISA_MUL,
+};
+
+static inline int cris_feature(CPUCRISState *env, int feature)
+{
+    return (env->features & (1u << feature)) != 0;
+}
+
+void register_cris_insns (CPUCRISState *env);
+
+/* CRIS uses 8k pages.  */
+#define TARGET_PAGE_BITS 13
+
+#define CPUState CPUCRISState
+#define cpu_init cpu_cris_init
+#define cpu_exec cpu_cris_exec
+#define cpu_gen_code cpu_cris_gen_code
+#define cpu_signal_handler cpu_cris_signal_handler
+
+/* MMU modes definitions */
+#define MMU_MODE0_SUFFIX _kernel
+#define MMU_MODE1_SUFFIX _user
+#define MMU_USER_IDX 1
+/* CRIS FIXME: I guess we want to validate supervisor mode acceses here.  */
+static inline int cpu_mmu_index (CPUState *env)
+{
+    return 0;
+}
+
+#include "cpu-all.h"
+
+/* Register aliases.  */
+#define REG_SP  14
+#define REG_ACR 15
+#define REG_MOF 7
+
+/* Support regs.  */
+#define SR_PID 2
+#define SR_SRS 3
+#define SR_EBP 9
+#define SR_ERP 10
+#define SR_CCS 13
+
+/* Support func regs.  */
+#define SFR_RW_GC_CFG      0][0
+#define SFR_RW_MM_CFG      1][0
+#define SFR_RW_MM_KBASE_LO 1][1
+#define SFR_RW_MM_KBASE_HI 1][2
+#define SFR_R_MM_CAUSE     1][3
+#define SFR_RW_MM_TLB_SEL  1][4
+#define SFR_RW_MM_TLB_LO   1][5
+#define SFR_RW_MM_TLB_HI   1][6
+
+#endif

Added: trunk/src/host/qemu-neo1973/target-cris/crisv32-decode.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-cris/crisv32-decode.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-cris/crisv32-decode.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,126 @@
+/*
+ *  CRIS insn decoding macros.
+ *
+ *  Copyright (c) 2007 AXIS Communications AB
+ *  Written by Edgar E. Iglesias.
+ *
+ * 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
+ */
+
+/* Convenient binary macros.  */
+#define HEX__(n) 0x##n##LU
+#define B8__(x) ((x&0x0000000FLU)?1:0) \
+                 + ((x&0x000000F0LU)?2:0) \
+                 + ((x&0x00000F00LU)?4:0) \
+                 + ((x&0x0000F000LU)?8:0) \
+                 + ((x&0x000F0000LU)?16:0) \
+                 + ((x&0x00F00000LU)?32:0) \
+                 + ((x&0x0F000000LU)?64:0) \
+                 + ((x&0xF0000000LU)?128:0)
+#define B8(d) ((unsigned char)B8__(HEX__(d)))
+
+/* Quick imm.  */
+#define DEC_BCCQ     {B8(00000000), B8(11110000)}
+#define DEC_ADDOQ    {B8(00010000), B8(11110000)}
+#define DEC_ADDQ     {B8(00100000), B8(11111100)}
+#define DEC_MOVEQ    {B8(00100100), B8(11111100)}
+#define DEC_SUBQ     {B8(00101000), B8(11111100)}
+#define DEC_CMPQ     {B8(00101100), B8(11111100)}
+#define DEC_ANDQ     {B8(00110000), B8(11111100)}
+#define DEC_ORQ      {B8(00110100), B8(11111100)}
+#define DEC_BTSTQ    {B8(00111000), B8(11111110)}
+#define DEC_ASRQ     {B8(00111010), B8(11111110)}
+#define DEC_LSLQ     {B8(00111100), B8(11111110)}
+#define DEC_LSRQ     {B8(00111110), B8(11111110)}
+
+/* Register.  */
+#define DEC_MOVU_R   {B8(01000100), B8(11111110)}
+#define DEC_MOVU_R   {B8(01000100), B8(11111110)}
+#define DEC_MOVS_R   {B8(01000110), B8(11111110)}
+#define DEC_MOVE_R   {B8(01100100), B8(11111100)}
+#define DEC_MOVE_RP  {B8(01100011), B8(11111111)}
+#define DEC_MOVE_PR  {B8(01100111), B8(11111111)}
+#define DEC_DSTEP_R  {B8(01101111), B8(11111111)}
+#define DEC_MOVE_RS  {B8(10110111), B8(11111111)}
+#define DEC_MOVE_SR  {B8(11110111), B8(11111111)}
+#define DEC_ADDU_R   {B8(01000000), B8(11111110)}
+#define DEC_ADDS_R   {B8(01000010), B8(11111110)}
+#define DEC_ADD_R    {B8(01100000), B8(11111100)}
+#define DEC_ADDI_R   {B8(01010000), B8(11111100)}
+#define DEC_MULS_R   {B8(11010000), B8(11111100)}
+#define DEC_MULU_R   {B8(10010000), B8(11111100)}
+#define DEC_ADDI_ACR {B8(01010100), B8(11111100)}
+#define DEC_NEG_R    {B8(01011000), B8(11111100)}
+#define DEC_BOUND_R  {B8(01011100), B8(11111100)}
+#define DEC_SUBU_R   {B8(01001000), B8(11111110)}
+#define DEC_SUBS_R   {B8(01001010), B8(11111110)}
+#define DEC_SUB_R    {B8(01101000), B8(11111100)}
+#define DEC_CMP_R    {B8(01101100), B8(11111100)}
+#define DEC_AND_R    {B8(01110000), B8(11111100)}
+#define DEC_ABS_R    {B8(01101011), B8(11111111)}
+#define DEC_LZ_R     {B8(01110011), B8(11111111)}
+#define DEC_MCP_R    {B8(01111111), B8(11111111)}
+#define DEC_SWAP_R   {B8(01110111), B8(11111111)}
+#define DEC_XOR_R    {B8(01111011), B8(11111111)}
+#define DEC_LSL_R    {B8(01001100), B8(11111100)}
+#define DEC_LSR_R    {B8(01111100), B8(11111100)}
+#define DEC_ASR_R    {B8(01111000), B8(11111100)}
+#define DEC_OR_R     {B8(01110100), B8(11111100)}
+#define DEC_BTST_R   {B8(01001111), B8(11111111)}
+
+/* Fixed.  */
+#define DEC_SETF     {B8(01011011), B8(11111111)}
+#define DEC_CLEARF   {B8(01011111), B8(11111111)}
+
+/* Memory.  */
+#define DEC_ADDU_M   {B8(10000000), B8(10111110)}
+#define DEC_ADDS_M   {B8(10000010), B8(10111110)}
+#define DEC_MOVU_M   {B8(10000100), B8(10111110)}
+#define DEC_MOVS_M   {B8(10000110), B8(10111110)}
+#define DEC_SUBU_M   {B8(10001000), B8(10111110)}
+#define DEC_SUBS_M   {B8(10001010), B8(10111110)}
+#define DEC_CMPU_M   {B8(10001100), B8(10111110)}
+#define DEC_CMPS_M   {B8(10001110), B8(10111110)}
+#define DEC_ADDO_M   {B8(10010100), B8(10111100)}
+#define DEC_BOUND_M  {B8(10011100), B8(10111100)}
+#define DEC_ADD_M    {B8(10100000), B8(10111100)}
+#define DEC_MOVE_MR  {B8(10100100), B8(10111100)}
+#define DEC_SUB_M    {B8(10101000), B8(10111100)}
+#define DEC_CMP_M    {B8(10101100), B8(10111100)}
+#define DEC_AND_M    {B8(10110000), B8(10111100)}
+#define DEC_OR_M     {B8(10110100), B8(10111100)}
+#define DEC_TEST_M   {B8(10111000), B8(10111100)}
+#define DEC_MOVE_RM  {B8(10111100), B8(10111100)}
+
+#define DEC_ADDC_R   {B8(01010111), B8(11111111)}
+#define DEC_ADDC_MR  {B8(10011010), B8(10111111)}
+#define DEC_LAPCQ    {B8(10010111), B8(11111111)}
+#define DEC_LAPC_IM  {B8(11010111), B8(11111111)}
+
+#define DEC_MOVE_MP  {B8(10100011), B8(10111111)}
+#define DEC_MOVE_PM  {B8(10100111), B8(10111111)}
+
+#define DEC_SCC_R    {B8(01010011), B8(11111111)}
+#define DEC_RFE_ETC  {B8(10010011), B8(11111111)}
+#define DEC_JUMP_P   {B8(10011111), B8(11111111)}
+#define DEC_BCC_IM   {B8(11011111), B8(11111111)}
+#define DEC_JAS_R    {B8(10011011), B8(11111111)}
+#define DEC_JASC_R   {B8(10110011), B8(11111111)}
+#define DEC_JAS_IM   {B8(11011011), B8(11111111)}
+#define DEC_JASC_IM  {B8(11110011), B8(11111111)}
+#define DEC_BAS_IM   {B8(11101011), B8(11111111)}
+#define DEC_BASC_IM  {B8(11101111), B8(11111111)}
+#define DEC_MOVEM_MR {B8(10111011), B8(10111111)}
+#define DEC_MOVEM_RM {B8(10111111), B8(10111111)}

Added: trunk/src/host/qemu-neo1973/target-cris/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-cris/exec.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-cris/exec.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,68 @@
+/*
+ *  CRIS execution defines
+ *
+ *  Copyright (c) 2007 AXIS Communications AB
+ *  Written by Edgar E. Iglesias
+ *
+ * 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
+ * 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 "dyngen-exec.h"
+
+#if 1
+register struct CPUCRISState *env asm(AREG0);
+/* This is only used for tb lookup.  */
+register uint32_t T0 asm(AREG1);
+register uint32_t T1 asm(AREG2);
+#else
+struct CPUCRISState *env;
+/* This is only used for tb lookup.  */
+uint32_t T0;
+uint32_t T1;
+#endif
+#include "cpu.h"
+#include "exec-all.h"
+
+#define RETURN() __asm__ __volatile__("" : : : "memory");
+
+static inline void env_to_regs(void)
+{
+}
+
+static inline void regs_to_env(void)
+{
+}
+
+int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+                              int mmu_idx, int is_softmmu);
+void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr);
+
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif
+
+void cpu_cris_flush_flags(CPUCRISState *env, int cc_op);
+void helper_movec(CPUCRISState *env, int reg, uint32_t val);
+
+void cpu_loop_exit(void);
+
+static inline int cpu_halted(CPUState *env) {
+	if (!env->halted)
+		return 0;
+	if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+		env->halted = 0;
+		return 0;
+	}
+	return EXCP_HALTED;
+}

Added: trunk/src/host/qemu-neo1973/target-cris/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-cris/helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-cris/helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,173 @@
+/*
+ *  CRIS helper routines.
+ *
+ *  Copyright (c) 2007 AXIS Communications AB
+ *  Written by Edgar E. Iglesias.
+ *
+ * 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 <string.h>
+
+#include "config.h"
+#include "cpu.h"
+#include "mmu.h"
+#include "exec-all.h"
+#include "host-utils.h"
+
+#if defined(CONFIG_USER_ONLY)
+
+void do_interrupt (CPUState *env)
+{
+  env->exception_index = -1;
+}
+
+int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
+                             int mmu_idx, int is_softmmu)
+{
+    env->exception_index = 0xaa;
+    env->debug1 = address;
+    cpu_dump_state(env, stderr, fprintf, 0);
+    printf("%s addr=%x env->pc=%x\n", __func__, address, env->pc);
+    return 1;
+}
+
+target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
+{
+    return addr;
+}
+
+#else /* !CONFIG_USER_ONLY */
+
+int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+                               int mmu_idx, int is_softmmu)
+{
+	struct cris_mmu_result_t res;
+	int prot, miss;
+	target_ulong phy;
+
+	address &= TARGET_PAGE_MASK;
+	prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+//	printf ("%s pc=%x %x w=%d smmu=%d\n", __func__, env->pc, address, rw, is_softmmu);
+	miss = cris_mmu_translate(&res, env, address, rw, mmu_idx);
+	if (miss)
+	{
+		/* handle the miss.  */
+		phy = 0;
+		env->exception_index = EXCP_MMU_MISS;
+	}
+	else
+	{
+		phy = res.phy;
+	}
+//	printf ("a=%x phy=%x\n", address, phy);
+	return tlb_set_page(env, address, phy, prot, mmu_idx, is_softmmu);
+}
+
+
+static void cris_shift_ccs(CPUState *env)
+{
+	uint32_t ccs;
+	/* Apply the ccs shift.  */
+	ccs = env->pregs[SR_CCS];
+	ccs = (ccs & 0xc0000000) | ((ccs << 12) >> 2);
+//	printf ("ccs=%x %x\n", env->pregs[SR_CCS], ccs);
+	env->pregs[SR_CCS] = ccs;
+}
+
+void do_interrupt(CPUState *env)
+{
+	uint32_t ebp, isr;
+	int irqnum;
+
+	fflush(NULL);
+
+#if 0
+	printf ("exception index=%d interrupt_req=%d\n",
+		env->exception_index,
+		env->interrupt_request);
+#endif
+
+	switch (env->exception_index)
+	{
+		case EXCP_BREAK:
+//			printf ("BREAK! %d\n", env->trapnr);
+			irqnum = env->trapnr;
+			ebp = env->pregs[SR_EBP];
+			isr = ldl_code(ebp + irqnum * 4);
+			env->pregs[SR_ERP] = env->pc + 2;
+			env->pc = isr;
+
+			cris_shift_ccs(env);
+
+			break;
+		case EXCP_MMU_MISS:
+//			printf ("MMU miss\n");
+			irqnum = 4;
+			ebp = env->pregs[SR_EBP];
+			isr = ldl_code(ebp + irqnum * 4);
+			env->pregs[SR_ERP] = env->pc;
+			env->pc = isr;
+			cris_shift_ccs(env);
+			break;
+
+		default:
+		{
+			/* Maybe the irq was acked by sw before we got a
+			   change to take it.  */
+			if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+				if (!env->pending_interrupts)
+					return;
+				if (!(env->pregs[SR_CCS] & I_FLAG)) {
+					return;
+				}
+
+				irqnum = 31 - clz32(env->pending_interrupts);
+				irqnum += 0x30;
+				ebp = env->pregs[SR_EBP];
+				isr = ldl_code(ebp + irqnum * 4);
+				env->pregs[SR_ERP] = env->pc;
+				env->pc = isr;
+
+				cris_shift_ccs(env);
+#if 0
+				printf ("%s ebp=%x %x isr=%x %d"
+					" ir=%x pending=%x\n",
+					__func__,
+					ebp, ebp + irqnum * 4,
+					isr, env->exception_index,
+					env->interrupt_request,
+					env->pending_interrupts);
+#endif
+			}
+
+		}
+		break;
+	}
+}
+
+target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
+{
+//	printf ("%s\n", __func__);
+	uint32_t phy = addr;
+	struct cris_mmu_result_t res;
+	int miss;
+	miss = cris_mmu_translate(&res, env, addr, 0, 0);
+	if (!miss)
+		phy = res.phy;
+	return phy;
+}
+#endif

Added: trunk/src/host/qemu-neo1973/target-cris/mmu.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-cris/mmu.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-cris/mmu.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,148 @@
+/*
+ *  CRIS mmu emulation.
+ *
+ *  Copyright (c) 2007 AXIS Communications AB
+ *  Written by Edgar E. Iglesias.
+ *
+ * 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
+ */
+
+#ifndef CONFIG_USER_ONLY
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "cpu.h"
+#include "mmu.h"
+#include "exec-all.h"
+
+
+static int cris_mmu_enabled(uint32_t rw_gc_cfg)
+{
+	return (rw_gc_cfg & 12) != 0;
+}
+
+static int cris_mmu_segmented_addr(int seg, uint32_t rw_mm_cfg)
+{
+	return (1 << seg) & rw_mm_cfg;
+}
+
+static uint32_t cris_mmu_translate_seg(CPUState *env, int seg)
+{
+	uint32_t base;
+	int i;
+
+	if (seg < 8)
+		base = env->sregs[SFR_RW_MM_KBASE_LO];
+	else
+		base = env->sregs[SFR_RW_MM_KBASE_HI];
+
+	i = seg & 7;
+	base >>= i * 4;
+	base &= 15;
+
+	base <<= 28;
+	return base;
+}
+/* Used by the tlb decoder.  */
+#define EXTRACT_FIELD(src, start, end) \
+            (((src) >> start) & ((1 << (end - start + 1)) - 1))
+
+static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
+				   CPUState *env, uint32_t vaddr,
+				   int rw, int usermode)
+{
+	unsigned int vpage;
+	unsigned int idx;
+	uint32_t lo, hi;
+	uint32_t vpn, pfn = 0, pid, fg, fv, fk, fw, fx;
+	int i, match = 0;
+
+	vpage = vaddr >> 13;
+	idx = vpage & 31;
+	vpage >>= 4;
+
+	/* We know the index which to check on each set.
+	   Scan both I and D.  */
+	for (i = 0; i < 4; i++)
+	{
+		lo = env->tlbsets[0][i][idx].lo;
+		hi = env->tlbsets[0][i][idx].hi;
+
+		vpn = EXTRACT_FIELD(hi, 13, 31);
+		pid = EXTRACT_FIELD(hi, 0, 7);
+
+		if (vpn == vpage
+		    && pid == env->pregs[SR_PID]) {
+			match = 1;
+			break;
+		}
+	}
+
+	if (match) {
+		pfn = EXTRACT_FIELD(lo, 13, 31);
+		fg = EXTRACT_FIELD(lo, 4, 4);
+		fv = EXTRACT_FIELD(lo, 3, 3);
+		fk = EXTRACT_FIELD(lo, 2, 2);
+		fw = EXTRACT_FIELD(lo, 1, 1);
+		fx = EXTRACT_FIELD(lo, 0, 0);
+	}
+	printf ("%s match=%d vaddr=%x vpage=%x vpn=%x pfn=%x pid=%x %x\n",
+		__func__, match,
+		vaddr, vpage,
+		vpn, pfn, pid, env->pregs[SR_PID]);
+	res->pfn = pfn;
+	return !match;
+}
+
+int cris_mmu_translate(struct cris_mmu_result_t *res,
+		       CPUState *env, uint32_t vaddr,
+		       int rw, int mmu_idx)
+{
+	uint32_t phy = vaddr;
+	int seg;
+	int miss = 0;
+        int is_user = mmu_idx == MMU_USER_IDX;
+
+	if (!cris_mmu_enabled(env->sregs[SFR_RW_GC_CFG])) {
+		res->phy = vaddr;
+		return 0;
+	}
+
+	seg = vaddr >> 28;
+	if (cris_mmu_segmented_addr(seg, env->sregs[SFR_RW_MM_CFG]))
+	{
+		uint32_t base;
+
+		miss = 0;
+		base = cris_mmu_translate_seg(env, seg);
+		phy = base | (0x0fffffff & vaddr);
+		res->phy = phy;
+	}
+	else
+	{
+		miss = cris_mmu_translate_page(res, env, vaddr, rw, is_user);
+		if (!miss) {
+			phy &= 8191;
+			phy |= (res->pfn << 13);
+			res->phy = phy;
+		}
+	}
+//	printf ("miss=%d v=%x -> p=%x\n", miss, vaddr, phy);
+	return miss;
+}
+#endif

Added: trunk/src/host/qemu-neo1973/target-cris/mmu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-cris/mmu.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-cris/mmu.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,20 @@
+#define CRIS_MMU_ERR_EXEC  0
+#define CRIS_MMU_ERR_READ  1
+#define CRIS_MMU_ERR_WRITE 2
+#define CRIS_MMU_ERR_FLUSH 3
+
+struct cris_mmu_result_t
+{
+	uint32_t phy;
+	uint32_t pfn;
+	int g:1;
+	int v:1;
+	int k:1;
+	int w:1;
+	int e:1;
+	int cause_op;
+};
+
+int cris_mmu_translate(struct cris_mmu_result_t *res,
+		       CPUState *env, uint32_t vaddr,
+		       int rw, int mmu_idx);

Added: trunk/src/host/qemu-neo1973/target-cris/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-cris/op.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-cris/op.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,1287 @@
+/*
+ *  CRIS emulation micro-operations for qemu.
+ *
+ *  Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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 "host-utils.h"
+
+#define REGNAME r0
+#define REG (env->regs[0])
+#include "op_template.h"
+
+#define REGNAME r1
+#define REG (env->regs[1])
+#include "op_template.h"
+
+#define REGNAME r2
+#define REG (env->regs[2])
+#include "op_template.h"
+
+#define REGNAME r3
+#define REG (env->regs[3])
+#include "op_template.h"
+
+#define REGNAME r4
+#define REG (env->regs[4])
+#include "op_template.h"
+
+#define REGNAME r5
+#define REG (env->regs[5])
+#include "op_template.h"
+
+#define REGNAME r6
+#define REG (env->regs[6])
+#include "op_template.h"
+
+#define REGNAME r7
+#define REG (env->regs[7])
+#include "op_template.h"
+
+#define REGNAME r8
+#define REG (env->regs[8])
+#include "op_template.h"
+
+#define REGNAME r9
+#define REG (env->regs[9])
+#include "op_template.h"
+
+#define REGNAME r10
+#define REG (env->regs[10])
+#include "op_template.h"
+
+#define REGNAME r11
+#define REG (env->regs[11])
+#include "op_template.h"
+
+#define REGNAME r12
+#define REG (env->regs[12])
+#include "op_template.h"
+
+#define REGNAME r13
+#define REG (env->regs[13])
+#include "op_template.h"
+
+#define REGNAME r14
+#define REG (env->regs[14])
+#include "op_template.h"
+
+#define REGNAME r15
+#define REG (env->regs[15])
+#include "op_template.h"
+
+
+#define REGNAME p0
+#define REG (env->pregs[0])
+#include "op_template.h"
+
+#define REGNAME p1
+#define REG (env->pregs[1])
+#include "op_template.h"
+
+#define REGNAME p2
+#define REG (env->pregs[2])
+#include "op_template.h"
+
+#define REGNAME p3
+#define REG (env->pregs[3])
+#include "op_template.h"
+
+#define REGNAME p4
+#define REG (env->pregs[4])
+#include "op_template.h"
+
+#define REGNAME p5
+#define REG (env->pregs[5])
+#include "op_template.h"
+
+#define REGNAME p6
+#define REG (env->pregs[6])
+#include "op_template.h"
+
+#define REGNAME p7
+#define REG (env->pregs[7])
+#include "op_template.h"
+
+#define REGNAME p8
+#define REG (env->pregs[8])
+#include "op_template.h"
+
+#define REGNAME p9
+#define REG (env->pregs[9])
+#include "op_template.h"
+
+#define REGNAME p10
+#define REG (env->pregs[10])
+#include "op_template.h"
+
+#define REGNAME p11
+#define REG (env->pregs[11])
+#include "op_template.h"
+
+#define REGNAME p12
+#define REG (env->pregs[12])
+#include "op_template.h"
+
+#define REGNAME p13
+#define REG (env->pregs[13])
+#include "op_template.h"
+
+#define REGNAME p14
+#define REG (env->pregs[14])
+#include "op_template.h"
+
+#define REGNAME p15
+#define REG (env->pregs[15])
+#include "op_template.h"
+
+/* Microcode.  */
+
+void OPPROTO op_exit_tb (void)
+{
+	EXIT_TB();
+}
+
+void OPPROTO op_goto_tb0 (void)
+{
+	GOTO_TB(op_goto_tb0, PARAM1, 0);
+	RETURN();
+}
+
+void OPPROTO op_goto_tb1 (void)
+{
+	GOTO_TB(op_goto_tb1, PARAM1, 1);
+	RETURN();
+}
+
+void OPPROTO op_break_im(void)
+{
+	env->trapnr = PARAM1;
+	env->exception_index = EXCP_BREAK;
+	cpu_loop_exit();
+}
+
+void OPPROTO op_debug(void)
+{
+	env->exception_index = EXCP_DEBUG;
+	cpu_loop_exit();
+}
+
+void OPPROTO op_exec_insn(void)
+{
+	env->stats.exec_insns++;
+	RETURN();
+}
+void OPPROTO op_exec_load(void)
+{
+	env->stats.exec_loads++;
+	RETURN();
+}
+void OPPROTO op_exec_store(void)
+{
+	env->stats.exec_stores++;
+	RETURN();
+}
+
+void OPPROTO op_ccs_lshift (void)
+{
+	uint32_t ccs;
+
+	/* Apply the ccs shift.  */
+	ccs = env->pregs[SR_CCS];
+	ccs = (ccs & 0xc0000000) | ((ccs << 12) >> 2);
+	env->pregs[SR_CCS] = ccs;
+}
+void OPPROTO op_ccs_rshift (void)
+{
+	uint32_t ccs;
+
+	/* Apply the ccs shift.  */
+	ccs = env->pregs[SR_CCS];
+	ccs = (ccs & 0xc0000000) | (ccs >> 10);
+	env->pregs[SR_CCS] = ccs;
+}
+
+void OPPROTO op_setf (void)
+{
+	env->pregs[SR_CCS] |= PARAM1;
+	RETURN();
+}
+
+void OPPROTO op_clrf (void)
+{
+	env->pregs[SR_CCS] &= ~PARAM1;
+	RETURN();
+}
+
+void OPPROTO op_movl_debug1_T0 (void)
+{
+	env->debug1 = T0;
+	RETURN();
+}
+
+void OPPROTO op_movl_debug2_T0 (void)
+{
+	env->debug2 = T0;
+	RETURN();
+}
+
+void OPPROTO op_movl_debug3_T0 (void)
+{
+	env->debug3 = T0;
+	RETURN();
+}
+void OPPROTO op_movl_debug1_T1 (void)
+{
+	env->debug1 = T1;
+	RETURN();
+}
+
+void OPPROTO op_movl_debug2_T1 (void)
+{
+	env->debug2 = T1;
+	RETURN();
+}
+
+void OPPROTO op_movl_debug3_T1 (void)
+{
+	env->debug3 = T1;
+	RETURN();
+}
+void OPPROTO op_movl_debug3_im (void)
+{
+	env->debug3 = PARAM1;
+	RETURN();
+}
+void OPPROTO op_movl_T0_flags (void)
+{
+	T0 = env->pregs[SR_CCS];
+	RETURN();
+}
+void OPPROTO op_movl_flags_T0 (void)
+{
+	env->pregs[SR_CCS] = T0;
+	RETURN();
+}
+
+void OPPROTO op_movl_sreg_T0 (void)
+{
+	env->sregs[env->pregs[SR_SRS]][PARAM1] = T0;
+	RETURN();
+}
+
+void OPPROTO op_movl_tlb_lo_T0 (void)
+{
+	int srs;
+	srs = env->pregs[SR_SRS];
+	if (srs == 1 || srs == 2)
+	{
+		int set;
+		int idx;
+		uint32_t lo, hi;
+
+		idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
+		set >>= 4;
+		set &= 3;
+
+		idx &= 31;
+		/* We've just made a write to tlb_lo.  */
+		lo = env->sregs[SFR_RW_MM_TLB_LO];
+		hi = env->sregs[SFR_RW_MM_TLB_HI];
+		env->tlbsets[srs - 1][set][idx].lo = lo;
+		env->tlbsets[srs - 1][set][idx].hi = hi;
+	}
+
+	RETURN();
+}
+
+void OPPROTO op_movl_T0_sreg (void)
+{
+	T0 = env->sregs[env->pregs[SR_SRS]][PARAM1];
+	RETURN();
+}
+
+void OPPROTO op_update_cc (void)
+{
+	env->cc_op = PARAM1;
+	env->cc_dest = PARAM2;
+	env->cc_src = PARAM3;
+	RETURN();
+}
+
+void OPPROTO op_update_cc_op (void)
+{
+	env->cc_op = PARAM1;
+	RETURN();
+}
+
+void OPPROTO op_update_cc_mask (void)
+{
+	env->cc_mask = PARAM1;
+	RETURN();
+}
+
+void OPPROTO op_update_cc_dest_T0 (void)
+{
+	env->cc_dest = T0;
+	RETURN();
+}
+
+void OPPROTO op_update_cc_result_T0 (void)
+{
+	env->cc_result = T0;
+	RETURN();
+}
+
+void OPPROTO op_update_cc_size_im (void)
+{
+	env->cc_size = PARAM1;
+	RETURN();
+}
+
+void OPPROTO op_update_cc_src_T1 (void)
+{
+	env->cc_src = T1;
+	RETURN();
+}
+void OPPROTO op_update_cc_x (void)
+{
+	env->cc_x_live = PARAM1;
+	env->cc_x = PARAM2;
+	RETURN();
+}
+
+/* FIXME: is this allowed?  */
+extern inline void evaluate_flags_writeback(uint32_t flags)
+{
+	int x;
+
+	/* Extended arithmetics, leave the z flag alone.  */
+	env->debug3 = env->pregs[SR_CCS];
+
+	if (env->cc_x_live)
+		x = env->cc_x;
+	else
+		x = env->pregs[SR_CCS] & X_FLAG;
+
+	if ((x || env->cc_op == CC_OP_ADDC)
+	    && flags & Z_FLAG)
+		env->cc_mask &= ~Z_FLAG;
+
+	/* all insn clear the x-flag except setf or clrf.  */
+	env->pregs[SR_CCS] &= ~(env->cc_mask | X_FLAG);
+	flags &= env->cc_mask;
+	env->pregs[SR_CCS] |= flags;
+	RETURN();
+}
+
+void OPPROTO op_evaluate_flags_muls(void)
+{
+	uint32_t src;
+	uint32_t dst;
+	uint32_t res;
+	uint32_t flags = 0;
+	/* were gonna have to redo the muls.  */
+	int64_t tmp, t0 ,t1;
+	int32_t mof;
+	int dneg;
+
+	src = env->cc_src;
+	dst = env->cc_dest;
+	res = env->cc_result;
+
+
+	/* cast into signed values to make GCC sign extend.  */
+	t0 = (int32_t)src;
+	t1 = (int32_t)dst;
+	dneg = ((int32_t)res) < 0;
+
+	tmp = t0 * t1;
+	mof = tmp >> 32;
+	if (tmp == 0)
+		flags |= Z_FLAG;
+	else if (tmp < 0)
+		flags |= N_FLAG;
+	if ((dneg && mof != -1)
+	    || (!dneg && mof != 0))
+		flags |= V_FLAG;
+	evaluate_flags_writeback(flags);
+	RETURN();
+}
+
+void OPPROTO op_evaluate_flags_mulu(void)
+{
+	uint32_t src;
+	uint32_t dst;
+	uint32_t res;
+	uint32_t flags = 0;
+	/* were gonna have to redo the muls.  */
+	uint64_t tmp, t0 ,t1;
+	uint32_t mof;
+
+	src = env->cc_src;
+	dst = env->cc_dest;
+	res = env->cc_result;
+
+
+	/* cast into signed values to make GCC sign extend.  */
+	t0 = src;
+	t1 = dst;
+
+	tmp = t0 * t1;
+	mof = tmp >> 32;
+	if (tmp == 0)
+		flags |= Z_FLAG;
+	else if (tmp >> 63)
+		flags |= N_FLAG;
+	if (mof)
+		flags |= V_FLAG;
+
+	evaluate_flags_writeback(flags);
+	RETURN();
+}
+
+void OPPROTO op_evaluate_flags_mcp(void)
+{
+	uint32_t src;
+	uint32_t dst;
+	uint32_t res;
+	uint32_t flags = 0;
+
+	src = env->cc_src;
+	dst = env->cc_dest;
+	res = env->cc_result;
+
+	if ((res & 0x80000000L) != 0L)
+	{
+		flags |= N_FLAG;
+		if (((src & 0x80000000L) == 0L)
+		    && ((dst & 0x80000000L) == 0L))
+		{
+			flags |= V_FLAG;
+		}
+		else if (((src & 0x80000000L) != 0L) &&
+			 ((dst & 0x80000000L) != 0L))
+		{
+			flags |= R_FLAG;
+		}
+	}
+	else
+	{
+		if (res == 0L)
+			flags |= Z_FLAG;
+		if (((src & 0x80000000L) != 0L)
+		    && ((dst & 0x80000000L) != 0L))
+			flags |= V_FLAG;
+		if ((dst & 0x80000000L) != 0L
+		    || (src & 0x80000000L) != 0L)
+			flags |= R_FLAG;
+	}
+
+	evaluate_flags_writeback(flags);
+	RETURN();
+}
+
+void OPPROTO op_evaluate_flags_alu_4(void)
+{
+	uint32_t src;
+	uint32_t dst;
+	uint32_t res;
+	uint32_t flags = 0;
+
+	src = env->cc_src;
+	dst = env->cc_dest;
+	res = env->cc_result;
+
+	if ((res & 0x80000000L) != 0L)
+	{
+		flags |= N_FLAG;
+		if (((src & 0x80000000L) == 0L)
+		    && ((dst & 0x80000000L) == 0L))
+		{
+			flags |= V_FLAG;
+		}
+		else if (((src & 0x80000000L) != 0L) &&
+			 ((dst & 0x80000000L) != 0L))
+		{
+			flags |= C_FLAG;
+		}
+	}
+	else
+	{
+		if (res == 0L)
+			flags |= Z_FLAG;
+		if (((src & 0x80000000L) != 0L)
+		    && ((dst & 0x80000000L) != 0L))
+			flags |= V_FLAG;
+		if ((dst & 0x80000000L) != 0L
+		    || (src & 0x80000000L) != 0L)
+			flags |= C_FLAG;
+	}
+
+	if (env->cc_op == CC_OP_SUB
+	    || env->cc_op == CC_OP_CMP) {
+		flags ^= C_FLAG;
+	}
+	evaluate_flags_writeback(flags);
+	RETURN();
+}
+
+void OPPROTO op_evaluate_flags_move_4 (void)
+{
+	uint32_t src;
+	uint32_t res;
+	uint32_t flags = 0;
+
+	src = env->cc_src;
+	res = env->cc_result;
+
+	if ((int32_t)res < 0)
+		flags |= N_FLAG;
+	else if (res == 0L)
+		flags |= Z_FLAG;
+
+	evaluate_flags_writeback(flags);
+	RETURN();
+}
+void OPPROTO op_evaluate_flags_move_2 (void)
+{
+	uint32_t src;
+	uint32_t flags = 0;
+	uint16_t res;
+
+	src = env->cc_src;
+	res = env->cc_result;
+
+	if ((int16_t)res < 0L)
+		flags |= N_FLAG;
+	else if (res == 0)
+		flags |= Z_FLAG;
+
+	evaluate_flags_writeback(flags);
+	RETURN();
+}
+
+/* TODO: This is expensive. We could split things up and only evaluate part of
+   CCR on a need to know basis. For now, we simply re-evaluate everything.  */
+void OPPROTO op_evaluate_flags (void)
+{
+	uint32_t src;
+	uint32_t dst;
+	uint32_t res;
+	uint32_t flags = 0;
+
+	src = env->cc_src;
+	dst = env->cc_dest;
+	res = env->cc_result;
+
+
+	/* Now, evaluate the flags. This stuff is based on
+	   Per Zander's CRISv10 simulator.  */
+	switch (env->cc_size)
+	{
+		case 1:
+			if ((res & 0x80L) != 0L)
+			{
+				flags |= N_FLAG;
+				if (((src & 0x80L) == 0L)
+				    && ((dst & 0x80L) == 0L))
+				{
+					flags |= V_FLAG;
+				}
+				else if (((src & 0x80L) != 0L)
+					 && ((dst & 0x80L) != 0L))
+				{
+					flags |= C_FLAG;
+				}
+			}
+			else
+			{
+				if ((res & 0xFFL) == 0L)
+				{
+					flags |= Z_FLAG;
+				}
+				if (((src & 0x80L) != 0L)
+				    && ((dst & 0x80L) != 0L))
+				{
+					flags |= V_FLAG;
+				}
+				if ((dst & 0x80L) != 0L
+				    || (src & 0x80L) != 0L)
+				{
+					flags |= C_FLAG;
+				}
+			}
+			break;
+		case 2:
+			if ((res & 0x8000L) != 0L)
+			{
+				flags |= N_FLAG;
+				if (((src & 0x8000L) == 0L)
+				    && ((dst & 0x8000L) == 0L))
+				{
+					flags |= V_FLAG;
+				}
+				else if (((src & 0x8000L) != 0L)
+					 && ((dst & 0x8000L) != 0L))
+				{
+					flags |= C_FLAG;
+				}
+			}
+			else
+			{
+				if ((res & 0xFFFFL) == 0L)
+				{
+					flags |= Z_FLAG;
+				}
+				if (((src & 0x8000L) != 0L)
+				    && ((dst & 0x8000L) != 0L))
+				{
+					flags |= V_FLAG;
+				}
+				if ((dst & 0x8000L) != 0L
+				    || (src & 0x8000L) != 0L)
+				{
+					flags |= C_FLAG;
+				}
+			}
+			break;
+		case 4:
+			if ((res & 0x80000000L) != 0L)
+			{
+				flags |= N_FLAG;
+				if (((src & 0x80000000L) == 0L)
+				    && ((dst & 0x80000000L) == 0L))
+				{
+					flags |= V_FLAG;
+				}
+				else if (((src & 0x80000000L) != 0L) &&
+					 ((dst & 0x80000000L) != 0L))
+				{
+					flags |= C_FLAG;
+				}
+			}
+			else
+			{
+				if (res == 0L)
+					flags |= Z_FLAG;
+				if (((src & 0x80000000L) != 0L)
+				    && ((dst & 0x80000000L) != 0L))
+					flags |= V_FLAG;
+				if ((dst & 0x80000000L) != 0L
+				    || (src & 0x80000000L) != 0L)
+					flags |= C_FLAG;
+			}
+			break;
+		default:
+			break;
+	}
+
+	if (env->cc_op == CC_OP_SUB
+	    || env->cc_op == CC_OP_CMP) {
+		flags ^= C_FLAG;
+	}
+	evaluate_flags_writeback(flags);
+	RETURN();
+}
+
+void OPPROTO op_extb_T0_T0 (void)
+{
+	T0 = ((int8_t)T0);
+	RETURN();
+}
+void OPPROTO op_extb_T1_T0 (void)
+{
+	T1 = ((int8_t)T0);
+	RETURN();
+}
+void OPPROTO op_extb_T1_T1 (void)
+{
+	T1 = ((int8_t)T1);
+	RETURN();
+}
+void OPPROTO op_zextb_T0_T0 (void)
+{
+	T0 = ((uint8_t)T0);
+	RETURN();
+}
+void OPPROTO op_zextb_T1_T0 (void)
+{
+	T1 = ((uint8_t)T0);
+	RETURN();
+}
+void OPPROTO op_zextb_T1_T1 (void)
+{
+	T1 = ((uint8_t)T1);
+	RETURN();
+}
+void OPPROTO op_extw_T0_T0 (void)
+{
+	T0 = ((int16_t)T0);
+	RETURN();
+}
+void OPPROTO op_extw_T1_T0 (void)
+{
+	T1 = ((int16_t)T0);
+	RETURN();
+}
+void OPPROTO op_extw_T1_T1 (void)
+{
+	T1 = ((int16_t)T1);
+	RETURN();
+}
+
+void OPPROTO op_zextw_T0_T0 (void)
+{
+	T0 = ((uint16_t)T0);
+	RETURN();
+}
+void OPPROTO op_zextw_T1_T0 (void)
+{
+	T1 = ((uint16_t)T0);
+	RETURN();
+}
+
+void OPPROTO op_zextw_T1_T1 (void)
+{
+	T1 = ((uint16_t)T1);
+	RETURN();
+}
+
+void OPPROTO op_movl_T0_im (void)
+{
+	T0 = PARAM1;
+	RETURN();
+}
+void OPPROTO op_movl_T1_im (void)
+{
+	T1 = PARAM1;
+	RETURN();
+}
+
+void OPPROTO op_addl_T0_im (void)
+{
+	T0 += PARAM1;
+	RETURN();
+}
+
+void OPPROTO op_addl_T1_im (void)
+{
+	T1 += PARAM1;
+	RETURN();
+
+}
+void OPPROTO op_subl_T0_im (void)
+{
+	T0 -= PARAM1;
+	RETURN();
+}
+
+void OPPROTO op_addxl_T0_C (void)
+{
+	if (env->pregs[SR_CCS] & X_FLAG)
+		T0 += !!(env->pregs[SR_CCS] & C_FLAG);
+	RETURN();
+}
+void OPPROTO op_subxl_T0_C (void)
+{
+	if (env->pregs[SR_CCS] & X_FLAG)
+		T0 -= !!(env->pregs[SR_CCS] & C_FLAG);
+	RETURN();
+}
+void OPPROTO op_addl_T0_C (void)
+{
+	T0 += !!(env->pregs[SR_CCS] & C_FLAG);
+	RETURN();
+}
+void OPPROTO op_addl_T0_R (void)
+{
+	T0 += !!(env->pregs[SR_CCS] & R_FLAG);
+	RETURN();
+}
+
+void OPPROTO op_clr_R (void)
+{
+	env->pregs[SR_CCS] &= ~R_FLAG;
+	RETURN();
+}
+
+
+void OPPROTO op_andl_T0_im (void)
+{
+	T0 &= PARAM1;
+	RETURN();
+}
+
+void OPPROTO op_andl_T1_im (void)
+{
+	T1 &= PARAM1;
+	RETURN();
+}
+
+void OPPROTO op_movl_T0_T1 (void)
+{
+	T0 = T1;
+	RETURN();
+}
+
+void OPPROTO op_swp_T0_T1 (void)
+{
+	T0 ^= T1;
+	T1 ^= T0;
+	T0 ^= T1;
+	RETURN();
+}
+
+void OPPROTO op_movl_T1_T0 (void)
+{
+	T1 = T0;
+	RETURN();
+}
+
+void OPPROTO op_movl_pc_T0 (void)
+{
+	env->pc = T0;
+	RETURN();
+}
+
+void OPPROTO op_movl_T0_0 (void)
+{
+	T0 = 0;
+	RETURN();
+}
+
+void OPPROTO op_addl_T0_T1 (void)
+{
+	T0 += T1;
+	RETURN();
+}
+
+void OPPROTO op_subl_T0_T1 (void)
+{
+	T0 -= T1;
+	RETURN();
+}
+
+void OPPROTO op_absl_T1_T1 (void)
+{
+	int32_t st = T1;
+
+	T1 = st < 0 ? -st : st;
+	RETURN();
+}
+
+void OPPROTO op_muls_T0_T1 (void)
+{
+	int64_t tmp, t0 ,t1;
+
+	/* cast into signed values to make GCC sign extend these babies.  */
+	t0 = (int32_t)T0;
+	t1 = (int32_t)T1;
+
+	tmp = t0 * t1;
+	T0 = tmp & 0xffffffff;
+	env->pregs[REG_MOF] = tmp >> 32;
+	RETURN();
+}
+
+void OPPROTO op_mulu_T0_T1 (void)
+{
+	uint64_t tmp, t0 ,t1;
+	t0 = T0;
+	t1 = T1;
+
+	tmp = t0 * t1;
+	T0 = tmp & 0xffffffff;
+	env->pregs[REG_MOF] = tmp >> 32;
+	RETURN();
+}
+
+void OPPROTO op_dstep_T0_T1 (void)
+{
+	T0 <<= 1;
+	if (T0 >= T1)
+		T0 -= T1;
+	RETURN();
+}
+
+void OPPROTO op_orl_T0_T1 (void)
+{
+	T0 |= T1;
+	RETURN();
+}
+
+void OPPROTO op_andl_T0_T1 (void)
+{
+	T0 &= T1;
+	RETURN();
+}
+
+void OPPROTO op_xorl_T0_T1 (void)
+{
+	T0 ^= T1;
+	RETURN();
+}
+
+void OPPROTO op_lsll_T0_T1 (void)
+{
+	int s = T1;
+	if (s > 31)
+		T0 = 0;
+	else
+		T0 <<= s;
+	RETURN();
+}
+
+void OPPROTO op_lsll_T0_im (void)
+{
+	T0 <<= PARAM1;
+	RETURN();
+}
+
+void OPPROTO op_lsrl_T0_T1 (void)
+{
+	int s = T1;
+	if (s > 31)
+		T0 = 0;
+	else
+		T0 >>= s;
+	RETURN();
+}
+
+/* Rely on GCC emitting an arithmetic shift for signed right shifts.  */
+void OPPROTO op_asrl_T0_T1 (void)
+{
+	int s = T1;
+	if (s > 31)
+		T0 = T0 & 0x80000000 ? -1 : 0;
+	else
+		T0 = (int32_t)T0 >> s;
+	RETURN();
+}
+
+void OPPROTO op_btst_T0_T1 (void)
+{
+	/* FIXME: clean this up.  */
+
+	/* des ref:
+	   The N flag is set according to the selected bit in the dest reg.
+	   The Z flag is set if the selected bit and all bits to the right are
+	   zero.
+	   The destination reg is not affected.*/
+	unsigned int fz, sbit, bset, mask, masked_t0;
+
+	sbit = T1 & 31;
+        bset = !!(T0 & (1 << sbit));
+	mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1;
+	masked_t0 = T0 & mask;
+	fz = !(masked_t0 | bset);
+	/* Set the N and Z flags accordingly.  */
+	T0 = (bset << 3) | (fz << 2);
+	RETURN();
+}
+
+void OPPROTO op_bound_T0_T1 (void)
+{
+	if (T0 > T1)
+		T0 = T1;
+	RETURN();
+}
+
+void OPPROTO op_lz_T0_T1 (void)
+{
+	T0 = clz32(T1);
+	RETURN();
+}
+
+void OPPROTO op_negl_T0_T1 (void)
+{
+	T0 = -T1;
+	RETURN();
+}
+
+void OPPROTO op_negl_T1_T1 (void)
+{
+	T1 = -T1;
+	RETURN();
+}
+
+void OPPROTO op_not_T0_T0 (void)
+{
+	T0 = ~(T0);
+	RETURN();
+}
+void OPPROTO op_not_T1_T1 (void)
+{
+	T1 = ~(T1);
+	RETURN();
+}
+
+void OPPROTO op_swapw_T0_T0 (void)
+{
+	T0 = (T0 << 16) | ((T0 >> 16));
+	RETURN();
+}
+
+void OPPROTO op_swapb_T0_T0 (void)
+{
+	T0 = ((T0 << 8) & 0xff00ff00) | ((T0 >> 8) & 0x00ff00ff);
+	RETURN();
+}
+
+void OPPROTO op_swapr_T0_T0 (void)
+{
+	T0 = (((T0 << 7) & 0x80808080) |
+	      ((T0 << 5) & 0x40404040) |
+	      ((T0 << 3) & 0x20202020) |
+	      ((T0 << 1) & 0x10101010) |
+	      ((T0 >> 1) & 0x08080808) |
+	      ((T0 >> 3) & 0x04040404) |
+	      ((T0 >> 5) & 0x02020202) |
+	      ((T0 >> 7) & 0x01010101));
+	RETURN();
+}
+
+void OPPROTO op_tst_cc_eq (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int z_set;
+
+	z_set = !!(flags & Z_FLAG);
+	T0 = z_set;
+	RETURN();
+}
+
+void OPPROTO op_tst_cc_eq_fast (void) {
+	T0 = !(env->cc_result);
+	RETURN();
+}
+
+void OPPROTO op_tst_cc_ne (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int z_set;
+
+	z_set = !!(flags & Z_FLAG);
+	T0 = !z_set;
+	RETURN();
+}
+void OPPROTO op_tst_cc_ne_fast (void) {
+	T0 = !!(env->cc_result);
+	RETURN();
+}
+
+void OPPROTO op_tst_cc_cc (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int c_set;
+
+	c_set = !!(flags & C_FLAG);
+	T0 = !c_set;
+	RETURN();
+}
+void OPPROTO op_tst_cc_cs (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int c_set;
+
+	c_set = !!(flags & C_FLAG);
+	T0 = c_set;
+	RETURN();
+}
+
+void OPPROTO op_tst_cc_vc (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int v_set;
+
+	v_set = !!(flags & V_FLAG);
+	T0 = !v_set;
+	RETURN();
+}
+void OPPROTO op_tst_cc_vs (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int v_set;
+
+	v_set = !!(flags & V_FLAG);
+	T0 = v_set;
+	RETURN();
+}
+void OPPROTO op_tst_cc_pl (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int n_set;
+
+	n_set = !!(flags & N_FLAG);
+	T0 = !n_set;
+	RETURN();
+}
+void OPPROTO op_tst_cc_pl_fast (void) {
+	T0 = ((int32_t)env->cc_result) >= 0;
+	RETURN();
+}
+
+void OPPROTO op_tst_cc_mi (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int n_set;
+
+	n_set = !!(flags & N_FLAG);
+	T0 = n_set;
+	RETURN();
+}
+void OPPROTO op_tst_cc_mi_fast (void) {
+	T0 = ((int32_t)env->cc_result) < 0;
+	RETURN();
+}
+
+void OPPROTO op_tst_cc_ls (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int c_set;
+	int z_set;
+
+	c_set = !!(flags & C_FLAG);
+	z_set = !!(flags & Z_FLAG);
+	T0 = c_set || z_set;
+	RETURN();
+}
+void OPPROTO op_tst_cc_hi (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int z_set;
+	int c_set;
+
+	z_set = !!(flags & Z_FLAG);
+	c_set = !!(flags & C_FLAG);
+	T0 = !c_set && !z_set;
+	RETURN();
+
+}
+
+void OPPROTO op_tst_cc_ge (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int n_set;
+	int v_set;
+
+	n_set = !!(flags & N_FLAG);
+	v_set = !!(flags & V_FLAG);
+	T0 = (n_set && v_set) || (!n_set && !v_set);
+	RETURN();
+}
+
+void OPPROTO op_tst_cc_ge_fast (void) {
+	T0 = ((int32_t)env->cc_src < (int32_t)env->cc_dest);
+	RETURN();
+}
+
+void OPPROTO op_tst_cc_lt (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int n_set;
+	int v_set;
+
+	n_set = !!(flags & N_FLAG);
+	v_set = !!(flags & V_FLAG);
+	T0 = (n_set && !v_set) || (!n_set && v_set);
+	RETURN();
+}
+
+void OPPROTO op_tst_cc_gt (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int n_set;
+	int v_set;
+	int z_set;
+
+	n_set = !!(flags & N_FLAG);
+	v_set = !!(flags & V_FLAG);
+	z_set = !!(flags & Z_FLAG);
+	T0 = (n_set && v_set && !z_set)
+		|| (!n_set && !v_set && !z_set);
+	RETURN();
+}
+
+void OPPROTO op_tst_cc_le (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int n_set;
+	int v_set;
+	int z_set;
+
+	n_set = !!(flags & N_FLAG);
+	v_set = !!(flags & V_FLAG);
+	z_set = !!(flags & Z_FLAG);
+	T0 = z_set || (n_set && !v_set) || (!n_set && v_set);
+	RETURN();
+}
+
+void OPPROTO op_tst_cc_p (void) {
+	uint32_t flags = env->pregs[SR_CCS];
+	int p_set;
+
+	p_set = !!(flags & P_FLAG);
+	T0 = p_set;
+	RETURN();
+}
+
+/* Evaluate the if the branch should be taken or not. Needs to be done in
+   the original sequence. The acutal branch is rescheduled to right after the
+   delay-slot.  */
+void OPPROTO op_evaluate_bcc (void)
+{
+	env->btaken = T0;
+	RETURN();
+}
+
+/* this one is used on every alu op, optimize it!.  */
+void OPPROTO op_goto_if_not_x (void)
+{
+	if (env->pregs[SR_CCS] & X_FLAG)
+		GOTO_LABEL_PARAM(1);
+	RETURN();
+}
+
+void OPPROTO op_cc_jmp (void)
+{
+	if (env->btaken)
+		env->pc = PARAM1;
+	else
+		env->pc = PARAM2;
+	RETURN();
+}
+
+void OPPROTO op_cc_ngoto (void)
+{
+	if (!env->btaken)
+		GOTO_LABEL_PARAM(1);
+	RETURN();
+}
+
+void OPPROTO op_movl_btarget_T0 (void)
+{
+	env->btarget = T0;
+	RETURN();
+}
+
+void OPPROTO op_jmp (void)
+{
+	env->pc = env->btarget;
+	RETURN();
+}
+
+/* Load and store */
+#define MEMSUFFIX _raw
+#include "op_mem.c"
+#undef MEMSUFFIX
+#if !defined(CONFIG_USER_ONLY)
+#define MEMSUFFIX _user
+#include "op_mem.c"
+#undef MEMSUFFIX
+
+#define MEMSUFFIX _kernel
+#include "op_mem.c"
+#undef MEMSUFFIX
+#endif

Added: trunk/src/host/qemu-neo1973/target-cris/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-cris/op_helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-cris/op_helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,80 @@
+/*
+ *  CRIS helper routines
+ *
+ *  Copyright (c) 2007 AXIS Communications
+ *  Written by Edgar E. Iglesias
+ *
+ * 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 <assert.h>
+#include "exec.h"
+
+#define MMUSUFFIX _mmu
+#ifdef __s390__
+# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
+#else
+# define GETPC() (__builtin_return_address(0))
+#endif
+
+#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 mmu_idx, 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_cris_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
+    if (__builtin_expect(ret, 0)) {
+        if (retaddr) {
+            /* now we have a real cpu fault */
+            pc = (target_phys_addr_t)retaddr;
+            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, NULL);
+            }
+        }
+        cpu_loop_exit();
+    }
+    env = saved_env;
+}
+
+void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
+                          int is_asi)
+{
+
+}

Added: trunk/src/host/qemu-neo1973/target-cris/op_mem.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-cris/op_mem.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-cris/op_mem.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,59 @@
+/*
+ *  CRIS memory access (load and store) micro operations.
+ *
+ *  Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * 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 glue(op_ldb_T0_T0, MEMSUFFIX) (void) {
+    T0 = glue(ldsb, MEMSUFFIX) (T0);
+    RETURN();
+}
+
+void glue(op_ldub_T0_T0, MEMSUFFIX) (void) {
+    T0 = glue(ldub, MEMSUFFIX) (T0);
+    RETURN();
+}
+
+void glue(op_stb_T0_T1, MEMSUFFIX) (void) {
+    glue(stb, MEMSUFFIX) (T0, T1);
+    RETURN();
+}
+
+void glue(op_ldw_T0_T0, MEMSUFFIX) (void) {
+    T0 = glue(ldsw, MEMSUFFIX) (T0);
+    RETURN();
+}
+
+void glue(op_lduw_T0_T0, MEMSUFFIX) (void) {
+    T0 = glue(lduw, MEMSUFFIX) (T0);
+    RETURN();
+}
+
+void glue(op_stw_T0_T1, MEMSUFFIX) (void) {
+    glue(stw, MEMSUFFIX) (T0, T1);
+    RETURN();
+}
+
+void glue(op_ldl_T0_T0, MEMSUFFIX) (void) {
+    T0 = glue(ldl, MEMSUFFIX) (T0);
+    RETURN();
+}
+
+void glue(op_stl_T0_T1, MEMSUFFIX) (void) {
+    glue(stl, MEMSUFFIX) (T0, T1);
+    RETURN();
+}

Added: trunk/src/host/qemu-neo1973/target-cris/op_template.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-cris/op_template.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-cris/op_template.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,48 @@
+/*
+ *  CRIS micro operations (templates for various register related
+ *  operations)
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ * 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
+ */
+
+#ifndef SET_REG
+#define SET_REG(x) REG = x
+#endif
+
+void OPPROTO glue(op_movl_T0_, REGNAME)(void)
+{
+    T0 = REG;
+}
+
+void OPPROTO glue(op_movl_T1_, REGNAME)(void)
+{
+    T1 = REG;
+}
+
+void OPPROTO glue(glue(op_movl_, REGNAME), _T0)(void)
+{
+    SET_REG (T0);
+}
+
+void OPPROTO glue(glue(op_movl_, REGNAME), _T1)(void)
+{
+    SET_REG (T1);
+}
+
+#undef REG
+#undef REGNAME
+#undef SET_REG

Added: trunk/src/host/qemu-neo1973/target-cris/opcode-cris.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-cris/opcode-cris.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-cris/opcode-cris.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,366 @@
+/* cris.h -- Header file for CRIS opcode and register tables.
+   Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc.
+   Contributed by Axis Communications AB, Lund, Sweden.
+   Originally written for GAS 1.38.1 by Mikael Asker.
+   Updated, BFDized and GNUified by Hans-Peter Nilsson.
+
+This file is part of GAS, GDB and the GNU binutils.
+
+GAS, GDB, and GNU binutils 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, or (at your
+option) any later version.
+
+GAS, GDB, and GNU binutils are distributed in the hope that they 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 __CRIS_H_INCLUDED_
+#define __CRIS_H_INCLUDED_
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+
+
+/* Registers.  */
+#define MAX_REG (15)
+#define REG_SP (14)
+#define REG_PC (15)
+
+/* CPU version control of disassembly and assembly of instructions.
+   May affect how the instruction is assembled, at least the size of
+   immediate operands.  */
+enum cris_insn_version_usage
+{
+  /* Any version.  */
+  cris_ver_version_all=0,
+
+  /* Indeterminate (intended for disassembly only, or obsolete).  */
+  cris_ver_warning,
+
+  /* Only for v0..3 (Etrax 1..4).  */
+  cris_ver_v0_3,
+
+  /* Only for v3 or higher (ETRAX 4 and beyond).  */
+  cris_ver_v3p,
+
+  /* Only for v8 (Etrax 100).  */
+  cris_ver_v8,
+
+  /* Only for v8 or higher (ETRAX 100, ETRAX 100 LX).  */
+  cris_ver_v8p,
+
+  /* Only for v0..10.  FIXME: Not sure what to do with this.  */
+  cris_ver_sim_v0_10,
+
+  /* Only for v0..10.  */
+  cris_ver_v0_10,
+
+  /* Only for v3..10.  (ETRAX 4, ETRAX 100 and ETRAX 100 LX).  */
+  cris_ver_v3_10,
+
+  /* Only for v8..10 (ETRAX 100 and ETRAX 100 LX).  */
+  cris_ver_v8_10,
+
+  /* Only for v10 (ETRAX 100 LX) and same series.  */
+  cris_ver_v10,
+
+  /* Only for v10 (ETRAX 100 LX) and same series.  */
+  cris_ver_v10p,
+
+  /* Only for v32 or higher (codename GUINNESS).
+     Of course some or all these of may change to cris_ver_v32p if/when
+     there's a new revision. */
+  cris_ver_v32p
+};
+
+
+/* Special registers.  */
+struct cris_spec_reg
+{
+  const char *const name;
+  unsigned int number;
+
+  /* The size of the register.  */
+  unsigned int reg_size;
+
+  /* What CPU version the special register of that name is implemented
+     in.  If cris_ver_warning, emit an unimplemented-warning.  */
+  enum cris_insn_version_usage applicable_version;
+
+  /* There might be a specific warning for using a special register
+     here.  */
+  const char *const warning;
+};
+extern const struct cris_spec_reg cris_spec_regs[];
+
+
+/* Support registers (kind of special too, but not named as such).  */
+struct cris_support_reg
+{
+  const char *const name;
+  unsigned int number;
+};
+extern const struct cris_support_reg cris_support_regs[];
+
+struct cris_cond15
+{
+  /* The name of the condition.  */
+  const char *const name;
+
+  /* What CPU version this condition name applies to.  */
+  enum cris_insn_version_usage applicable_version;
+};
+extern const struct cris_cond15 cris_conds15[];
+
+/* Opcode-dependent constants.  */
+#define AUTOINCR_BIT (0x04)
+
+/* Prefixes.  */
+#define BDAP_QUICK_OPCODE (0x0100)
+#define BDAP_QUICK_Z_BITS (0x0e00)
+
+#define BIAP_OPCODE	  (0x0540)
+#define BIAP_Z_BITS	  (0x0a80)
+
+#define DIP_OPCODE	  (0x0970)
+#define DIP_Z_BITS	  (0xf280)
+
+#define BDAP_INDIR_LOW	  (0x40)
+#define BDAP_INDIR_LOW_Z  (0x80)
+#define BDAP_INDIR_HIGH	  (0x09)
+#define BDAP_INDIR_HIGH_Z (0x02)
+
+#define BDAP_INDIR_OPCODE (BDAP_INDIR_HIGH * 0x0100 + BDAP_INDIR_LOW)
+#define BDAP_INDIR_Z_BITS (BDAP_INDIR_HIGH_Z * 0x100 + BDAP_INDIR_LOW_Z)
+#define BDAP_PC_LOW	  (BDAP_INDIR_LOW + REG_PC)
+#define BDAP_INCR_HIGH	  (BDAP_INDIR_HIGH + AUTOINCR_BIT)
+
+/* No prefix must have this code for its "match" bits in the
+   opcode-table.  "BCC .+2" will do nicely.  */
+#define NO_CRIS_PREFIX 0
+
+/* Definitions for condition codes.  */
+#define CC_CC  0x0
+#define CC_HS  0x0
+#define CC_CS  0x1
+#define CC_LO  0x1
+#define CC_NE  0x2
+#define CC_EQ  0x3
+#define CC_VC  0x4
+#define CC_VS  0x5
+#define CC_PL  0x6
+#define CC_MI  0x7
+#define CC_LS  0x8
+#define CC_HI  0x9
+#define CC_GE  0xA
+#define CC_LT  0xB
+#define CC_GT  0xC
+#define CC_LE  0xD
+#define CC_A   0xE
+#define CC_EXT 0xF
+
+/* A table of strings "cc", "cs"... indexed with condition code
+   values as above.  */
+extern const char *const cris_cc_strings[];
+
+/* Bcc quick.  */
+#define BRANCH_QUICK_LOW  (0)
+#define BRANCH_QUICK_HIGH (0)
+#define BRANCH_QUICK_OPCODE (BRANCH_QUICK_HIGH * 0x0100 + BRANCH_QUICK_LOW)
+#define BRANCH_QUICK_Z_BITS (0x0F00)
+
+/* BA quick.  */
+#define BA_QUICK_HIGH (BRANCH_QUICK_HIGH + CC_A * 0x10)
+#define BA_QUICK_OPCODE (BA_QUICK_HIGH * 0x100 + BRANCH_QUICK_LOW)
+
+/* Bcc [PC+].  */
+#define BRANCH_PC_LOW	 (0xFF)
+#define BRANCH_INCR_HIGH (0x0D)
+#define BA_PC_INCR_OPCODE \
+ ((BRANCH_INCR_HIGH + CC_A * 0x10) * 0x0100 + BRANCH_PC_LOW)
+
+/* Jump.  */
+/* Note that old versions generated special register 8 (in high bits)
+   and not-that-old versions recognized it as a jump-instruction.
+   That opcode now belongs to JUMPU.  */
+#define JUMP_INDIR_OPCODE (0x0930)
+#define JUMP_INDIR_Z_BITS (0xf2c0)
+#define JUMP_PC_INCR_OPCODE \
+ (JUMP_INDIR_OPCODE + AUTOINCR_BIT * 0x0100 + REG_PC)
+
+#define MOVE_M_TO_PREG_OPCODE 0x0a30
+#define MOVE_M_TO_PREG_ZBITS 0x01c0
+
+/* BDAP.D N,PC.  */
+#define MOVE_PC_INCR_OPCODE_PREFIX \
+ (((BDAP_INCR_HIGH | (REG_PC << 4)) << 8) | BDAP_PC_LOW | (2 << 4))
+#define MOVE_PC_INCR_OPCODE_SUFFIX \
+ (MOVE_M_TO_PREG_OPCODE | REG_PC | (AUTOINCR_BIT << 8))
+
+#define JUMP_PC_INCR_OPCODE_V32 (0x0DBF)
+
+/* BA DWORD (V32).  */
+#define BA_DWORD_OPCODE (0x0EBF)
+
+/* Nop.  */
+#define NOP_OPCODE (0x050F)
+#define NOP_Z_BITS (0xFFFF ^ NOP_OPCODE)
+
+#define NOP_OPCODE_V32 (0x05B0)
+#define NOP_Z_BITS_V32 (0xFFFF ^ NOP_OPCODE_V32)
+
+/* For the compatibility mode, let's use "MOVE R0,P0".  Doesn't affect
+   registers or flags.  Unfortunately shuts off interrupts for one cycle
+   for < v32, but there doesn't seem to be any alternative without that
+   effect.  */
+#define NOP_OPCODE_COMMON (0x630)
+#define NOP_OPCODE_ZBITS_COMMON (0xffff & ~NOP_OPCODE_COMMON)
+
+/* LAPC.D  */
+#define LAPC_DWORD_OPCODE (0x0D7F)
+#define LAPC_DWORD_Z_BITS (0x0fff & ~LAPC_DWORD_OPCODE)
+
+/* Structure of an opcode table entry.  */
+enum cris_imm_oprnd_size_type
+{
+  /* No size is applicable.  */
+  SIZE_NONE,
+
+  /* Always 32 bits.  */
+  SIZE_FIX_32,
+
+  /* Indicated by size of special register.  */
+  SIZE_SPEC_REG,
+
+  /* Indicated by size field, signed.  */
+  SIZE_FIELD_SIGNED,
+
+  /* Indicated by size field, unsigned.  */
+  SIZE_FIELD_UNSIGNED,
+
+  /* Indicated by size field, no sign implied.  */
+  SIZE_FIELD
+};
+
+/* For GDB.  FIXME: Is this the best way to handle opcode
+   interpretation?  */
+enum cris_op_type
+{
+  cris_not_implemented_op = 0,
+  cris_abs_op,
+  cris_addi_op,
+  cris_asr_op,
+  cris_asrq_op,
+  cris_ax_ei_setf_op,
+  cris_bdap_prefix,
+  cris_biap_prefix,
+  cris_break_op,
+  cris_btst_nop_op,
+  cris_clearf_di_op,
+  cris_dip_prefix,
+  cris_dstep_logshift_mstep_neg_not_op,
+  cris_eight_bit_offset_branch_op,
+  cris_move_mem_to_reg_movem_op,
+  cris_move_reg_to_mem_movem_op,
+  cris_move_to_preg_op,
+  cris_muls_op,
+  cris_mulu_op,
+  cris_none_reg_mode_add_sub_cmp_and_or_move_op,
+  cris_none_reg_mode_clear_test_op,
+  cris_none_reg_mode_jump_op,
+  cris_none_reg_mode_move_from_preg_op,
+  cris_quick_mode_add_sub_op,
+  cris_quick_mode_and_cmp_move_or_op,
+  cris_quick_mode_bdap_prefix,
+  cris_reg_mode_add_sub_cmp_and_or_move_op,
+  cris_reg_mode_clear_op,
+  cris_reg_mode_jump_op,
+  cris_reg_mode_move_from_preg_op,
+  cris_reg_mode_test_op,
+  cris_scc_op,
+  cris_sixteen_bit_offset_branch_op,
+  cris_three_operand_add_sub_cmp_and_or_op,
+  cris_three_operand_bound_op,
+  cris_two_operand_bound_op,
+  cris_xor_op
+};
+
+struct cris_opcode
+{
+  /* The name of the insn.  */
+  const char *name;
+
+  /* Bits that must be 1 for a match.  */
+  unsigned int match;
+
+  /* Bits that must be 0 for a match.  */
+  unsigned int lose;
+
+  /* See the table in "opcodes/cris-opc.c".  */
+  const char *args;
+
+  /* Nonzero if this is a delayed branch instruction.  */
+  char delayed;
+
+  /* Size of immediate operands.  */
+  enum cris_imm_oprnd_size_type imm_oprnd_size;
+
+  /* Indicates which version this insn was first implemented in.  */
+  enum cris_insn_version_usage applicable_version;
+
+  /* What kind of operation this is.  */
+  enum cris_op_type op;
+};
+extern const struct cris_opcode cris_opcodes[];
+
+
+/* These macros are for the target-specific flags in disassemble_info
+   used at disassembly.  */
+
+/* This insn accesses memory.  This flag is more trustworthy than
+   checking insn_type for "dis_dref" which does not work for
+   e.g. "JSR [foo]".  */
+#define CRIS_DIS_FLAG_MEMREF (1 << 0)
+
+/* The "target" field holds a register number.  */
+#define CRIS_DIS_FLAG_MEM_TARGET_IS_REG (1 << 1)
+
+/* The "target2" field holds a register number; add it to "target".  */
+#define CRIS_DIS_FLAG_MEM_TARGET2_IS_REG (1 << 2)
+
+/* Yet another add-on: the register in "target2" must be multiplied
+   by 2 before adding to "target".  */
+#define CRIS_DIS_FLAG_MEM_TARGET2_MULT2 (1 << 3)
+
+/* Yet another add-on: the register in "target2" must be multiplied
+   by 4 (mutually exclusive with .._MULT2).  */
+#define CRIS_DIS_FLAG_MEM_TARGET2_MULT4 (1 << 4)
+
+/* The register in "target2" is an indirect memory reference (of the
+   register there), add to "target".  Assumed size is dword (mutually
+   exclusive with .._MULT[24]).  */
+#define CRIS_DIS_FLAG_MEM_TARGET2_MEM (1 << 5)
+
+/* Add-on to CRIS_DIS_FLAG_MEM_TARGET2_MEM; the memory access is "byte";
+   sign-extended before adding to "target".  */
+#define CRIS_DIS_FLAG_MEM_TARGET2_MEM_BYTE (1 << 6)
+
+/* Add-on to CRIS_DIS_FLAG_MEM_TARGET2_MEM; the memory access is "word";
+   sign-extended before adding to "target".  */
+#define CRIS_DIS_FLAG_MEM_TARGET2_MEM_WORD (1 << 7)
+
+#endif /* __CRIS_H_INCLUDED_ */
+
+/*
+ * Local variables:
+ * eval: (c-set-style "gnu")
+ * indent-tabs-mode: t
+ * End:
+ */

Added: trunk/src/host/qemu-neo1973/target-cris/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-cris/translate.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-cris/translate.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,2507 @@
+/*
+ *  CRIS emulation for qemu: main translation routines.
+ *
+ *  Copyright (c) 2007 AXIS Communications AB
+ *  Written by Edgar E. Iglesias.
+ *
+ * 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
+ */
+
+/*
+ * This file implements a CRIS decoder-stage in SW. The decoder translates the
+ * guest (CRIS) machine-code into host machine code via dyngen using the
+ * micro-operations described in op.c
+ *
+ * The micro-operations for CRIS translation implement a RISC style ISA.
+ * Note that the micro-operations typically order their operands
+ * starting with the dst. CRIS asm, does the opposite.
+ *
+ * For example the following CRIS code:
+ * add.d [$r0], $r1
+ *
+ * translates into:
+ *
+ * gen_movl_T0_reg(0);   // Fetch $r0 into T0
+ * gen_load_T0_T0();     // Load T0, @T0
+ * gen_movl_reg_T0(1);   // Writeback T0 into $r1
+ *
+ * The actual names for the micro-code generators vary but the example
+ * illustrates the point.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "disas.h"
+#include "crisv32-decode.h"
+
+#define CRIS_STATS 0
+#if CRIS_STATS
+#define STATS(x) x
+#else
+#define STATS(x)
+#endif
+
+#define DISAS_CRIS 0
+#if DISAS_CRIS
+#define DIS(x) x
+#else
+#define DIS(x)
+#endif
+
+#ifdef USE_DIRECT_JUMP
+#define TBPARAM(x)
+#else
+#define TBPARAM(x) (long)(x)
+#endif
+
+#define BUG() (gen_BUG(dc, __FILE__, __LINE__))
+#define BUG_ON(x) ({if (x) BUG();})
+
+/* Used by the decoder.  */
+#define EXTRACT_FIELD(src, start, end) \
+            (((src) >> start) & ((1 << (end - start + 1)) - 1))
+
+#define CC_MASK_NZ 0xc
+#define CC_MASK_NZV 0xe
+#define CC_MASK_NZVC 0xf
+#define CC_MASK_RNZV 0x10e
+
+static uint16_t *gen_opc_ptr;
+static uint32_t *gen_opparam_ptr;
+
+enum {
+#define DEF(s, n, copy_size) INDEX_op_ ## s,
+#include "opc.h"
+#undef DEF
+    NB_OPS,
+};
+#include "gen-op.h"
+
+/* This is the state at translation time.  */
+typedef struct DisasContext {
+	CPUState *env;
+	target_ulong pc, insn_pc;
+
+	/* Decoder.  */
+	uint32_t ir;
+	uint32_t opcode;
+	unsigned int op1;
+	unsigned int op2;
+	unsigned int zsize, zzsize;
+	unsigned int mode;
+	unsigned int postinc;
+
+
+	struct
+	{
+		int op;
+		int size;
+		unsigned int mask;
+	} cc_state[3];
+	int cc_i;
+
+	int update_cc;
+	int cc_op;
+	int cc_size;
+	uint32_t cc_mask;
+	int flags_live;
+	int flagx_live;
+	int flags_x;
+	uint32_t tb_entry_flags;
+
+	int memidx; /* user or kernel mode.  */
+	int is_jmp;
+	int dyn_jmp;
+
+	uint32_t delayed_pc;
+	int delayed_branch;
+	int bcc;
+	uint32_t condlabel;
+
+	struct TranslationBlock *tb;
+	int singlestep_enabled;
+} DisasContext;
+
+void cris_prepare_jmp (DisasContext *dc, uint32_t dst);
+static void gen_BUG(DisasContext *dc, char *file, int line)
+{
+	printf ("BUG: pc=%x %s %d\n", dc->pc, file, line);
+	fprintf (logfile, "BUG: pc=%x %s %d\n", dc->pc, file, line);
+	cpu_dump_state (dc->env, stdout, fprintf, 0);
+	fflush(NULL);
+	cris_prepare_jmp (dc, 0x70000000 + line);
+}
+
+/* Table to generate quick moves from T0 onto any register.  */
+static GenOpFunc *gen_movl_reg_T0[16] =
+{
+	gen_op_movl_r0_T0, gen_op_movl_r1_T0,
+	gen_op_movl_r2_T0, gen_op_movl_r3_T0,
+	gen_op_movl_r4_T0, gen_op_movl_r5_T0,
+	gen_op_movl_r6_T0, gen_op_movl_r7_T0,
+	gen_op_movl_r8_T0, gen_op_movl_r9_T0,
+	gen_op_movl_r10_T0, gen_op_movl_r11_T0,
+	gen_op_movl_r12_T0, gen_op_movl_r13_T0,
+	gen_op_movl_r14_T0, gen_op_movl_r15_T0,
+};
+static GenOpFunc *gen_movl_T0_reg[16] =
+{
+	gen_op_movl_T0_r0, gen_op_movl_T0_r1,
+	gen_op_movl_T0_r2, gen_op_movl_T0_r3,
+	gen_op_movl_T0_r4, gen_op_movl_T0_r5,
+	gen_op_movl_T0_r6, gen_op_movl_T0_r7,
+	gen_op_movl_T0_r8, gen_op_movl_T0_r9,
+	gen_op_movl_T0_r10, gen_op_movl_T0_r11,
+	gen_op_movl_T0_r12, gen_op_movl_T0_r13,
+	gen_op_movl_T0_r14, gen_op_movl_T0_r15,
+};
+
+static void noop_write(void) {
+	/* nop.  */
+}
+
+static void gen_vr_read(void) {
+	gen_op_movl_T0_im(32);
+}
+
+static void gen_ccs_read(void) {
+	gen_op_movl_T0_p13();
+}
+
+static void gen_ccs_write(void) {
+	gen_op_movl_p13_T0();
+}
+
+/* Table to generate quick moves from T0 onto any register.  */
+static GenOpFunc *gen_movl_preg_T0[16] =
+{
+	noop_write,  /* bz, not writeable.  */
+	noop_write,  /* vr, not writeable.  */
+	gen_op_movl_p2_T0, gen_op_movl_p3_T0,
+	noop_write,  /* wz, not writeable.  */
+	gen_op_movl_p5_T0,
+	gen_op_movl_p6_T0, gen_op_movl_p7_T0,
+	noop_write,  /* dz, not writeable.  */
+	gen_op_movl_p9_T0,
+	gen_op_movl_p10_T0, gen_op_movl_p11_T0,
+	gen_op_movl_p12_T0,
+	gen_ccs_write, /* ccs needs special treatment.  */
+	gen_op_movl_p14_T0, gen_op_movl_p15_T0,
+};
+static GenOpFunc *gen_movl_T0_preg[16] =
+{
+	gen_op_movl_T0_p0,
+	gen_vr_read,
+	gen_op_movl_T0_p2, gen_op_movl_T0_p3,
+	gen_op_movl_T0_p4, gen_op_movl_T0_p5,
+	gen_op_movl_T0_p6, gen_op_movl_T0_p7,
+	gen_op_movl_T0_p8, gen_op_movl_T0_p9,
+	gen_op_movl_T0_p10, gen_op_movl_T0_p11,
+	gen_op_movl_T0_p12,
+	gen_ccs_read, /* ccs needs special treatment.  */
+	gen_op_movl_T0_p14, gen_op_movl_T0_p15,
+};
+
+/* We need this table to handle moves with implicit width.  */
+int preg_sizes[] = {
+	1, /* bz.  */
+	1, /* vr.  */
+	4, /* pid.  */
+	1, /* srs.  */
+	2, /* wz.  */
+	4, 4, 4,
+	4, 4, 4, 4,
+	4, 4, 4, 4,
+};
+
+#ifdef CONFIG_USER_ONLY
+#define GEN_OP_LD(width, reg) \
+  void gen_op_ld##width##_T0_##reg (DisasContext *dc) { \
+    gen_op_ld##width##_T0_##reg##_raw(); \
+  }
+#define GEN_OP_ST(width, reg) \
+  void gen_op_st##width##_##reg##_T1 (DisasContext *dc) { \
+    gen_op_st##width##_##reg##_T1_raw(); \
+  }
+#else
+#define GEN_OP_LD(width, reg) \
+  void gen_op_ld##width##_T0_##reg (DisasContext *dc) { \
+    if (dc->memidx) gen_op_ld##width##_T0_##reg##_kernel(); \
+    else gen_op_ld##width##_T0_##reg##_user();\
+  }
+#define GEN_OP_ST(width, reg) \
+  void gen_op_st##width##_##reg##_T1 (DisasContext *dc) { \
+    if (dc->memidx) gen_op_st##width##_##reg##_T1_kernel(); \
+    else gen_op_st##width##_##reg##_T1_user();\
+  }
+#endif
+
+GEN_OP_LD(ub, T0)
+GEN_OP_LD(b, T0)
+GEN_OP_ST(b, T0)
+GEN_OP_LD(uw, T0)
+GEN_OP_LD(w, T0)
+GEN_OP_ST(w, T0)
+GEN_OP_LD(l, T0)
+GEN_OP_ST(l, T0)
+
+static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
+{
+	TranslationBlock *tb;
+	tb = dc->tb;
+	if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
+		if (n == 0)
+			gen_op_goto_tb0(TBPARAM(tb));
+		else
+			gen_op_goto_tb1(TBPARAM(tb));
+		gen_op_movl_T0_0();
+	} else {
+		gen_op_movl_T0_0();
+	}
+	gen_op_exit_tb();
+}
+
+/* Sign extend at translation time.  */
+static int sign_extend(unsigned int val, unsigned int width)
+{
+	int sval;
+
+	/* LSL.  */
+	val <<= 31 - width;
+	sval = val;
+	/* ASR.  */
+	sval >>= 31 - width;
+	return sval;
+}
+
+static void cris_evaluate_flags(DisasContext *dc)
+{
+	if (!dc->flags_live) {
+
+		switch (dc->cc_op)
+		{
+			case CC_OP_MCP:
+				gen_op_evaluate_flags_mcp ();
+				break;
+			case CC_OP_MULS:
+				gen_op_evaluate_flags_muls ();
+				break;
+			case CC_OP_MULU:
+				gen_op_evaluate_flags_mulu ();
+				break;
+			case CC_OP_MOVE:
+				switch (dc->cc_size)
+				{
+					case 4:
+						gen_op_evaluate_flags_move_4();
+						break;
+					case 2:
+						gen_op_evaluate_flags_move_2();
+						break;
+					default:
+						gen_op_evaluate_flags ();
+						break;
+				}
+				break;
+
+			default:
+			{
+				switch (dc->cc_size)
+				{
+					case 4:
+						gen_op_evaluate_flags_alu_4 ();
+						break;
+					default:
+						gen_op_evaluate_flags ();
+						break;
+				}
+			}
+			break;
+		}
+		dc->flags_live = 1;
+	}
+}
+
+static void cris_cc_mask(DisasContext *dc, unsigned int mask)
+{
+	uint32_t ovl;
+
+	ovl = (dc->cc_mask ^ mask) & ~mask;
+	if (ovl) {
+		/* TODO: optimize this case. It trigs all the time.  */
+		cris_evaluate_flags (dc);
+	}
+	dc->cc_mask = mask;
+
+	dc->update_cc = 1;
+	if (mask == 0)
+		dc->update_cc = 0;
+	else {
+		gen_op_update_cc_mask(mask);
+		dc->flags_live = 0;
+	}
+}
+
+static void cris_update_cc_op(DisasContext *dc, int op)
+{
+	dc->cc_op = op;
+	gen_op_update_cc_op(op);
+	dc->flags_live = 0;
+}
+static void cris_update_cc_size(DisasContext *dc, int size)
+{
+	dc->cc_size = size;
+	gen_op_update_cc_size_im(size);
+}
+
+/* op is the operation.
+   T0, T1 are the operands.
+   dst is the destination reg.
+*/
+static void crisv32_alu_op(DisasContext *dc, int op, int rd, int size)
+{
+	int writeback = 1;
+	if (dc->update_cc) {
+		cris_update_cc_op(dc, op);
+		cris_update_cc_size(dc, size);
+		gen_op_update_cc_x(dc->flagx_live, dc->flags_x);
+		gen_op_update_cc_dest_T0();
+	}
+
+	/* Emit the ALU insns.  */
+	switch (op)
+	{
+		case CC_OP_ADD:
+			gen_op_addl_T0_T1();
+			/* Extended arithmetics.  */
+			if (!dc->flagx_live)
+				gen_op_addxl_T0_C();
+			else if (dc->flags_x)
+				gen_op_addxl_T0_C();
+			break;
+		case CC_OP_ADDC:
+			gen_op_addl_T0_T1();
+			gen_op_addl_T0_C();
+			break;
+		case CC_OP_MCP:
+			gen_op_addl_T0_T1();
+			gen_op_addl_T0_R();
+			break;
+		case CC_OP_SUB:
+			gen_op_negl_T1_T1();
+			gen_op_addl_T0_T1();
+			/* CRIS flag evaluation needs ~src.  */
+			gen_op_negl_T1_T1();
+			gen_op_not_T1_T1();
+
+			/* Extended arithmetics.  */
+			if (!dc->flagx_live)
+				gen_op_subxl_T0_C();
+			else if (dc->flags_x)
+				gen_op_subxl_T0_C();
+			break;
+		case CC_OP_MOVE:
+			gen_op_movl_T0_T1();
+			break;
+		case CC_OP_OR:
+			gen_op_orl_T0_T1();
+			break;
+		case CC_OP_AND:
+			gen_op_andl_T0_T1();
+			break;
+		case CC_OP_XOR:
+			gen_op_xorl_T0_T1();
+			break;
+		case CC_OP_LSL:
+			gen_op_lsll_T0_T1();
+			break;
+		case CC_OP_LSR:
+			gen_op_lsrl_T0_T1();
+			break;
+		case CC_OP_ASR:
+			gen_op_asrl_T0_T1();
+			break;
+		case CC_OP_NEG:
+			gen_op_negl_T0_T1();
+			/* Extended arithmetics.  */
+			gen_op_subxl_T0_C();
+			break;
+		case CC_OP_LZ:
+			gen_op_lz_T0_T1();
+			break;
+		case CC_OP_BTST:
+			gen_op_btst_T0_T1();
+			writeback = 0;
+			break;
+		case CC_OP_MULS:
+			gen_op_muls_T0_T1();
+			break;
+		case CC_OP_MULU:
+			gen_op_mulu_T0_T1();
+			break;
+		case CC_OP_DSTEP:
+			gen_op_dstep_T0_T1();
+			break;
+		case CC_OP_BOUND:
+			gen_op_bound_T0_T1();
+			break;
+		case CC_OP_CMP:
+			gen_op_negl_T1_T1();
+			gen_op_addl_T0_T1();
+			/* CRIS flag evaluation needs ~src.  */
+			gen_op_negl_T1_T1();
+			gen_op_not_T1_T1();
+
+			/* Extended arithmetics.  */
+			gen_op_subxl_T0_C();
+			writeback = 0;
+			break;
+		default:
+			fprintf (logfile, "illegal ALU op.\n");
+			BUG();
+			break;
+	}
+
+	if (dc->update_cc)
+		gen_op_update_cc_src_T1();
+
+	if (size == 1)
+		gen_op_andl_T0_im(0xff);
+	else if (size == 2)
+		gen_op_andl_T0_im(0xffff);
+	/* Writeback.  */
+	if (writeback) {
+		if (size == 4)
+			gen_movl_reg_T0[rd]();
+		else {
+			gen_op_movl_T1_T0();
+			gen_movl_T0_reg[rd]();
+			if (size == 1)
+				gen_op_andl_T0_im(~0xff);
+			else
+				gen_op_andl_T0_im(~0xffff);
+			gen_op_orl_T0_T1();
+			gen_movl_reg_T0[rd]();
+			gen_op_movl_T0_T1();
+		}
+	}
+	if (dc->update_cc)
+		gen_op_update_cc_result_T0();
+
+	{
+		/* TODO: Optimize this.  */
+		if (!dc->flagx_live)
+			cris_evaluate_flags(dc);
+	}
+}
+
+static int arith_cc(DisasContext *dc)
+{
+	if (dc->update_cc) {
+		switch (dc->cc_op) {
+			case CC_OP_ADD: return 1;
+			case CC_OP_SUB: return 1;
+			case CC_OP_LSL: return 1;
+			case CC_OP_LSR: return 1;
+			case CC_OP_ASR: return 1;
+			case CC_OP_CMP: return 1;
+			default:
+				return 0;
+		}
+	}
+	return 0;
+}
+
+static void gen_tst_cc (DisasContext *dc, int cond)
+{
+	int arith_opt;
+
+	/* TODO: optimize more condition codes.  */
+	arith_opt = arith_cc(dc) && !dc->flags_live;
+	switch (cond) {
+		case CC_EQ:
+			if (arith_opt)
+				gen_op_tst_cc_eq_fast ();
+			else {
+				cris_evaluate_flags(dc);
+				gen_op_tst_cc_eq ();
+			}
+			break;
+		case CC_NE:
+			if (arith_opt)
+				gen_op_tst_cc_ne_fast ();
+			else {
+				cris_evaluate_flags(dc);
+				gen_op_tst_cc_ne ();
+			}
+			break;
+		case CC_CS:
+			cris_evaluate_flags(dc);
+			gen_op_tst_cc_cs ();
+			break;
+		case CC_CC:
+			cris_evaluate_flags(dc);
+			gen_op_tst_cc_cc ();
+			break;
+		case CC_VS:
+			cris_evaluate_flags(dc);
+			gen_op_tst_cc_vs ();
+			break;
+		case CC_VC:
+			cris_evaluate_flags(dc);
+			gen_op_tst_cc_vc ();
+			break;
+		case CC_PL:
+			if (arith_opt)
+				gen_op_tst_cc_pl_fast ();
+			else {
+				cris_evaluate_flags(dc);
+				gen_op_tst_cc_pl ();
+			}
+			break;
+		case CC_MI:
+			if (arith_opt)
+				gen_op_tst_cc_mi_fast ();
+			else {
+				cris_evaluate_flags(dc);
+				gen_op_tst_cc_mi ();
+			}
+			break;
+		case CC_LS:
+			cris_evaluate_flags(dc);
+			gen_op_tst_cc_ls ();
+			break;
+		case CC_HI:
+			cris_evaluate_flags(dc);
+			gen_op_tst_cc_hi ();
+			break;
+		case CC_GE:
+			cris_evaluate_flags(dc);
+			gen_op_tst_cc_ge ();
+			break;
+		case CC_LT:
+			cris_evaluate_flags(dc);
+			gen_op_tst_cc_lt ();
+			break;
+		case CC_GT:
+			cris_evaluate_flags(dc);
+			gen_op_tst_cc_gt ();
+			break;
+		case CC_LE:
+			cris_evaluate_flags(dc);
+			gen_op_tst_cc_le ();
+			break;
+		case CC_P:
+			cris_evaluate_flags(dc);
+			gen_op_tst_cc_p ();
+			break;
+		case CC_A:
+			cris_evaluate_flags(dc);
+			gen_op_movl_T0_im (1);
+			break;
+		default:
+			BUG();
+			break;
+	};
+}
+
+static void cris_prepare_cc_branch (DisasContext *dc, int offset, int cond)
+{
+	/* This helps us re-schedule the micro-code to insns in delay-slots
+	   before the actual jump.  */
+	dc->delayed_branch = 2;
+	dc->delayed_pc = dc->pc + offset;
+	dc->bcc = cond;
+	if (cond != CC_A)
+	{
+		gen_tst_cc (dc, cond);
+		gen_op_evaluate_bcc ();
+	}
+	gen_op_movl_T0_im (dc->delayed_pc);
+	gen_op_movl_btarget_T0 ();
+}
+
+/* Dynamic jumps, when the dest is in a live reg for example.  */
+void cris_prepare_dyn_jmp (DisasContext *dc)
+{
+	/* This helps us re-schedule the micro-code to insns in delay-slots
+	   before the actual jump.  */
+	dc->delayed_branch = 2;
+	dc->dyn_jmp = 1;
+	dc->bcc = CC_A;
+}
+
+void cris_prepare_jmp (DisasContext *dc, uint32_t dst)
+{
+	/* This helps us re-schedule the micro-code to insns in delay-slots
+	   before the actual jump.  */
+	dc->delayed_branch = 2;
+	dc->delayed_pc = dst;
+	dc->dyn_jmp = 0;
+	dc->bcc = CC_A;
+}
+
+void gen_load_T0_T0 (DisasContext *dc, unsigned int size, int sign)
+{
+	if (size == 1) {
+		if (sign)
+			gen_op_ldb_T0_T0(dc);
+		else
+			gen_op_ldub_T0_T0(dc);
+	}
+	else if (size == 2) {
+		if (sign)
+			gen_op_ldw_T0_T0(dc);
+		else
+			gen_op_lduw_T0_T0(dc);
+	}
+	else {
+		gen_op_ldl_T0_T0(dc);
+	}
+}
+
+void gen_store_T0_T1 (DisasContext *dc, unsigned int size)
+{
+	/* Remember, operands are flipped. CRIS has reversed order.  */
+	if (size == 1) {
+		gen_op_stb_T0_T1(dc);
+	}
+	else if (size == 2) {
+		gen_op_stw_T0_T1(dc);
+	}
+	else
+		gen_op_stl_T0_T1(dc);
+}
+
+/* sign extend T1 according to size.  */
+static void gen_sext_T1_T0(int size)
+{
+	if (size == 1)
+		gen_op_extb_T1_T0();
+	else if (size == 2)
+		gen_op_extw_T1_T0();
+}
+
+static void gen_sext_T1_T1(int size)
+{
+	if (size == 1)
+		gen_op_extb_T1_T1();
+	else if (size == 2)
+		gen_op_extw_T1_T1();
+}
+
+static void gen_sext_T0_T0(int size)
+{
+	if (size == 1)
+		gen_op_extb_T0_T0();
+	else if (size == 2)
+		gen_op_extw_T0_T0();
+}
+
+static void gen_zext_T0_T0(int size)
+{
+	if (size == 1)
+		gen_op_zextb_T0_T0();
+	else if (size == 2)
+		gen_op_zextw_T0_T0();
+}
+
+static void gen_zext_T1_T0(int size)
+{
+	if (size == 1)
+		gen_op_zextb_T1_T0();
+	else if (size == 2)
+		gen_op_zextw_T1_T0();
+}
+
+static void gen_zext_T1_T1(int size)
+{
+	if (size == 1)
+		gen_op_zextb_T1_T1();
+	else if (size == 2)
+		gen_op_zextw_T1_T1();
+}
+
+#if DISAS_CRIS
+static char memsize_char(int size)
+{
+	switch (size)
+	{
+		case 1: return 'b';  break;
+		case 2: return 'w';  break;
+		case 4: return 'd';  break;
+		default:
+			return 'x';
+			break;
+	}
+}
+#endif
+
+static unsigned int memsize_z(DisasContext *dc)
+{
+	return dc->zsize + 1;
+}
+
+static unsigned int memsize_zz(DisasContext *dc)
+{
+	switch (dc->zzsize)
+	{
+		case 0: return 1;
+		case 1: return 2;
+		default:
+			return 4;
+	}
+}
+
+static void do_postinc (DisasContext *dc, int size)
+{
+	if (!dc->postinc)
+		return;
+	gen_movl_T0_reg[dc->op1]();
+	gen_op_addl_T0_im(size);
+	gen_movl_reg_T0[dc->op1]();
+}
+
+
+static void dec_prep_move_r(DisasContext *dc, int rs, int rd,
+			    int size, int s_ext)
+{
+	gen_movl_T0_reg[rs]();
+	gen_op_movl_T1_T0();
+	if (s_ext)
+		gen_sext_T1_T1(size);
+	else
+		gen_zext_T1_T1(size);
+}
+
+/* Prepare T0 and T1 for a register alu operation.
+   s_ext decides if the operand1 should be sign-extended or zero-extended when
+   needed.  */
+static void dec_prep_alu_r(DisasContext *dc, int rs, int rd,
+			  int size, int s_ext)
+{
+	dec_prep_move_r(dc, rs, rd, size, s_ext);
+
+	gen_movl_T0_reg[rd]();
+	if (s_ext)
+		gen_sext_T0_T0(size);
+	else
+		gen_zext_T0_T0(size);
+}
+
+/* Prepare T0 and T1 for a memory + alu operation.
+   s_ext decides if the operand1 should be sign-extended or zero-extended when
+   needed.  */
+static int dec_prep_alu_m(DisasContext *dc, int s_ext, int memsize)
+{
+	unsigned int rs, rd;
+	uint32_t imm;
+	int is_imm;
+	int insn_len = 2;
+
+	rs = dc->op1;
+	rd = dc->op2;
+	is_imm = rs == 15 && dc->postinc;
+
+	/* Load [$rs] onto T1.  */
+	if (is_imm) {
+		insn_len = 2 + memsize;
+		if (memsize == 1)
+			insn_len++;
+
+		imm = ldl_code(dc->pc + 2);
+		if (memsize != 4) {
+			if (s_ext) {
+				imm = sign_extend(imm, (memsize * 8) - 1);
+			} else {
+				if (memsize == 1)
+					imm &= 0xff;
+				else
+					imm &= 0xffff;
+			}
+		}
+		DIS(fprintf (logfile, "imm=%x rd=%d sext=%d ms=%d\n",
+			    imm, rd, s_ext, memsize));
+		gen_op_movl_T1_im (imm);
+		dc->postinc = 0;
+	} else {
+		gen_movl_T0_reg[rs]();
+		gen_load_T0_T0(dc, memsize, 0);
+		gen_op_movl_T1_T0();
+		if (s_ext)
+			gen_sext_T1_T1(memsize);
+		else
+			gen_zext_T1_T1(memsize);
+	}
+
+	/* put dest in T0.  */
+	gen_movl_T0_reg[rd]();
+	return insn_len;
+}
+
+#if DISAS_CRIS
+static const char *cc_name(int cc)
+{
+	static char *cc_names[16] = {
+		"cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi",
+		"ls", "hi", "ge", "lt", "gt", "le", "a", "p"
+	};
+	assert(cc < 16);
+	return cc_names[cc];
+}
+#endif
+
+static unsigned int dec_bccq(DisasContext *dc)
+{
+	int32_t offset;
+	int sign;
+	uint32_t cond = dc->op2;
+	int tmp;
+
+	offset = EXTRACT_FIELD (dc->ir, 1, 7);
+	sign = EXTRACT_FIELD(dc->ir, 0, 0);
+
+	offset *= 2;
+	offset |= sign << 8;
+	tmp = offset;
+	offset = sign_extend(offset, 8);
+
+	/* op2 holds the condition-code.  */
+	cris_cc_mask(dc, 0);
+	cris_prepare_cc_branch (dc, offset, cond);
+	return 2;
+}
+static unsigned int dec_addoq(DisasContext *dc)
+{
+	uint32_t imm;
+
+	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7);
+	imm = sign_extend(dc->op1, 7);
+
+	DIS(fprintf (logfile, "addoq %d, $r%u\n", imm, dc->op2));
+	cris_cc_mask(dc, 0);
+	/* Fetch register operand,  */
+	gen_movl_T0_reg[dc->op2]();
+	gen_op_movl_T1_im(imm);
+	crisv32_alu_op(dc, CC_OP_ADD, REG_ACR, 4);
+	return 2;
+}
+static unsigned int dec_addq(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "addq %u, $r%u\n", dc->op1, dc->op2));
+
+	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
+
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	/* Fetch register operand,  */
+	gen_movl_T0_reg[dc->op2]();
+	gen_op_movl_T1_im(dc->op1);
+	crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
+	return 2;
+}
+static unsigned int dec_moveq(DisasContext *dc)
+{
+	uint32_t imm;
+
+	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
+	imm = sign_extend(dc->op1, 5);
+	DIS(fprintf (logfile, "moveq %d, $r%u\n", imm, dc->op2));
+
+	cris_cc_mask(dc, 0);
+	gen_op_movl_T1_im(imm);
+	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+
+	return 2;
+}
+static unsigned int dec_subq(DisasContext *dc)
+{
+	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
+
+	DIS(fprintf (logfile, "subq %u, $r%u\n", dc->op1, dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	/* Fetch register operand,  */
+	gen_movl_T0_reg[dc->op2]();
+	gen_op_movl_T1_im(dc->op1);
+	crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
+	return 2;
+}
+static unsigned int dec_cmpq(DisasContext *dc)
+{
+	uint32_t imm;
+	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
+	imm = sign_extend(dc->op1, 5);
+
+	DIS(fprintf (logfile, "cmpq %d, $r%d\n", imm, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	gen_movl_T0_reg[dc->op2]();
+	gen_op_movl_T1_im(imm);
+	crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4);
+	return 2;
+}
+static unsigned int dec_andq(DisasContext *dc)
+{
+	uint32_t imm;
+	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
+	imm = sign_extend(dc->op1, 5);
+
+	DIS(fprintf (logfile, "andq %d, $r%d\n", imm, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZ);
+	gen_movl_T0_reg[dc->op2]();
+	gen_op_movl_T1_im(imm);
+	crisv32_alu_op(dc, CC_OP_AND, dc->op2, 4);
+	return 2;
+}
+static unsigned int dec_orq(DisasContext *dc)
+{
+	uint32_t imm;
+	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
+	imm = sign_extend(dc->op1, 5);
+	DIS(fprintf (logfile, "orq %d, $r%d\n", imm, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZ);
+	gen_movl_T0_reg[dc->op2]();
+	gen_op_movl_T1_im(imm);
+	crisv32_alu_op(dc, CC_OP_OR, dc->op2, 4);
+	return 2;
+}
+static unsigned int dec_btstq(DisasContext *dc)
+{
+	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
+	DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2));
+	cris_evaluate_flags(dc);
+	cris_cc_mask(dc, CC_MASK_NZ);
+	gen_movl_T0_reg[dc->op2]();
+	gen_op_movl_T1_im(dc->op1);
+	crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
+
+	cris_update_cc_op(dc, CC_OP_FLAGS);
+	gen_op_movl_flags_T0();
+	dc->flags_live = 1;
+	return 2;
+}
+static unsigned int dec_asrq(DisasContext *dc)
+{
+	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
+	DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZ);
+	gen_movl_T0_reg[dc->op2]();
+	gen_op_movl_T1_im(dc->op1);
+	crisv32_alu_op(dc, CC_OP_ASR, dc->op2, 4);
+	return 2;
+}
+static unsigned int dec_lslq(DisasContext *dc)
+{
+	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
+	DIS(fprintf (logfile, "lslq %u, $r%d\n", dc->op1, dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZ);
+	gen_movl_T0_reg[dc->op2]();
+	gen_op_movl_T1_im(dc->op1);
+	crisv32_alu_op(dc, CC_OP_LSL, dc->op2, 4);
+	return 2;
+}
+static unsigned int dec_lsrq(DisasContext *dc)
+{
+	dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
+	DIS(fprintf (logfile, "lsrq %u, $r%d\n", dc->op1, dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZ);
+	gen_movl_T0_reg[dc->op2]();
+	gen_op_movl_T1_im(dc->op1);
+	crisv32_alu_op(dc, CC_OP_LSR, dc->op2, 4);
+	return 2;
+}
+
+static unsigned int dec_move_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+
+	DIS(fprintf (logfile, "move.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZ);
+	dec_prep_move_r(dc, dc->op1, dc->op2, size, 0);
+	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, size);
+	return 2;
+}
+
+static unsigned int dec_scc_r(DisasContext *dc)
+{
+	int cond = dc->op2;
+
+	DIS(fprintf (logfile, "s%s $r%u\n",
+		    cc_name(cond), dc->op1));
+
+	if (cond != CC_A)
+	{
+		gen_tst_cc (dc, cond);
+		gen_op_movl_T1_T0();
+	}
+	else
+		gen_op_movl_T1_im(1);
+
+	cris_cc_mask(dc, 0);
+	crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
+	return 2;
+}
+
+static unsigned int dec_and_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+
+	DIS(fprintf (logfile, "and.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZ);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
+	crisv32_alu_op(dc, CC_OP_AND, dc->op2, size);
+	return 2;
+}
+
+static unsigned int dec_lz_r(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "lz $r%u, $r%u\n",
+		    dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZ);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
+	crisv32_alu_op(dc, CC_OP_LZ, dc->op2, 4);
+	return 2;
+}
+
+static unsigned int dec_lsl_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+
+	DIS(fprintf (logfile, "lsl.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZ);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
+	gen_op_andl_T1_im(63);
+	crisv32_alu_op(dc, CC_OP_LSL, dc->op2, size);
+	return 2;
+}
+
+static unsigned int dec_lsr_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+
+	DIS(fprintf (logfile, "lsr.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZ);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
+	gen_op_andl_T1_im(63);
+	crisv32_alu_op(dc, CC_OP_LSR, dc->op2, size);
+	return 2;
+}
+
+static unsigned int dec_asr_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+
+	DIS(fprintf (logfile, "asr.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZ);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1);
+	gen_op_andl_T1_im(63);
+	crisv32_alu_op(dc, CC_OP_ASR, dc->op2, size);
+	return 2;
+}
+
+static unsigned int dec_muls_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+
+	DIS(fprintf (logfile, "muls.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZV);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1);
+	gen_sext_T0_T0(size);
+	crisv32_alu_op(dc, CC_OP_MULS, dc->op2, 4);
+	return 2;
+}
+
+static unsigned int dec_mulu_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+
+	DIS(fprintf (logfile, "mulu.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZV);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
+	gen_zext_T0_T0(size);
+	crisv32_alu_op(dc, CC_OP_MULU, dc->op2, 4);
+	return 2;
+}
+
+
+static unsigned int dec_dstep_r(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "dstep $r%u, $r%u\n", dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZ);
+	gen_movl_T0_reg[dc->op1]();
+	gen_op_movl_T1_T0();
+	gen_movl_T0_reg[dc->op2]();
+	crisv32_alu_op(dc, CC_OP_DSTEP, dc->op2, 4);
+	return 2;
+}
+
+static unsigned int dec_xor_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+	DIS(fprintf (logfile, "xor.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+	BUG_ON(size != 4); /* xor is dword.  */
+	cris_cc_mask(dc, CC_MASK_NZ);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
+	crisv32_alu_op(dc, CC_OP_XOR, dc->op2, 4);
+	return 2;
+}
+
+static unsigned int dec_bound_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+	DIS(fprintf (logfile, "bound.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZ);
+	/* TODO: needs optmimization.  */
+	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
+	/* rd should be 4.  */
+	gen_movl_T0_reg[dc->op2]();
+	crisv32_alu_op(dc, CC_OP_BOUND, dc->op2, 4);
+	return 2;
+}
+
+static unsigned int dec_cmp_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+	DIS(fprintf (logfile, "cmp.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
+	crisv32_alu_op(dc, CC_OP_CMP, dc->op2, size);
+	return 2;
+}
+
+static unsigned int dec_abs_r(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "abs $r%u, $r%u\n",
+		    dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZ);
+	dec_prep_move_r(dc, dc->op1, dc->op2, 4, 0);
+	gen_op_absl_T1_T1();
+	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+	return 2;
+}
+
+static unsigned int dec_add_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+	DIS(fprintf (logfile, "add.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
+	crisv32_alu_op(dc, CC_OP_ADD, dc->op2, size);
+	return 2;
+}
+
+static unsigned int dec_addc_r(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "addc $r%u, $r%u\n",
+		    dc->op1, dc->op2));
+	cris_evaluate_flags(dc);
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
+	crisv32_alu_op(dc, CC_OP_ADDC, dc->op2, 4);
+	return 2;
+}
+
+static unsigned int dec_mcp_r(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "mcp $p%u, $r%u\n",
+		     dc->op2, dc->op1));
+	cris_evaluate_flags(dc);
+	cris_cc_mask(dc, CC_MASK_RNZV);
+	gen_movl_T0_preg[dc->op2]();
+	gen_op_movl_T1_T0();
+	gen_movl_T0_reg[dc->op1]();
+	crisv32_alu_op(dc, CC_OP_MCP, dc->op1, 4);
+	return 2;
+}
+
+#if DISAS_CRIS
+static char * swapmode_name(int mode, char *modename) {
+	int i = 0;
+	if (mode & 8)
+		modename[i++] = 'n';
+	if (mode & 4)
+		modename[i++] = 'w';
+	if (mode & 2)
+		modename[i++] = 'b';
+	if (mode & 1)
+		modename[i++] = 'r';
+	modename[i++] = 0;
+	return modename;
+}
+#endif
+
+static unsigned int dec_swap_r(DisasContext *dc)
+{
+	DIS(char modename[4]);
+	DIS(fprintf (logfile, "swap%s $r%u\n",
+		     swapmode_name(dc->op2, modename), dc->op1));
+
+	cris_cc_mask(dc, CC_MASK_NZ);
+	gen_movl_T0_reg[dc->op1]();
+	if (dc->op2 & 8)
+		gen_op_not_T0_T0();
+	if (dc->op2 & 4)
+		gen_op_swapw_T0_T0();
+	if (dc->op2 & 2)
+		gen_op_swapb_T0_T0();
+	if (dc->op2 & 1)
+		gen_op_swapr_T0_T0();
+	gen_op_movl_T1_T0();
+	crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4);
+	return 2;
+}
+
+static unsigned int dec_or_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+	DIS(fprintf (logfile, "or.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZ);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
+	crisv32_alu_op(dc, CC_OP_OR, dc->op2, size);
+	return 2;
+}
+
+static unsigned int dec_addi_r(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "addi.%c $r%u, $r%u\n",
+		    memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
+	cris_cc_mask(dc, 0);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
+	gen_op_lsll_T0_im(dc->zzsize);
+	gen_op_addl_T0_T1();
+	gen_movl_reg_T0[dc->op1]();
+	return 2;
+}
+
+static unsigned int dec_addi_acr(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "addi.%c $r%u, $r%u, $acr\n",
+		    memsize_char(memsize_zz(dc)), dc->op2, dc->op1));
+	cris_cc_mask(dc, 0);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
+	gen_op_lsll_T0_im(dc->zzsize);
+	gen_op_addl_T0_T1();
+	gen_movl_reg_T0[REG_ACR]();
+	return 2;
+}
+
+static unsigned int dec_neg_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+	DIS(fprintf (logfile, "neg.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
+	crisv32_alu_op(dc, CC_OP_NEG, dc->op2, size);
+	return 2;
+}
+
+static unsigned int dec_btst_r(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "btst $r%u, $r%u\n",
+		    dc->op1, dc->op2));
+	cris_evaluate_flags(dc);
+	cris_cc_mask(dc, CC_MASK_NZ);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0);
+	crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4);
+
+	cris_update_cc_op(dc, CC_OP_FLAGS);
+	gen_op_movl_flags_T0();
+	dc->flags_live = 1;
+	return 2;
+}
+
+static unsigned int dec_sub_r(DisasContext *dc)
+{
+	int size = memsize_zz(dc);
+	DIS(fprintf (logfile, "sub.%c $r%u, $r%u\n",
+		    memsize_char(size), dc->op1, dc->op2));
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0);
+	crisv32_alu_op(dc, CC_OP_SUB, dc->op2, size);
+	return 2;
+}
+
+/* Zero extension. From size to dword.  */
+static unsigned int dec_movu_r(DisasContext *dc)
+{
+	int size = memsize_z(dc);
+	DIS(fprintf (logfile, "movu.%c $r%u, $r%u\n",
+		    memsize_char(size),
+		    dc->op1, dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZ);
+	dec_prep_move_r(dc, dc->op1, dc->op2, size, 0);
+	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+	return 2;
+}
+
+/* Sign extension. From size to dword.  */
+static unsigned int dec_movs_r(DisasContext *dc)
+{
+	int size = memsize_z(dc);
+	DIS(fprintf (logfile, "movs.%c $r%u, $r%u\n",
+		    memsize_char(size),
+		    dc->op1, dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZ);
+	gen_movl_T0_reg[dc->op1]();
+	/* Size can only be qi or hi.  */
+	gen_sext_T1_T0(size);
+	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+	return 2;
+}
+
+/* zero extension. From size to dword.  */
+static unsigned int dec_addu_r(DisasContext *dc)
+{
+	int size = memsize_z(dc);
+	DIS(fprintf (logfile, "addu.%c $r%u, $r%u\n",
+		    memsize_char(size),
+		    dc->op1, dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	gen_movl_T0_reg[dc->op1]();
+	/* Size can only be qi or hi.  */
+	gen_zext_T1_T0(size);
+	gen_movl_T0_reg[dc->op2]();
+	crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
+	return 2;
+}
+/* Sign extension. From size to dword.  */
+static unsigned int dec_adds_r(DisasContext *dc)
+{
+	int size = memsize_z(dc);
+	DIS(fprintf (logfile, "adds.%c $r%u, $r%u\n",
+		    memsize_char(size),
+		    dc->op1, dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	gen_movl_T0_reg[dc->op1]();
+	/* Size can only be qi or hi.  */
+	gen_sext_T1_T0(size);
+	gen_movl_T0_reg[dc->op2]();
+	crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
+	return 2;
+}
+
+/* Zero extension. From size to dword.  */
+static unsigned int dec_subu_r(DisasContext *dc)
+{
+	int size = memsize_z(dc);
+	DIS(fprintf (logfile, "subu.%c $r%u, $r%u\n",
+		    memsize_char(size),
+		    dc->op1, dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	gen_movl_T0_reg[dc->op1]();
+	/* Size can only be qi or hi.  */
+	gen_zext_T1_T0(size);
+	gen_movl_T0_reg[dc->op2]();
+	crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
+	return 2;
+}
+
+/* Sign extension. From size to dword.  */
+static unsigned int dec_subs_r(DisasContext *dc)
+{
+	int size = memsize_z(dc);
+	DIS(fprintf (logfile, "subs.%c $r%u, $r%u\n",
+		    memsize_char(size),
+		    dc->op1, dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	gen_movl_T0_reg[dc->op1]();
+	/* Size can only be qi or hi.  */
+	gen_sext_T1_T0(size);
+	gen_movl_T0_reg[dc->op2]();
+	crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
+	return 2;
+}
+
+static unsigned int dec_setclrf(DisasContext *dc)
+{
+	uint32_t flags;
+	int set = (~dc->opcode >> 2) & 1;
+
+	flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4)
+		| EXTRACT_FIELD(dc->ir, 0, 3);
+	DIS(fprintf (logfile, "set=%d flags=%x\n", set, flags));
+	if (set && flags == 0)
+		DIS(fprintf (logfile, "nop\n"));
+	else if (!set && (flags & 0x20))
+		DIS(fprintf (logfile, "di\n"));
+	else
+		DIS(fprintf (logfile, "%sf %x\n",
+			    set ? "set" : "clr",
+			    flags));
+
+	if (set && (flags & X_FLAG)) {
+		dc->flagx_live = 1;
+		dc->flags_x = 1;
+	}
+
+	/* Simply decode the flags.  */
+	cris_evaluate_flags (dc);
+	cris_update_cc_op(dc, CC_OP_FLAGS);
+	if (set)
+		gen_op_setf (flags);
+	else
+		gen_op_clrf (flags);
+	dc->flags_live = 1;
+	return 2;
+}
+
+static unsigned int dec_move_rs(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "move $r%u, $s%u\n", dc->op1, dc->op2));
+	cris_cc_mask(dc, 0);
+	gen_movl_T0_reg[dc->op1]();
+	gen_op_movl_sreg_T0(dc->op2);
+
+	if (dc->op2 == 5) /* srs is checked at runtime.  */
+		gen_op_movl_tlb_lo_T0();
+	return 2;
+}
+static unsigned int dec_move_sr(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "move $s%u, $r%u\n", dc->op1, dc->op2));
+	cris_cc_mask(dc, 0);
+	gen_op_movl_T0_sreg(dc->op1);
+	gen_op_movl_T1_T0();
+	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+	return 2;
+}
+static unsigned int dec_move_rp(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "move $r%u, $p%u\n", dc->op1, dc->op2));
+	cris_cc_mask(dc, 0);
+	gen_movl_T0_reg[dc->op1]();
+	gen_op_movl_T1_T0();
+	gen_movl_preg_T0[dc->op2]();
+	return 2;
+}
+static unsigned int dec_move_pr(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "move $p%u, $r%u\n", dc->op1, dc->op2));
+	cris_cc_mask(dc, 0);
+	gen_movl_T0_preg[dc->op2]();
+	gen_op_movl_T1_T0();
+	crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, preg_sizes[dc->op2]);
+	return 2;
+}
+
+static unsigned int dec_move_mr(DisasContext *dc)
+{
+	int memsize = memsize_zz(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "move.%c [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZ);
+	insn_len = dec_prep_alu_m(dc, 0, memsize);
+	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, memsize);
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_movs_m(DisasContext *dc)
+{
+	int memsize = memsize_z(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "movs.%c [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	/* sign extend.  */
+	cris_cc_mask(dc, CC_MASK_NZ);
+	insn_len = dec_prep_alu_m(dc, 1, memsize);
+	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_addu_m(DisasContext *dc)
+{
+	int memsize = memsize_z(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "addu.%c [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	/* sign extend.  */
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	insn_len = dec_prep_alu_m(dc, 0, memsize);
+	crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_adds_m(DisasContext *dc)
+{
+	int memsize = memsize_z(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "adds.%c [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	/* sign extend.  */
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	insn_len = dec_prep_alu_m(dc, 1, memsize);
+	crisv32_alu_op(dc, CC_OP_ADD, dc->op2, 4);
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_subu_m(DisasContext *dc)
+{
+	int memsize = memsize_z(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "subu.%c [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	/* sign extend.  */
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	insn_len = dec_prep_alu_m(dc, 0, memsize);
+	crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_subs_m(DisasContext *dc)
+{
+	int memsize = memsize_z(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "subs.%c [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	/* sign extend.  */
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	insn_len = dec_prep_alu_m(dc, 1, memsize);
+	crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4);
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_movu_m(DisasContext *dc)
+{
+	int memsize = memsize_z(dc);
+	int insn_len;
+
+	DIS(fprintf (logfile, "movu.%c [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZ);
+	insn_len = dec_prep_alu_m(dc, 0, memsize);
+	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_cmpu_m(DisasContext *dc)
+{
+	int memsize = memsize_z(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "cmpu.%c [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	insn_len = dec_prep_alu_m(dc, 0, memsize);
+	crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4);
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_cmps_m(DisasContext *dc)
+{
+	int memsize = memsize_z(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "cmps.%c [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	insn_len = dec_prep_alu_m(dc, 1, memsize);
+	crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_cmp_m(DisasContext *dc)
+{
+	int memsize = memsize_zz(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "cmp.%c [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	insn_len = dec_prep_alu_m(dc, 0, memsize);
+	crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_test_m(DisasContext *dc)
+{
+	int memsize = memsize_zz(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "test.%d [$r%u%s] op2=%x\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZ);
+	gen_op_clrf(3);
+	insn_len = dec_prep_alu_m(dc, 0, memsize);
+	gen_op_swp_T0_T1();
+	gen_op_movl_T1_im(0);
+	crisv32_alu_op(dc, CC_OP_CMP, dc->op2, memsize_zz(dc));
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_and_m(DisasContext *dc)
+{
+	int memsize = memsize_zz(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "and.%d [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZ);
+	insn_len = dec_prep_alu_m(dc, 0, memsize);
+	crisv32_alu_op(dc, CC_OP_AND, dc->op2, memsize_zz(dc));
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_add_m(DisasContext *dc)
+{
+	int memsize = memsize_zz(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	insn_len = dec_prep_alu_m(dc, 0, memsize);
+	crisv32_alu_op(dc, CC_OP_ADD, dc->op2, memsize_zz(dc));
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_addo_m(DisasContext *dc)
+{
+	int memsize = memsize_zz(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "add.%d [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	cris_cc_mask(dc, 0);
+	insn_len = dec_prep_alu_m(dc, 1, memsize);
+	crisv32_alu_op(dc, CC_OP_ADD, REG_ACR, 4);
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_bound_m(DisasContext *dc)
+{
+	int memsize = memsize_zz(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "bound.%d [$r%u%s, $r%u\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	cris_cc_mask(dc, CC_MASK_NZ);
+	insn_len = dec_prep_alu_m(dc, 0, memsize);
+	crisv32_alu_op(dc, CC_OP_BOUND, dc->op2, 4);
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_addc_mr(DisasContext *dc)
+{
+	int insn_len = 2;
+	DIS(fprintf (logfile, "addc [$r%u%s, $r%u\n",
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	cris_evaluate_flags(dc);
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	insn_len = dec_prep_alu_m(dc, 0, 4);
+	crisv32_alu_op(dc, CC_OP_ADDC, dc->op2, 4);
+	do_postinc(dc, 4);
+	return insn_len;
+}
+
+static unsigned int dec_sub_m(DisasContext *dc)
+{
+	int memsize = memsize_zz(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "sub.%c [$r%u%s, $r%u ir=%x zz=%x\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2, dc->ir, dc->zzsize));
+
+	cris_cc_mask(dc, CC_MASK_NZVC);
+	insn_len = dec_prep_alu_m(dc, 0, memsize);
+	crisv32_alu_op(dc, CC_OP_SUB, dc->op2, memsize);
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_or_m(DisasContext *dc)
+{
+	int memsize = memsize_zz(dc);
+	int insn_len;
+	DIS(fprintf (logfile, "or.%d [$r%u%s, $r%u pc=%x\n",
+		    memsize_char(memsize),
+		    dc->op1, dc->postinc ? "+]" : "]",
+		    dc->op2, dc->pc));
+
+	cris_cc_mask(dc, CC_MASK_NZ);
+	insn_len = dec_prep_alu_m(dc, 0, memsize);
+	crisv32_alu_op(dc, CC_OP_OR, dc->op2, memsize_zz(dc));
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_move_mp(DisasContext *dc)
+{
+	int memsize = memsize_zz(dc);
+	int insn_len = 2;
+
+	DIS(fprintf (logfile, "move.%c [$r%u%s, $p%u\n",
+		    memsize_char(memsize),
+		    dc->op1,
+		    dc->postinc ? "+]" : "]",
+		    dc->op2));
+
+	cris_cc_mask(dc, 0);
+	insn_len = dec_prep_alu_m(dc, 0, memsize);
+	gen_op_movl_T0_T1();
+	gen_movl_preg_T0[dc->op2]();
+
+	do_postinc(dc, memsize);
+	return insn_len;
+}
+
+static unsigned int dec_move_pm(DisasContext *dc)
+{
+	int memsize;
+
+	memsize = preg_sizes[dc->op2];
+
+	DIS(fprintf (logfile, "move.%d $p%u, [$r%u%s\n",
+		     memsize, dc->op2, dc->op1, dc->postinc ? "+]" : "]"));
+
+	cris_cc_mask(dc, 0);
+	/* prepare store.  */
+	gen_movl_T0_preg[dc->op2]();
+	gen_op_movl_T1_T0();
+	gen_movl_T0_reg[dc->op1]();
+	gen_store_T0_T1(dc, memsize);
+	if (dc->postinc)
+	{
+		gen_op_addl_T0_im(memsize);
+		gen_movl_reg_T0[dc->op1]();
+	}
+	return 2;
+}
+
+static unsigned int dec_movem_mr(DisasContext *dc)
+{
+	int i;
+
+	DIS(fprintf (logfile, "movem [$r%u%s, $r%u\n", dc->op1,
+		    dc->postinc ? "+]" : "]", dc->op2));
+
+	cris_cc_mask(dc, 0);
+	/* fetch the address into T1.  */
+	gen_movl_T0_reg[dc->op1]();
+	gen_op_movl_T1_T0();
+	for (i = 0; i <= dc->op2; i++) {
+		/* Perform the load onto regnum i. Always dword wide.  */
+		gen_load_T0_T0(dc, 4, 0);
+		gen_movl_reg_T0[i]();
+		/* Update the address.  */
+		gen_op_addl_T1_im(4);
+		gen_op_movl_T0_T1();
+	}
+	if (dc->postinc) {
+		/* writeback the updated pointer value.  */
+		gen_movl_reg_T0[dc->op1]();
+	}
+	return 2;
+}
+
+static unsigned int dec_movem_rm(DisasContext *dc)
+{
+	int i;
+
+	DIS(fprintf (logfile, "movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
+		     dc->postinc ? "+]" : "]"));
+
+	cris_cc_mask(dc, 0);
+	for (i = 0; i <= dc->op2; i++) {
+		/* Fetch register i into T1.  */
+		gen_movl_T0_reg[i]();
+		gen_op_movl_T1_T0();
+
+		/* Fetch the address into T0.  */
+		gen_movl_T0_reg[dc->op1]();
+		/* Displace it.  */
+		gen_op_addl_T0_im(i * 4);
+
+		/* Perform the store.  */
+		gen_store_T0_T1(dc, 4);
+	}
+	if (dc->postinc) {
+		/* Update the address.  */
+		gen_op_addl_T0_im(4);
+		/* writeback the updated pointer value.  */
+		gen_movl_reg_T0[dc->op1]();
+	}
+	return 2;
+}
+
+static unsigned int dec_move_rm(DisasContext *dc)
+{
+	int memsize;
+
+	memsize = memsize_zz(dc);
+
+	DIS(fprintf (logfile, "move.%d $r%u, [$r%u]\n",
+		     memsize, dc->op2, dc->op1));
+
+	cris_cc_mask(dc, 0);
+	/* prepare store.  */
+	gen_movl_T0_reg[dc->op2]();
+	gen_op_movl_T1_T0();
+	gen_movl_T0_reg[dc->op1]();
+	gen_store_T0_T1(dc, memsize);
+	if (dc->postinc)
+	{
+		gen_op_addl_T0_im(memsize);
+		gen_movl_reg_T0[dc->op1]();
+	}
+	return 2;
+}
+
+
+static unsigned int dec_lapcq(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "lapcq %x, $r%u\n",
+		    dc->pc + dc->op1*2, dc->op2));
+	cris_cc_mask(dc, 0);
+	gen_op_movl_T1_im(dc->pc + dc->op1*2);
+	crisv32_alu_op(dc, CC_OP_MOVE, dc->op2, 4);
+	return 2;
+}
+
+static unsigned int dec_lapc_im(DisasContext *dc)
+{
+	unsigned int rd;
+	int32_t imm;
+	int insn_len = 6;
+
+	rd = dc->op2;
+
+	cris_cc_mask(dc, 0);
+	imm = ldl_code(dc->pc + 2);
+	DIS(fprintf (logfile, "lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2));
+	gen_op_movl_T0_im (dc->pc + imm);
+	gen_movl_reg_T0[rd] ();
+	return insn_len;
+}
+
+/* Jump to special reg.  */
+static unsigned int dec_jump_p(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "jump $p%u\n", dc->op2));
+	cris_cc_mask(dc, 0);
+	/* Store the return address in Pd.  */
+	gen_movl_T0_preg[dc->op2]();
+	gen_op_movl_btarget_T0();
+	cris_prepare_dyn_jmp(dc);
+	return 2;
+}
+
+/* Jump and save.  */
+static unsigned int dec_jas_r(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "jas $r%u, $p%u\n", dc->op1, dc->op2));
+	cris_cc_mask(dc, 0);
+	/* Stor the return address in Pd.  */
+	gen_movl_T0_reg[dc->op1]();
+	gen_op_movl_btarget_T0();
+	gen_op_movl_T0_im(dc->pc + 4);
+	gen_movl_preg_T0[dc->op2]();
+	cris_prepare_dyn_jmp(dc);
+	return 2;
+}
+
+static unsigned int dec_jas_im(DisasContext *dc)
+{
+	uint32_t imm;
+
+	imm = ldl_code(dc->pc + 2);
+
+	DIS(fprintf (logfile, "jas 0x%x\n", imm));
+	cris_cc_mask(dc, 0);
+	/* Stor the return address in Pd.  */
+	gen_op_movl_T0_im(imm);
+	gen_op_movl_btarget_T0();
+	gen_op_movl_T0_im(dc->pc + 8);
+	gen_movl_preg_T0[dc->op2]();
+	cris_prepare_dyn_jmp(dc);
+	return 6;
+}
+
+static unsigned int dec_jasc_im(DisasContext *dc)
+{
+	uint32_t imm;
+
+	imm = ldl_code(dc->pc + 2);
+
+	DIS(fprintf (logfile, "jasc 0x%x\n", imm));
+	cris_cc_mask(dc, 0);
+	/* Stor the return address in Pd.  */
+	gen_op_movl_T0_im(imm);
+	gen_op_movl_btarget_T0();
+	gen_op_movl_T0_im(dc->pc + 8 + 4);
+	gen_movl_preg_T0[dc->op2]();
+	cris_prepare_dyn_jmp(dc);
+	return 6;
+}
+
+static unsigned int dec_jasc_r(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "jasc_r $r%u, $p%u\n", dc->op1, dc->op2));
+	cris_cc_mask(dc, 0);
+	/* Stor the return address in Pd.  */
+	gen_movl_T0_reg[dc->op1]();
+	gen_op_movl_btarget_T0();
+	gen_op_movl_T0_im(dc->pc + 4 + 4);
+	gen_movl_preg_T0[dc->op2]();
+	cris_prepare_dyn_jmp(dc);
+	return 2;
+}
+
+static unsigned int dec_bcc_im(DisasContext *dc)
+{
+	int32_t offset;
+	uint32_t cond = dc->op2;
+
+	offset = ldl_code(dc->pc + 2);
+	offset = sign_extend(offset, 15);
+
+	DIS(fprintf (logfile, "b%s %d pc=%x dst=%x\n",
+		    cc_name(cond), offset,
+		    dc->pc, dc->pc + offset));
+
+	cris_cc_mask(dc, 0);
+	/* op2 holds the condition-code.  */
+	cris_prepare_cc_branch (dc, offset, cond);
+	return 4;
+}
+
+static unsigned int dec_bas_im(DisasContext *dc)
+{
+	int32_t simm;
+
+
+	simm = ldl_code(dc->pc + 2);
+
+	DIS(fprintf (logfile, "bas 0x%x, $p%u\n", dc->pc + simm, dc->op2));
+	cris_cc_mask(dc, 0);
+	/* Stor the return address in Pd.  */
+	gen_op_movl_T0_im(dc->pc + simm);
+	gen_op_movl_btarget_T0();
+	gen_op_movl_T0_im(dc->pc + 8);
+	gen_movl_preg_T0[dc->op2]();
+	cris_prepare_dyn_jmp(dc);
+	return 6;
+}
+
+static unsigned int dec_basc_im(DisasContext *dc)
+{
+	int32_t simm;
+	simm = ldl_code(dc->pc + 2);
+
+	DIS(fprintf (logfile, "basc 0x%x, $p%u\n", dc->pc + simm, dc->op2));
+	cris_cc_mask(dc, 0);
+	/* Stor the return address in Pd.  */
+	gen_op_movl_T0_im(dc->pc + simm);
+	gen_op_movl_btarget_T0();
+	gen_op_movl_T0_im(dc->pc + 12);
+	gen_movl_preg_T0[dc->op2]();
+	cris_prepare_dyn_jmp(dc);
+	return 6;
+}
+
+static unsigned int dec_rfe_etc(DisasContext *dc)
+{
+	DIS(fprintf (logfile, "rfe_etc opc=%x pc=0x%x op1=%d op2=%d\n",
+		    dc->opcode, dc->pc, dc->op1, dc->op2));
+
+	cris_cc_mask(dc, 0);
+
+	if (dc->op2 == 15) /* ignore halt.  */
+		goto done;
+
+	switch (dc->op2 & 7) {
+		case 2:
+			/* rfe.  */
+			cris_evaluate_flags(dc);
+			gen_op_ccs_rshift();
+			break;
+		case 5:
+			/* rfn.  */
+			BUG();
+			break;
+		case 6:
+			/* break.  */
+			gen_op_movl_T0_im(dc->pc);
+			gen_op_movl_pc_T0();
+			/* Breaks start at 16 in the exception vector.  */
+			gen_op_break_im(dc->op1 + 16);
+			break;
+		default:
+			printf ("op2=%x\n", dc->op2);
+			BUG();
+			break;
+
+	}
+  done:
+	return 2;
+}
+
+static unsigned int dec_null(DisasContext *dc)
+{
+	printf ("unknown insn pc=%x opc=%x op1=%x op2=%x\n",
+		dc->pc, dc->opcode, dc->op1, dc->op2);
+	fflush(NULL);
+	BUG();
+	return 2;
+}
+
+struct decoder_info {
+	struct {
+		uint32_t bits;
+		uint32_t mask;
+	};
+	unsigned int (*dec)(DisasContext *dc);
+} decinfo[] = {
+	/* Order matters here.  */
+	{DEC_MOVEQ, dec_moveq},
+	{DEC_BTSTQ, dec_btstq},
+	{DEC_CMPQ, dec_cmpq},
+	{DEC_ADDOQ, dec_addoq},
+	{DEC_ADDQ, dec_addq},
+	{DEC_SUBQ, dec_subq},
+	{DEC_ANDQ, dec_andq},
+	{DEC_ORQ, dec_orq},
+	{DEC_ASRQ, dec_asrq},
+	{DEC_LSLQ, dec_lslq},
+	{DEC_LSRQ, dec_lsrq},
+	{DEC_BCCQ, dec_bccq},
+
+	{DEC_BCC_IM, dec_bcc_im},
+	{DEC_JAS_IM, dec_jas_im},
+	{DEC_JAS_R, dec_jas_r},
+	{DEC_JASC_IM, dec_jasc_im},
+	{DEC_JASC_R, dec_jasc_r},
+	{DEC_BAS_IM, dec_bas_im},
+	{DEC_BASC_IM, dec_basc_im},
+	{DEC_JUMP_P, dec_jump_p},
+	{DEC_LAPC_IM, dec_lapc_im},
+	{DEC_LAPCQ, dec_lapcq},
+
+	{DEC_RFE_ETC, dec_rfe_etc},
+	{DEC_ADDC_MR, dec_addc_mr},
+
+	{DEC_MOVE_MP, dec_move_mp},
+	{DEC_MOVE_PM, dec_move_pm},
+	{DEC_MOVEM_MR, dec_movem_mr},
+	{DEC_MOVEM_RM, dec_movem_rm},
+	{DEC_MOVE_PR, dec_move_pr},
+	{DEC_SCC_R, dec_scc_r},
+	{DEC_SETF, dec_setclrf},
+	{DEC_CLEARF, dec_setclrf},
+
+	{DEC_MOVE_SR, dec_move_sr},
+	{DEC_MOVE_RP, dec_move_rp},
+	{DEC_SWAP_R, dec_swap_r},
+	{DEC_ABS_R, dec_abs_r},
+	{DEC_LZ_R, dec_lz_r},
+	{DEC_MOVE_RS, dec_move_rs},
+	{DEC_BTST_R, dec_btst_r},
+	{DEC_ADDC_R, dec_addc_r},
+
+	{DEC_DSTEP_R, dec_dstep_r},
+	{DEC_XOR_R, dec_xor_r},
+	{DEC_MCP_R, dec_mcp_r},
+	{DEC_CMP_R, dec_cmp_r},
+
+	{DEC_ADDI_R, dec_addi_r},
+	{DEC_ADDI_ACR, dec_addi_acr},
+
+	{DEC_ADD_R, dec_add_r},
+	{DEC_SUB_R, dec_sub_r},
+
+	{DEC_ADDU_R, dec_addu_r},
+	{DEC_ADDS_R, dec_adds_r},
+	{DEC_SUBU_R, dec_subu_r},
+	{DEC_SUBS_R, dec_subs_r},
+	{DEC_LSL_R, dec_lsl_r},
+
+	{DEC_AND_R, dec_and_r},
+	{DEC_OR_R, dec_or_r},
+	{DEC_BOUND_R, dec_bound_r},
+	{DEC_ASR_R, dec_asr_r},
+	{DEC_LSR_R, dec_lsr_r},
+
+	{DEC_MOVU_R, dec_movu_r},
+	{DEC_MOVS_R, dec_movs_r},
+	{DEC_NEG_R, dec_neg_r},
+	{DEC_MOVE_R, dec_move_r},
+
+	/* ftag_fidx_i_m.  */
+	/* ftag_fidx_d_m.  */
+
+	{DEC_MULS_R, dec_muls_r},
+	{DEC_MULU_R, dec_mulu_r},
+
+	{DEC_ADDU_M, dec_addu_m},
+	{DEC_ADDS_M, dec_adds_m},
+	{DEC_SUBU_M, dec_subu_m},
+	{DEC_SUBS_M, dec_subs_m},
+
+	{DEC_CMPU_M, dec_cmpu_m},
+	{DEC_CMPS_M, dec_cmps_m},
+	{DEC_MOVU_M, dec_movu_m},
+	{DEC_MOVS_M, dec_movs_m},
+
+	{DEC_CMP_M, dec_cmp_m},
+	{DEC_ADDO_M, dec_addo_m},
+	{DEC_BOUND_M, dec_bound_m},
+	{DEC_ADD_M, dec_add_m},
+	{DEC_SUB_M, dec_sub_m},
+	{DEC_AND_M, dec_and_m},
+	{DEC_OR_M, dec_or_m},
+	{DEC_MOVE_RM, dec_move_rm},
+	{DEC_TEST_M, dec_test_m},
+	{DEC_MOVE_MR, dec_move_mr},
+
+	{{0, 0}, dec_null}
+};
+
+static inline unsigned int
+cris_decoder(DisasContext *dc)
+{
+	unsigned int insn_len = 2;
+	uint32_t tmp;
+	int i;
+
+	/* Load a halfword onto the instruction register.  */
+	tmp = ldl_code(dc->pc);
+	dc->ir = tmp & 0xffff;
+
+	/* Now decode it.  */
+	dc->opcode   = EXTRACT_FIELD(dc->ir, 4, 11);
+	dc->op1      = EXTRACT_FIELD(dc->ir, 0, 3);
+	dc->op2      = EXTRACT_FIELD(dc->ir, 12, 15);
+	dc->zsize    = EXTRACT_FIELD(dc->ir, 4, 4);
+	dc->zzsize   = EXTRACT_FIELD(dc->ir, 4, 5);
+	dc->postinc  = EXTRACT_FIELD(dc->ir, 10, 10);
+
+	/* Large switch for all insns.  */
+	for (i = 0; i < sizeof decinfo / sizeof decinfo[0]; i++) {
+		if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits)
+		{
+			insn_len = decinfo[i].dec(dc);
+			break;
+		}
+	}
+
+	return insn_len;
+}
+
+static void check_breakpoint(CPUState *env, DisasContext *dc)
+{
+	int j;
+	if (env->nb_breakpoints > 0) {
+		for(j = 0; j < env->nb_breakpoints; j++) {
+			if (env->breakpoints[j] == dc->pc) {
+				cris_evaluate_flags (dc);
+				gen_op_movl_T0_im((long)dc->pc);
+				gen_op_movl_pc_T0();
+				gen_op_debug();
+				dc->is_jmp = DISAS_UPDATE;
+			}
+		}
+	}
+}
+
+
+/* generate intermediate code for basic block 'tb'.  */
+struct DisasContext ctx;
+static int
+gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
+                               int search_pc)
+{
+	uint16_t *gen_opc_end;
+   	uint32_t pc_start;
+	unsigned int insn_len;
+	int j, lj;
+	struct DisasContext *dc = &ctx;
+	uint32_t next_page_start;
+
+	pc_start = tb->pc;
+	dc->env = env;
+	dc->tb = tb;
+
+	gen_opc_ptr = gen_opc_buf;
+	gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+	gen_opparam_ptr = gen_opparam_buf;
+
+	dc->is_jmp = DISAS_NEXT;
+	dc->pc = pc_start;
+	dc->singlestep_enabled = env->singlestep_enabled;
+	dc->flagx_live = 0;
+	dc->flags_x = 0;
+	next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+	lj = -1;
+	do
+	{
+		check_breakpoint(env, dc);
+		if (dc->is_jmp == DISAS_JUMP)
+			goto done;
+
+		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] = dc->pc;
+			gen_opc_instr_start[lj] = 1;
+		}
+
+		insn_len = cris_decoder(dc);
+		STATS(gen_op_exec_insn());
+		dc->pc += insn_len;
+		if (!dc->flagx_live
+		    || (dc->flagx_live &&
+			!(dc->cc_op == CC_OP_FLAGS && dc->flags_x))) {
+			gen_movl_T0_preg[SR_CCS]();
+			gen_op_andl_T0_im(~X_FLAG);
+			gen_movl_preg_T0[SR_CCS]();
+			dc->flagx_live = 1;
+			dc->flags_x = 0;
+		}
+
+		/* Check for delayed branches here. If we do it before
+		   actually genereating any host code, the simulator will just
+		   loop doing nothing for on this program location.  */
+		if (dc->delayed_branch) {
+			dc->delayed_branch--;
+			if (dc->delayed_branch == 0)
+			{
+				if (dc->bcc == CC_A) {
+					gen_op_jmp ();
+					dc->is_jmp = DISAS_UPDATE;
+				}
+				else {
+					/* Conditional jmp.  */
+					gen_op_cc_jmp (dc->delayed_pc, dc->pc);
+					dc->is_jmp = DISAS_UPDATE;
+				}
+			}
+		}
+
+		if (env->singlestep_enabled)
+			break;
+	} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end
+		 && dc->pc < next_page_start);
+
+	if (!dc->is_jmp) {
+		gen_op_movl_T0_im((long)dc->pc);
+		gen_op_movl_pc_T0();
+	}
+
+	cris_evaluate_flags (dc);
+  done:
+	if (__builtin_expect(env->singlestep_enabled, 0)) {
+		gen_op_debug();
+	} else {
+		switch(dc->is_jmp) {
+			case DISAS_NEXT:
+				gen_goto_tb(dc, 1, dc->pc);
+				break;
+			default:
+			case DISAS_JUMP:
+			case DISAS_UPDATE:
+				/* indicate that the hash table must be used
+				   to find the next TB */
+				/* T0 is used to index the jmp tables.  */
+				gen_op_movl_T0_0();
+				gen_op_exit_tb();
+				break;
+			case DISAS_TB_JUMP:
+				/* nothing more to generate */
+				break;
+		}
+	}
+	*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;
+	} else {
+		tb->size = dc->pc - pc_start;
+	}
+
+#ifdef DEBUG_DISAS
+	if (loglevel & CPU_LOG_TB_IN_ASM) {
+		fprintf(logfile, "--------------\n");
+		fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
+		target_disas(logfile, pc_start, dc->pc + 4 - pc_start, 0);
+		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);
+}
+
+void cpu_dump_state (CPUState *env, FILE *f,
+                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+                     int flags)
+{
+	int i;
+	uint32_t srs;
+
+	if (!env || !f)
+		return;
+
+	cpu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
+		    "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n"
+		    "debug=%x %x %x\n",
+		    env->pc, env->pregs[SR_CCS], env->btaken, env->btarget,
+		    env->cc_op,
+		    env->cc_src, env->cc_dest, env->cc_result, env->cc_mask,
+		    env->debug1, env->debug2, env->debug3);
+
+	for (i = 0; i < 16; i++) {
+		cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
+		if ((i + 1) % 4 == 0)
+			cpu_fprintf(f, "\n");
+	}
+	cpu_fprintf(f, "\nspecial regs:\n");
+	for (i = 0; i < 16; i++) {
+		cpu_fprintf(f, "p%2.2d=%8.8x ", i, env->pregs[i]);
+		if ((i + 1) % 4 == 0)
+			cpu_fprintf(f, "\n");
+	}
+	srs = env->pregs[SR_SRS];
+	cpu_fprintf(f, "\nsupport function regs bank %d:\n", srs);
+	if (srs < 256) {
+		for (i = 0; i < 16; i++) {
+			cpu_fprintf(f, "s%2.2d=%8.8x ",
+				    i, env->sregs[srs][i]);
+			if ((i + 1) % 4 == 0)
+				cpu_fprintf(f, "\n");
+		}
+	}
+	cpu_fprintf(f, "\n\n");
+
+}
+
+CPUCRISState *cpu_cris_init (void)
+{
+	CPUCRISState *env;
+
+	env = qemu_mallocz(sizeof(CPUCRISState));
+	if (!env)
+		return NULL;
+	cpu_exec_init(env);
+	cpu_reset(env);
+	return env;
+}
+
+void cpu_reset (CPUCRISState *env)
+{
+	memset(env, 0, offsetof(CPUCRISState, breakpoints));
+	tlb_flush(env, 1);
+}

Modified: trunk/src/host/qemu-neo1973/target-i386/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/cpu.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-i386/cpu.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -84,6 +84,7 @@
 #define DESC_AVL_MASK   (1 << 20)
 #define DESC_P_MASK     (1 << 15)
 #define DESC_DPL_SHIFT  13
+#define DESC_DPL_MASK   (1 << DESC_DPL_SHIFT)
 #define DESC_S_MASK     (1 << 12)
 #define DESC_TYPE_SHIFT 8
 #define DESC_A_MASK     (1 << 8)
@@ -149,6 +150,8 @@
 #define HF_VM_SHIFT         17 /* must be same as eflags */
 #define HF_HALTED_SHIFT     18 /* CPU halted */
 #define HF_SMM_SHIFT        19 /* CPU in SMM mode */
+#define HF_GIF_SHIFT        20 /* if set CPU takes interrupts */
+#define HF_HIF_SHIFT        21 /* shadow copy of IF_MASK when in SVM */
 
 #define HF_CPL_MASK          (3 << HF_CPL_SHIFT)
 #define HF_SOFTMMU_MASK      (1 << HF_SOFTMMU_SHIFT)
@@ -166,6 +169,8 @@
 #define HF_OSFXSR_MASK       (1 << HF_OSFXSR_SHIFT)
 #define HF_HALTED_MASK       (1 << HF_HALTED_SHIFT)
 #define HF_SMM_MASK          (1 << HF_SMM_SHIFT)
+#define HF_GIF_MASK          (1 << HF_GIF_SHIFT)
+#define HF_HIF_MASK          (1 << HF_HIF_SHIFT)
 
 #define CR0_PE_MASK  (1 << 0)
 #define CR0_MP_MASK  (1 << 1)
@@ -249,6 +254,8 @@
 #define MSR_GSBASE                      0xc0000101
 #define MSR_KERNELGSBASE                0xc0000102
 
+#define MSR_VM_HSAVE_PA                 0xc0010117
+
 /* cpuid_features bits */
 #define CPUID_FP87 (1 << 0)
 #define CPUID_VME  (1 << 1)
@@ -283,6 +290,8 @@
 #define CPUID_EXT2_FFXSR   (1 << 25)
 #define CPUID_EXT2_LM      (1 << 29)
 
+#define CPUID_EXT3_SVM     (1 << 2)
+
 #define EXCP00_DIVZ	0
 #define EXCP01_SSTP	1
 #define EXCP02_NMI	2
@@ -423,6 +432,8 @@
 #define CPU_NB_REGS 8
 #endif
 
+#define NB_MMU_MODES 2
+
 typedef struct CPUX86State {
 #if TARGET_LONG_BITS > HOST_LONG_BITS
     /* temporaries if we cannot store them in host registers */
@@ -489,6 +500,16 @@
     uint32_t sysenter_eip;
     uint64_t efer;
     uint64_t star;
+
+    target_phys_addr_t vm_hsave;
+    target_phys_addr_t vm_vmcb;
+    uint64_t intercept;
+    uint16_t intercept_cr_read;
+    uint16_t intercept_cr_write;
+    uint16_t intercept_dr_read;
+    uint16_t intercept_dr_write;
+    uint32_t intercept_exceptions;
+
 #ifdef TARGET_X86_64
     target_ulong lstar;
     target_ulong cstar;
@@ -530,6 +551,7 @@
     uint32_t cpuid_xlevel;
     uint32_t cpuid_model[12];
     uint32_t cpuid_ext2_features;
+    uint32_t cpuid_ext3_features;
     uint32_t cpuid_apic_id;
 
 #ifdef USE_KQEMU
@@ -668,6 +690,17 @@
 #define cpu_gen_code cpu_x86_gen_code
 #define cpu_signal_handler cpu_x86_signal_handler
 
+/* MMU modes definitions */
+#define MMU_MODE0_SUFFIX _kernel
+#define MMU_MODE1_SUFFIX _user
+#define MMU_USER_IDX 1
+static inline int cpu_mmu_index (CPUState *env)
+{
+    return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0;
+}
+
 #include "cpu-all.h"
 
+#include "svm.h"
+
 #endif /* CPU_I386_H */

Modified: trunk/src/host/qemu-neo1973/target-i386/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/exec.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-i386/exec.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -163,8 +163,8 @@
 void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
 void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr);
 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
-                             int is_write, int is_user, int is_softmmu);
-void tlb_fill(target_ulong addr, int is_write, int is_user,
+                             int is_write, int mmu_idx, int is_softmmu);
+void tlb_fill(target_ulong addr, int is_write, int mmu_idx,
               void *retaddr);
 void __hidden cpu_lock(void);
 void __hidden cpu_unlock(void);
@@ -502,6 +502,15 @@
 void helper_hlt(void);
 void helper_monitor(void);
 void helper_mwait(void);
+void helper_vmrun(target_ulong addr);
+void helper_vmmcall(void);
+void helper_vmload(target_ulong addr);
+void helper_vmsave(target_ulong addr);
+void helper_stgi(void);
+void helper_clgi(void);
+void helper_skinit(void);
+void helper_invlpga(void);
+void vmexit(uint64_t exit_code, uint64_t exit_info_1);
 
 extern const uint8_t parity_table[256];
 extern const uint8_t rclw_table[32];
@@ -589,3 +598,4 @@
     }
     return EXCP_HALTED;
 }
+

Modified: trunk/src/host/qemu-neo1973/target-i386/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-i386/helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -594,7 +594,18 @@
     int has_error_code, new_stack, shift;
     uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
     uint32_t old_eip, sp_mask;
+    int svm_should_check = 1;
 
+    if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) {
+        next_eip = EIP;
+        svm_should_check = 0;
+    }
+
+    if (svm_should_check
+        && (INTERCEPTEDl(_exceptions, 1 << intno)
+        && !is_int)) {
+        raise_interrupt(intno, is_int, error_code, 0);
+    }
     has_error_code = 0;
     if (!is_int && !is_hw) {
         switch(intno) {
@@ -830,7 +841,17 @@
     int has_error_code, new_stack;
     uint32_t e1, e2, e3, ss;
     target_ulong old_eip, esp, offset;
+    int svm_should_check = 1;
 
+    if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) {
+        next_eip = EIP;
+        svm_should_check = 0;
+    }
+    if (svm_should_check
+        && INTERCEPTEDl(_exceptions, 1 << intno)
+        && !is_int) {
+        raise_interrupt(intno, is_int, error_code, 0);
+    }
     has_error_code = 0;
     if (!is_int && !is_hw) {
         switch(intno) {
@@ -1077,7 +1098,17 @@
     int selector;
     uint32_t offset, esp;
     uint32_t old_cs, old_eip;
+    int svm_should_check = 1;
 
+    if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) {
+        next_eip = EIP;
+        svm_should_check = 0;
+    }
+    if (svm_should_check
+        && INTERCEPTEDl(_exceptions, 1 << intno)
+        && !is_int) {
+        raise_interrupt(intno, is_int, error_code, 0);
+    }
     /* real mode (simpler !) */
     dt = &env->idt;
     if (intno * 4 + 3 > dt->limit)
@@ -1227,8 +1258,10 @@
 void raise_interrupt(int intno, int is_int, int error_code,
                      int next_eip_addend)
 {
-    if (!is_int)
+    if (!is_int) {
+        svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
         intno = check_exception(intno, &error_code);
+    }
 
     env->exception_index = intno;
     env->error_code = error_code;
@@ -1671,7 +1704,7 @@
     case 0x80000001:
         EAX = env->cpuid_features;
         EBX = 0;
-        ECX = 0;
+        ECX = env->cpuid_ext3_features;
         EDX = env->cpuid_ext2_features;
         break;
     case 0x80000002:
@@ -2745,6 +2778,9 @@
     case MSR_PAT:
         env->pat = val;
         break;
+    case MSR_VM_HSAVE_PA:
+        env->vm_hsave = val;
+        break;
 #ifdef TARGET_X86_64
     case MSR_LSTAR:
         env->lstar = val;
@@ -2796,6 +2832,9 @@
     case MSR_PAT:
         val = env->pat;
         break;
+    case MSR_VM_HSAVE_PA:
+        val = env->vm_hsave;
+        break;
 #ifdef TARGET_X86_64
     case MSR_LSTAR:
         val = env->lstar;
@@ -3685,7 +3724,7 @@
 {
     uint64_t r0, r1;
 
-    mulu64(&r1, &r0, EAX, T0);
+    mulu64(&r0, &r1, EAX, T0);
     EAX = r0;
     EDX = r1;
     CC_DST = r0;
@@ -3696,7 +3735,7 @@
 {
     uint64_t r0, r1;
 
-    muls64(&r1, &r0, EAX, T0);
+    muls64(&r0, &r1, EAX, T0);
     EAX = r0;
     EDX = r1;
     CC_DST = r0;
@@ -3707,7 +3746,7 @@
 {
     uint64_t r0, r1;
 
-    muls64(&r1, &r0, T0, T1);
+    muls64(&r0, &r1, T0, T1);
     T0 = r0;
     CC_DST = r0;
     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
@@ -3826,7 +3865,11 @@
 #if !defined(CONFIG_USER_ONLY)
 
 #define MMUSUFFIX _mmu
-#define GETPC() (__builtin_return_address(0))
+#ifdef __s390__
+# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
+#else
+# define GETPC() (__builtin_return_address(0))
+#endif
 
 #define SHIFT 0
 #include "softmmu_template.h"
@@ -3846,7 +3889,7 @@
    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)
+void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 {
     TranslationBlock *tb;
     int ret;
@@ -3858,7 +3901,7 @@
     saved_env = env;
     env = cpu_single_env;
 
-    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, is_user, 1);
+    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
     if (ret) {
         if (retaddr) {
             /* now we have a real cpu fault */
@@ -3877,3 +3920,491 @@
     }
     env = saved_env;
 }
+
+
+/* Secure Virtual Machine helpers */
+
+void helper_stgi(void)
+{
+    env->hflags |= HF_GIF_MASK;
+}
+
+void helper_clgi(void)
+{
+    env->hflags &= ~HF_GIF_MASK;
+}
+
+#if defined(CONFIG_USER_ONLY)
+
+void helper_vmrun(target_ulong addr) { }
+void helper_vmmcall(void) { }
+void helper_vmload(target_ulong addr) { }
+void helper_vmsave(target_ulong addr) { }
+void helper_skinit(void) { }
+void helper_invlpga(void) { }
+void vmexit(uint64_t exit_code, uint64_t exit_info_1) { }
+int svm_check_intercept_param(uint32_t type, uint64_t param)
+{
+    return 0;
+}
+
+#else
+
+static inline uint32_t
+vmcb2cpu_attrib(uint16_t vmcb_attrib, uint32_t vmcb_base, uint32_t vmcb_limit)
+{
+    return    ((vmcb_attrib & 0x00ff) << 8)          /* Type, S, DPL, P */
+	    | ((vmcb_attrib & 0x0f00) << 12)         /* AVL, L, DB, G */
+	    | ((vmcb_base >> 16) & 0xff)             /* Base 23-16 */
+	    | (vmcb_base & 0xff000000)               /* Base 31-24 */
+	    | (vmcb_limit & 0xf0000);                /* Limit 19-16 */
+}
+
+static inline uint16_t cpu2vmcb_attrib(uint32_t cpu_attrib)
+{
+    return    ((cpu_attrib >> 8) & 0xff)             /* Type, S, DPL, P */
+	    | ((cpu_attrib & 0xf00000) >> 12);       /* AVL, L, DB, G */
+}
+
+extern uint8_t *phys_ram_base;
+void helper_vmrun(target_ulong addr)
+{
+    uint32_t event_inj;
+    uint32_t int_ctl;
+
+    if (loglevel & CPU_LOG_TB_IN_ASM)
+        fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr);
+
+    env->vm_vmcb = addr;
+    regs_to_env();
+
+    /* save the current CPU state in the hsave page */
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
+    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
+
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
+    stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
+
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8), env->cr[8]);
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
+
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
+
+    SVM_SAVE_SEG(env->vm_hsave, segs[R_ES], es);
+    SVM_SAVE_SEG(env->vm_hsave, segs[R_CS], cs);
+    SVM_SAVE_SEG(env->vm_hsave, segs[R_SS], ss);
+    SVM_SAVE_SEG(env->vm_hsave, segs[R_DS], ds);
+
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip), EIP);
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
+    stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
+
+    /* load the interception bitmaps so we do not need to access the
+       vmcb in svm mode */
+    /* We shift all the intercept bits so we can OR them with the TB
+       flags later on */
+    env->intercept            = (ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept)) << INTERCEPT_INTR) | INTERCEPT_SVM_MASK;
+    env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
+    env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
+    env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
+    env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
+    env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
+
+    env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
+    env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
+
+    env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
+    env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
+
+    /* clear exit_info_2 so we behave like the real hardware */
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0);
+
+    cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
+    cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
+    cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
+    env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
+    int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
+    if (int_ctl & V_INTR_MASKING_MASK) {
+        env->cr[8] = int_ctl & V_TPR_MASK;
+        if (env->eflags & IF_MASK)
+            env->hflags |= HF_HIF_MASK;
+    }
+
+#ifdef TARGET_X86_64
+    env->efer = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer));
+    env->hflags &= ~HF_LMA_MASK;
+    if (env->efer & MSR_EFER_LMA)
+       env->hflags |= HF_LMA_MASK;
+#endif
+    env->eflags = 0;
+    load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
+                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
+    CC_OP = CC_OP_EFLAGS;
+    CC_DST = 0xffffffff;
+
+    SVM_LOAD_SEG(env->vm_vmcb, ES, es);
+    SVM_LOAD_SEG(env->vm_vmcb, CS, cs);
+    SVM_LOAD_SEG(env->vm_vmcb, SS, ss);
+    SVM_LOAD_SEG(env->vm_vmcb, DS, ds);
+
+    EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
+    env->eip = EIP;
+    ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
+    EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
+    env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
+    env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
+    cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
+
+    /* FIXME: guest state consistency checks */
+
+    switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
+        case TLB_CONTROL_DO_NOTHING:
+            break;
+        case TLB_CONTROL_FLUSH_ALL_ASID:
+            /* FIXME: this is not 100% correct but should work for now */
+            tlb_flush(env, 1);
+        break;
+    }
+
+    helper_stgi();
+
+    regs_to_env();
+
+    /* maybe we need to inject an event */
+    event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
+    if (event_inj & SVM_EVTINJ_VALID) {
+        uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
+        uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
+        uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
+        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
+
+        if (loglevel & CPU_LOG_TB_IN_ASM)
+            fprintf(logfile, "Injecting(%#hx): ", valid_err);
+        /* FIXME: need to implement valid_err */
+        switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
+        case SVM_EVTINJ_TYPE_INTR:
+                env->exception_index = vector;
+                env->error_code = event_inj_err;
+                env->exception_is_int = 1;
+                env->exception_next_eip = -1;
+                if (loglevel & CPU_LOG_TB_IN_ASM)
+                    fprintf(logfile, "INTR");
+                break;
+        case SVM_EVTINJ_TYPE_NMI:
+                env->exception_index = vector;
+                env->error_code = event_inj_err;
+                env->exception_is_int = 1;
+                env->exception_next_eip = EIP;
+                if (loglevel & CPU_LOG_TB_IN_ASM)
+                    fprintf(logfile, "NMI");
+                break;
+        case SVM_EVTINJ_TYPE_EXEPT:
+                env->exception_index = vector;
+                env->error_code = event_inj_err;
+                env->exception_is_int = 0;
+                env->exception_next_eip = -1;
+                if (loglevel & CPU_LOG_TB_IN_ASM)
+                    fprintf(logfile, "EXEPT");
+                break;
+        case SVM_EVTINJ_TYPE_SOFT:
+                env->exception_index = vector;
+                env->error_code = event_inj_err;
+                env->exception_is_int = 1;
+                env->exception_next_eip = EIP;
+                if (loglevel & CPU_LOG_TB_IN_ASM)
+                    fprintf(logfile, "SOFT");
+                break;
+        }
+        if (loglevel & CPU_LOG_TB_IN_ASM)
+            fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code);
+    }
+    if ((int_ctl & V_IRQ_MASK) || (env->intercept & INTERCEPT_VINTR)) {
+        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
+    }
+
+    cpu_loop_exit();
+}
+
+void helper_vmmcall(void)
+{
+    if (loglevel & CPU_LOG_TB_IN_ASM)
+        fprintf(logfile,"vmmcall!\n");
+}
+
+void helper_vmload(target_ulong addr)
+{
+    if (loglevel & CPU_LOG_TB_IN_ASM)
+        fprintf(logfile,"vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
+                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
+                env->segs[R_FS].base);
+
+    SVM_LOAD_SEG2(addr, segs[R_FS], fs);
+    SVM_LOAD_SEG2(addr, segs[R_GS], gs);
+    SVM_LOAD_SEG2(addr, tr, tr);
+    SVM_LOAD_SEG2(addr, ldt, ldtr);
+
+#ifdef TARGET_X86_64
+    env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base));
+    env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar));
+    env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar));
+    env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask));
+#endif
+    env->star = ldq_phys(addr + offsetof(struct vmcb, save.star));
+    env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs));
+    env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_esp));
+    env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_eip));
+}
+
+void helper_vmsave(target_ulong addr)
+{
+    if (loglevel & CPU_LOG_TB_IN_ASM)
+        fprintf(logfile,"vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
+                addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
+                env->segs[R_FS].base);
+
+    SVM_SAVE_SEG(addr, segs[R_FS], fs);
+    SVM_SAVE_SEG(addr, segs[R_GS], gs);
+    SVM_SAVE_SEG(addr, tr, tr);
+    SVM_SAVE_SEG(addr, ldt, ldtr);
+
+#ifdef TARGET_X86_64
+    stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase);
+    stq_phys(addr + offsetof(struct vmcb, save.lstar), env->lstar);
+    stq_phys(addr + offsetof(struct vmcb, save.cstar), env->cstar);
+    stq_phys(addr + offsetof(struct vmcb, save.sfmask), env->fmask);
+#endif
+    stq_phys(addr + offsetof(struct vmcb, save.star), env->star);
+    stq_phys(addr + offsetof(struct vmcb, save.sysenter_cs), env->sysenter_cs);
+    stq_phys(addr + offsetof(struct vmcb, save.sysenter_esp), env->sysenter_esp);
+    stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip);
+}
+
+void helper_skinit(void)
+{
+    if (loglevel & CPU_LOG_TB_IN_ASM)
+        fprintf(logfile,"skinit!\n");
+}
+
+void helper_invlpga(void)
+{
+    tlb_flush(env, 0);
+}
+
+int svm_check_intercept_param(uint32_t type, uint64_t param)
+{
+    switch(type) {
+    case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
+        if (INTERCEPTEDw(_cr_read, (1 << (type - SVM_EXIT_READ_CR0)))) {
+            vmexit(type, param);
+            return 1;
+        }
+        break;
+    case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 8:
+        if (INTERCEPTEDw(_dr_read, (1 << (type - SVM_EXIT_READ_DR0)))) {
+            vmexit(type, param);
+            return 1;
+        }
+        break;
+    case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
+        if (INTERCEPTEDw(_cr_write, (1 << (type - SVM_EXIT_WRITE_CR0)))) {
+            vmexit(type, param);
+            return 1;
+        }
+        break;
+    case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 8:
+        if (INTERCEPTEDw(_dr_write, (1 << (type - SVM_EXIT_WRITE_DR0)))) {
+            vmexit(type, param);
+            return 1;
+        }
+        break;
+    case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 16:
+        if (INTERCEPTEDl(_exceptions, (1 << (type - SVM_EXIT_EXCP_BASE)))) {
+            vmexit(type, param);
+            return 1;
+        }
+        break;
+    case SVM_EXIT_IOIO:
+        if (INTERCEPTED(1ULL << INTERCEPT_IOIO_PROT)) {
+            /* FIXME: this should be read in at vmrun (faster this way?) */
+            uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
+            uint16_t port = (uint16_t) (param >> 16);
+
+            if(ldub_phys(addr + port / 8) & (1 << (port % 8)))
+                vmexit(type, param);
+        }
+        break;
+
+    case SVM_EXIT_MSR:
+        if (INTERCEPTED(1ULL << INTERCEPT_MSR_PROT)) {
+            /* FIXME: this should be read in at vmrun (faster this way?) */
+            uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa));
+            switch((uint32_t)ECX) {
+            case 0 ... 0x1fff:
+                T0 = (ECX * 2) % 8;
+                T1 = ECX / 8;
+                break;
+            case 0xc0000000 ... 0xc0001fff:
+                T0 = (8192 + ECX - 0xc0000000) * 2;
+                T1 = (T0 / 8);
+                T0 %= 8;
+                break;
+            case 0xc0010000 ... 0xc0011fff:
+                T0 = (16384 + ECX - 0xc0010000) * 2;
+                T1 = (T0 / 8);
+                T0 %= 8;
+                break;
+            default:
+                vmexit(type, param);
+                return 1;
+            }
+            if (ldub_phys(addr + T1) & ((1 << param) << T0))
+                vmexit(type, param);
+            return 1;
+        }
+        break;
+    default:
+        if (INTERCEPTED((1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR)))) {
+            vmexit(type, param);
+            return 1;
+        }
+        break;
+    }
+    return 0;
+}
+
+void vmexit(uint64_t exit_code, uint64_t exit_info_1)
+{
+    uint32_t int_ctl;
+
+    if (loglevel & CPU_LOG_TB_IN_ASM)
+        fprintf(logfile,"vmexit(%016" PRIx64 ", %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
+                exit_code, exit_info_1,
+                ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
+                EIP);
+
+    if(env->hflags & HF_INHIBIT_IRQ_MASK) {
+        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
+        env->hflags &= ~HF_INHIBIT_IRQ_MASK;
+    } else {
+        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
+    }
+
+    /* Save the VM state in the vmcb */
+    SVM_SAVE_SEG(env->vm_vmcb, segs[R_ES], es);
+    SVM_SAVE_SEG(env->vm_vmcb, segs[R_CS], cs);
+    SVM_SAVE_SEG(env->vm_vmcb, segs[R_SS], ss);
+    SVM_SAVE_SEG(env->vm_vmcb, segs[R_DS], ds);
+
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
+    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
+
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base), env->idt.base);
+    stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
+
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
+
+    if ((int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl))) & V_INTR_MASKING_MASK) {
+        int_ctl &= ~V_TPR_MASK;
+        int_ctl |= env->cr[8] & V_TPR_MASK;
+        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
+    }
+
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags());
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip);
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP);
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX);
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
+    stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK);
+
+    /* Reload the host state from vm_hsave */
+    env->hflags &= ~HF_HIF_MASK;
+    env->intercept = 0;
+    env->intercept_exceptions = 0;
+    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+
+    env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base));
+    env->gdt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit));
+
+    env->idt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base));
+    env->idt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit));
+
+    cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK);
+    cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4)));
+    cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3)));
+    if (int_ctl & V_INTR_MASKING_MASK)
+        env->cr[8] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8));
+    /* we need to set the efer after the crs so the hidden flags get set properly */
+#ifdef TARGET_X86_64
+    env->efer  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer));
+    env->hflags &= ~HF_LMA_MASK;
+    if (env->efer & MSR_EFER_LMA)
+       env->hflags |= HF_LMA_MASK;
+#endif
+
+    env->eflags = 0;
+    load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)),
+                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
+    CC_OP = CC_OP_EFLAGS;
+
+    SVM_LOAD_SEG(env->vm_hsave, ES, es);
+    SVM_LOAD_SEG(env->vm_hsave, CS, cs);
+    SVM_LOAD_SEG(env->vm_hsave, SS, ss);
+    SVM_LOAD_SEG(env->vm_hsave, DS, ds);
+
+    EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
+    ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));
+    EAX = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax));
+
+    env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6));
+    env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7));
+
+    /* other setups */
+    cpu_x86_set_cpl(env, 0);
+    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code_hi), (uint32_t)(exit_code >> 32));
+    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1);
+
+    helper_clgi();
+    /* FIXME: Resets the current ASID register to zero (host ASID). */
+
+    /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
+
+    /* Clears the TSC_OFFSET inside the processor. */
+
+    /* If the host is in PAE mode, the processor reloads the host's PDPEs
+       from the page table indicated the host's CR3. If the PDPEs contain
+       illegal state, the processor causes a shutdown. */
+
+    /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
+    env->cr[0] |= CR0_PE_MASK;
+    env->eflags &= ~VM_MASK;
+
+    /* Disables all breakpoints in the host DR7 register. */
+
+    /* Checks the reloaded host state for consistency. */
+
+    /* If the host's rIP reloaded by #VMEXIT is outside the limit of the
+       host's code segment or non-canonical (in the case of long mode), a
+       #GP fault is delivered inside the host.) */
+
+    /* remove any pending exception */
+    env->exception_index = -1;
+    env->error_code = 0;
+    env->old_exception = -1;
+
+    regs_to_env();
+    cpu_loop_exit();
+}
+
+#endif

Modified: trunk/src/host/qemu-neo1973/target-i386/helper2.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/helper2.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-i386/helper2.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -27,6 +27,7 @@
 
 #include "cpu.h"
 #include "exec-all.h"
+#include "svm.h"
 
 //#define DEBUG_MMU
 
@@ -111,10 +112,11 @@
                                CPUID_CX8 | CPUID_PGE | CPUID_CMOV |
                                CPUID_PAT);
         env->pat = 0x0007040600070406ULL;
+        env->cpuid_ext3_features = CPUID_EXT3_SVM;
         env->cpuid_ext_features = CPUID_EXT_SSE3;
         env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP;
         env->cpuid_features |= CPUID_APIC;
-        env->cpuid_xlevel = 0x80000006;
+        env->cpuid_xlevel = 0x8000000e;
         {
             const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
             int c, len, i;
@@ -131,7 +133,6 @@
         /* currently not enabled for std i386 because not fully tested */
         env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF);
         env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX;
-        env->cpuid_xlevel = 0x80000008;
 
         /* these features are needed for Win64 and aren't fully implemented */
         env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA;
@@ -162,6 +163,7 @@
 #ifdef CONFIG_SOFTMMU
     env->hflags |= HF_SOFTMMU_MASK;
 #endif
+    env->hflags |= HF_GIF_MASK;
 
     cpu_x86_update_cr0(env, 0x60000010);
     env->a20_mask = 0xffffffff;
@@ -569,7 +571,7 @@
 #if defined(CONFIG_USER_ONLY)
 
 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
-                             int is_write, int is_user, int is_softmmu)
+                             int is_write, int mmu_idx, int is_softmmu)
 {
     /* user mode only emulation */
     is_write &= 1;
@@ -596,14 +598,15 @@
    2  = soft MMU activation required for this block
 */
 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
-                             int is_write1, int is_user, int is_softmmu)
+                             int is_write1, int mmu_idx, int is_softmmu)
 {
     uint64_t ptep, pte;
     uint32_t pdpe_addr, pde_addr, pte_addr;
-    int error_code, is_dirty, prot, page_size, ret, is_write;
+    int error_code, is_dirty, prot, page_size, ret, is_write, is_user;
     unsigned long paddr, page_offset;
     target_ulong vaddr, virt_addr;
 
+    is_user = mmu_idx == MMU_USER_IDX;
 #if defined(DEBUG_MMU)
     printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
            addr, is_write1, is_user, env->eip);
@@ -860,12 +863,11 @@
     paddr = (pte & TARGET_PAGE_MASK) + page_offset;
     vaddr = virt_addr + page_offset;
 
-    ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
+    ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
     return ret;
  do_fault_protect:
     error_code = PG_ERROR_P_MASK;
  do_fault:
-    env->cr[2] = addr;
     error_code |= (is_write << PG_ERROR_W_BIT);
     if (is_user)
         error_code |= PG_ERROR_U_MASK;
@@ -873,8 +875,16 @@
         (env->efer & MSR_EFER_NXE) &&
         (env->cr[4] & CR4_PAE_MASK))
         error_code |= PG_ERROR_I_D_MASK;
+    if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE)) {
+        stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), addr);
+    } else {
+        env->cr[2] = addr;
+    }
     env->error_code = error_code;
     env->exception_index = EXCP0E_PAGE;
+    /* the VMM will handle this */
+    if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE))
+        return 2;
     return 1;
 }
 

Modified: trunk/src/host/qemu-neo1973/target-i386/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/op.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-i386/op.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -513,8 +513,6 @@
 } UREG64;
 #endif
 
-#ifdef TARGET_X86_64
-
 #define PARAMQ1 \
 ({\
     UREG64 __p;\
@@ -523,6 +521,8 @@
     __p.q;\
 })
 
+#ifdef TARGET_X86_64
+
 void OPPROTO op_movq_T0_im64(void)
 {
     T0 = PARAMQ1;
@@ -1242,13 +1242,53 @@
     helper_ltr_T0();
 }
 
-/* CR registers access */
+/* CR registers access. */
 void OPPROTO op_movl_crN_T0(void)
 {
     helper_movl_crN_T0(PARAM1);
 }
 
+/* These pseudo-opcodes check for SVM intercepts. */
+void OPPROTO op_svm_check_intercept(void)
+{
+    A0 = PARAM1 & PARAM2;
+    svm_check_intercept(PARAMQ1);
+}
+
+void OPPROTO op_svm_check_intercept_param(void)
+{
+    A0 = PARAM1 & PARAM2;
+    svm_check_intercept_param(PARAMQ1, T1);
+}
+
+void OPPROTO op_svm_vmexit(void)
+{
+    A0 = PARAM1 & PARAM2;
+    vmexit(PARAMQ1, T1);
+}
+
+void OPPROTO op_geneflags(void)
+{
+    CC_SRC = cc_table[CC_OP].compute_all();
+}
+
+/* This pseudo-opcode checks for IO intercepts. */
 #if !defined(CONFIG_USER_ONLY)
+void OPPROTO op_svm_check_intercept_io(void)
+{
+    A0 = PARAM1 & PARAM2;
+    /* PARAMQ1 = TYPE (0 = OUT, 1 = IN; 4 = STRING; 8 = REP)
+       T0      = PORT
+       T1      = next eip */
+    stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), T1);
+    /* ASIZE does not appear on real hw */
+    svm_check_intercept_param(SVM_EXIT_IOIO,
+                              (PARAMQ1 & ~SVM_IOIO_ASIZE_MASK) |
+                              ((T0 & 0xffff) << 16));
+}
+#endif
+
+#if !defined(CONFIG_USER_ONLY)
 void OPPROTO op_movtl_T0_cr8(void)
 {
     T0 = cpu_get_apic_tpr(env);
@@ -2452,3 +2492,45 @@
 
 #define SHIFT 1
 #include "ops_sse.h"
+
+/* Secure Virtual Machine ops */
+
+void OPPROTO op_vmrun(void)
+{
+    helper_vmrun(EAX);
+}
+
+void OPPROTO op_vmmcall(void)
+{
+    helper_vmmcall();
+}
+
+void OPPROTO op_vmload(void)
+{
+    helper_vmload(EAX);
+}
+
+void OPPROTO op_vmsave(void)
+{
+    helper_vmsave(EAX);
+}
+
+void OPPROTO op_stgi(void)
+{
+    helper_stgi();
+}
+
+void OPPROTO op_clgi(void)
+{
+    helper_clgi();
+}
+
+void OPPROTO op_skinit(void)
+{
+    helper_skinit();
+}
+
+void OPPROTO op_invlpga(void)
+{
+    helper_invlpga();
+}

Added: trunk/src/host/qemu-neo1973/target-i386/svm.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/svm.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-i386/svm.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,358 @@
+#ifndef __SVM_H
+#define __SVM_H
+
+enum {
+        /* We shift all the intercept bits so we can OR them with the
+           TB flags later on */
+	INTERCEPT_INTR = HF_HIF_SHIFT,
+	INTERCEPT_NMI,
+	INTERCEPT_SMI,
+	INTERCEPT_INIT,
+	INTERCEPT_VINTR,
+	INTERCEPT_SELECTIVE_CR0,
+	INTERCEPT_STORE_IDTR,
+	INTERCEPT_STORE_GDTR,
+	INTERCEPT_STORE_LDTR,
+	INTERCEPT_STORE_TR,
+	INTERCEPT_LOAD_IDTR,
+	INTERCEPT_LOAD_GDTR,
+	INTERCEPT_LOAD_LDTR,
+	INTERCEPT_LOAD_TR,
+	INTERCEPT_RDTSC,
+	INTERCEPT_RDPMC,
+	INTERCEPT_PUSHF,
+	INTERCEPT_POPF,
+	INTERCEPT_CPUID,
+	INTERCEPT_RSM,
+	INTERCEPT_IRET,
+	INTERCEPT_INTn,
+	INTERCEPT_INVD,
+	INTERCEPT_PAUSE,
+	INTERCEPT_HLT,
+	INTERCEPT_INVLPG,
+	INTERCEPT_INVLPGA,
+	INTERCEPT_IOIO_PROT,
+	INTERCEPT_MSR_PROT,
+	INTERCEPT_TASK_SWITCH,
+	INTERCEPT_FERR_FREEZE,
+	INTERCEPT_SHUTDOWN,
+	INTERCEPT_VMRUN,
+	INTERCEPT_VMMCALL,
+	INTERCEPT_VMLOAD,
+	INTERCEPT_VMSAVE,
+	INTERCEPT_STGI,
+	INTERCEPT_CLGI,
+	INTERCEPT_SKINIT,
+	INTERCEPT_RDTSCP,
+	INTERCEPT_ICEBP,
+	INTERCEPT_WBINVD,
+};
+/* This is not really an intercept but rather a placeholder to
+   show that we are in an SVM (just like a hidden flag, but keeps the
+   TBs clean) */
+#define INTERCEPT_SVM 63
+#define INTERCEPT_SVM_MASK (1ULL << INTERCEPT_SVM)
+
+struct __attribute__ ((__packed__)) vmcb_control_area {
+	uint16_t intercept_cr_read;
+	uint16_t intercept_cr_write;
+	uint16_t intercept_dr_read;
+	uint16_t intercept_dr_write;
+	uint32_t intercept_exceptions;
+	uint64_t intercept;
+	uint8_t reserved_1[44];
+	uint64_t iopm_base_pa;
+	uint64_t msrpm_base_pa;
+	uint64_t tsc_offset;
+	uint32_t asid;
+	uint8_t tlb_ctl;
+	uint8_t reserved_2[3];
+	uint32_t int_ctl;
+	uint32_t int_vector;
+	uint32_t int_state;
+	uint8_t reserved_3[4];
+	uint32_t exit_code;
+	uint32_t exit_code_hi;
+	uint64_t exit_info_1;
+	uint64_t exit_info_2;
+	uint32_t exit_int_info;
+	uint32_t exit_int_info_err;
+	uint64_t nested_ctl;
+	uint8_t reserved_4[16];
+	uint32_t event_inj;
+	uint32_t event_inj_err;
+	uint64_t nested_cr3;
+	uint64_t lbr_ctl;
+	uint8_t reserved_5[832];
+};
+
+
+#define TLB_CONTROL_DO_NOTHING 0
+#define TLB_CONTROL_FLUSH_ALL_ASID 1
+
+#define V_TPR_MASK 0x0f
+
+#define V_IRQ_SHIFT 8
+#define V_IRQ_MASK (1 << V_IRQ_SHIFT)
+
+#define V_INTR_PRIO_SHIFT 16
+#define V_INTR_PRIO_MASK (0x0f << V_INTR_PRIO_SHIFT)
+
+#define V_IGN_TPR_SHIFT 20
+#define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT)
+
+#define V_INTR_MASKING_SHIFT 24
+#define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
+
+#define SVM_INTERRUPT_SHADOW_MASK 1
+
+#define SVM_IOIO_STR_SHIFT 2
+#define SVM_IOIO_REP_SHIFT 3
+#define SVM_IOIO_SIZE_SHIFT 4
+#define SVM_IOIO_ASIZE_SHIFT 7
+
+#define SVM_IOIO_TYPE_MASK 1
+#define SVM_IOIO_STR_MASK (1 << SVM_IOIO_STR_SHIFT)
+#define SVM_IOIO_REP_MASK (1 << SVM_IOIO_REP_SHIFT)
+#define SVM_IOIO_SIZE_MASK (7 << SVM_IOIO_SIZE_SHIFT)
+#define SVM_IOIO_ASIZE_MASK (7 << SVM_IOIO_ASIZE_SHIFT)
+
+struct __attribute__ ((__packed__)) vmcb_seg {
+	uint16_t selector;
+	uint16_t attrib;
+	uint32_t limit;
+	uint64_t base;
+};
+
+struct __attribute__ ((__packed__)) vmcb_save_area {
+	struct vmcb_seg es;
+	struct vmcb_seg cs;
+	struct vmcb_seg ss;
+	struct vmcb_seg ds;
+	struct vmcb_seg fs;
+	struct vmcb_seg gs;
+	struct vmcb_seg gdtr;
+	struct vmcb_seg ldtr;
+	struct vmcb_seg idtr;
+	struct vmcb_seg tr;
+	uint8_t reserved_1[43];
+	uint8_t cpl;
+	uint8_t reserved_2[4];
+	uint64_t efer;
+	uint8_t reserved_3[112];
+	uint64_t cr4;
+	uint64_t cr3;
+	uint64_t cr0;
+	uint64_t dr7;
+	uint64_t dr6;
+	uint64_t rflags;
+	uint64_t rip;
+	uint8_t reserved_4[88];
+	uint64_t rsp;
+	uint8_t reserved_5[24];
+	uint64_t rax;
+	uint64_t star;
+	uint64_t lstar;
+	uint64_t cstar;
+	uint64_t sfmask;
+	uint64_t kernel_gs_base;
+	uint64_t sysenter_cs;
+	uint64_t sysenter_esp;
+	uint64_t sysenter_eip;
+	uint64_t cr2;
+	/* qemu: cr8 added to reuse this as hsave */
+	uint64_t cr8;
+	uint8_t reserved_6[32 - 8]; /* originally 32 */
+	uint64_t g_pat;
+	uint64_t dbgctl;
+	uint64_t br_from;
+	uint64_t br_to;
+	uint64_t last_excp_from;
+	uint64_t last_excp_to;
+};
+
+struct __attribute__ ((__packed__)) vmcb {
+	struct vmcb_control_area control;
+	struct vmcb_save_area save;
+};
+
+#define SVM_CPUID_FEATURE_SHIFT 2
+#define SVM_CPUID_FUNC 0x8000000a
+
+#define MSR_EFER_SVME_MASK (1ULL << 12)
+
+#define SVM_SELECTOR_S_SHIFT 4
+#define SVM_SELECTOR_DPL_SHIFT 5
+#define SVM_SELECTOR_P_SHIFT 7
+#define SVM_SELECTOR_AVL_SHIFT 8
+#define SVM_SELECTOR_L_SHIFT 9
+#define SVM_SELECTOR_DB_SHIFT 10
+#define SVM_SELECTOR_G_SHIFT 11
+
+#define SVM_SELECTOR_TYPE_MASK (0xf)
+#define SVM_SELECTOR_S_MASK (1 << SVM_SELECTOR_S_SHIFT)
+#define SVM_SELECTOR_DPL_MASK (3 << SVM_SELECTOR_DPL_SHIFT)
+#define SVM_SELECTOR_P_MASK (1 << SVM_SELECTOR_P_SHIFT)
+#define SVM_SELECTOR_AVL_MASK (1 << SVM_SELECTOR_AVL_SHIFT)
+#define SVM_SELECTOR_L_MASK (1 << SVM_SELECTOR_L_SHIFT)
+#define SVM_SELECTOR_DB_MASK (1 << SVM_SELECTOR_DB_SHIFT)
+#define SVM_SELECTOR_G_MASK (1 << SVM_SELECTOR_G_SHIFT)
+
+#define SVM_SELECTOR_WRITE_MASK (1 << 1)
+#define SVM_SELECTOR_READ_MASK SVM_SELECTOR_WRITE_MASK
+#define SVM_SELECTOR_CODE_MASK (1 << 3)
+
+#define INTERCEPT_CR0_MASK 1
+#define INTERCEPT_CR3_MASK (1 << 3)
+#define INTERCEPT_CR4_MASK (1 << 4)
+
+#define INTERCEPT_DR0_MASK 1
+#define INTERCEPT_DR1_MASK (1 << 1)
+#define INTERCEPT_DR2_MASK (1 << 2)
+#define INTERCEPT_DR3_MASK (1 << 3)
+#define INTERCEPT_DR4_MASK (1 << 4)
+#define INTERCEPT_DR5_MASK (1 << 5)
+#define INTERCEPT_DR6_MASK (1 << 6)
+#define INTERCEPT_DR7_MASK (1 << 7)
+
+#define SVM_EVTINJ_VEC_MASK 0xff
+
+#define SVM_EVTINJ_TYPE_SHIFT 8
+#define SVM_EVTINJ_TYPE_MASK (7 << SVM_EVTINJ_TYPE_SHIFT)
+
+#define SVM_EVTINJ_TYPE_INTR (0 << SVM_EVTINJ_TYPE_SHIFT)
+#define SVM_EVTINJ_TYPE_NMI (2 << SVM_EVTINJ_TYPE_SHIFT)
+#define SVM_EVTINJ_TYPE_EXEPT (3 << SVM_EVTINJ_TYPE_SHIFT)
+#define SVM_EVTINJ_TYPE_SOFT (4 << SVM_EVTINJ_TYPE_SHIFT)
+
+#define SVM_EVTINJ_VALID (1 << 31)
+#define SVM_EVTINJ_VALID_ERR (1 << 11)
+
+#define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK
+
+#define	SVM_EXITINTINFO_TYPE_INTR SVM_EVTINJ_TYPE_INTR
+#define	SVM_EXITINTINFO_TYPE_NMI SVM_EVTINJ_TYPE_NMI
+#define	SVM_EXITINTINFO_TYPE_EXEPT SVM_EVTINJ_TYPE_EXEPT
+#define	SVM_EXITINTINFO_TYPE_SOFT SVM_EVTINJ_TYPE_SOFT
+
+#define SVM_EXITINTINFO_VALID SVM_EVTINJ_VALID
+#define SVM_EXITINTINFO_VALID_ERR SVM_EVTINJ_VALID_ERR
+
+#define	SVM_EXIT_READ_CR0 	0x000
+#define	SVM_EXIT_READ_CR3 	0x003
+#define	SVM_EXIT_READ_CR4 	0x004
+#define	SVM_EXIT_READ_CR8 	0x008
+#define	SVM_EXIT_WRITE_CR0 	0x010
+#define	SVM_EXIT_WRITE_CR3 	0x013
+#define	SVM_EXIT_WRITE_CR4 	0x014
+#define	SVM_EXIT_WRITE_CR8 	0x018
+#define	SVM_EXIT_READ_DR0 	0x020
+#define	SVM_EXIT_READ_DR1 	0x021
+#define	SVM_EXIT_READ_DR2 	0x022
+#define	SVM_EXIT_READ_DR3 	0x023
+#define	SVM_EXIT_READ_DR4 	0x024
+#define	SVM_EXIT_READ_DR5 	0x025
+#define	SVM_EXIT_READ_DR6 	0x026
+#define	SVM_EXIT_READ_DR7 	0x027
+#define	SVM_EXIT_WRITE_DR0 	0x030
+#define	SVM_EXIT_WRITE_DR1 	0x031
+#define	SVM_EXIT_WRITE_DR2 	0x032
+#define	SVM_EXIT_WRITE_DR3 	0x033
+#define	SVM_EXIT_WRITE_DR4 	0x034
+#define	SVM_EXIT_WRITE_DR5 	0x035
+#define	SVM_EXIT_WRITE_DR6 	0x036
+#define	SVM_EXIT_WRITE_DR7 	0x037
+#define SVM_EXIT_EXCP_BASE      0x040
+#define SVM_EXIT_INTR		0x060
+#define SVM_EXIT_NMI		0x061
+#define SVM_EXIT_SMI		0x062
+#define SVM_EXIT_INIT		0x063
+#define SVM_EXIT_VINTR		0x064
+#define SVM_EXIT_CR0_SEL_WRITE	0x065
+#define SVM_EXIT_IDTR_READ	0x066
+#define SVM_EXIT_GDTR_READ	0x067
+#define SVM_EXIT_LDTR_READ	0x068
+#define SVM_EXIT_TR_READ	0x069
+#define SVM_EXIT_IDTR_WRITE	0x06a
+#define SVM_EXIT_GDTR_WRITE	0x06b
+#define SVM_EXIT_LDTR_WRITE	0x06c
+#define SVM_EXIT_TR_WRITE	0x06d
+#define SVM_EXIT_RDTSC		0x06e
+#define SVM_EXIT_RDPMC		0x06f
+#define SVM_EXIT_PUSHF		0x070
+#define SVM_EXIT_POPF		0x071
+#define SVM_EXIT_CPUID		0x072
+#define SVM_EXIT_RSM		0x073
+#define SVM_EXIT_IRET		0x074
+#define SVM_EXIT_SWINT		0x075
+#define SVM_EXIT_INVD		0x076
+#define SVM_EXIT_PAUSE		0x077
+#define SVM_EXIT_HLT		0x078
+#define SVM_EXIT_INVLPG		0x079
+#define SVM_EXIT_INVLPGA	0x07a
+#define SVM_EXIT_IOIO		0x07b
+#define SVM_EXIT_MSR		0x07c
+#define SVM_EXIT_TASK_SWITCH	0x07d
+#define SVM_EXIT_FERR_FREEZE	0x07e
+#define SVM_EXIT_SHUTDOWN	0x07f
+#define SVM_EXIT_VMRUN		0x080
+#define SVM_EXIT_VMMCALL	0x081
+#define SVM_EXIT_VMLOAD		0x082
+#define SVM_EXIT_VMSAVE		0x083
+#define SVM_EXIT_STGI		0x084
+#define SVM_EXIT_CLGI		0x085
+#define SVM_EXIT_SKINIT		0x086
+#define SVM_EXIT_RDTSCP		0x087
+#define SVM_EXIT_ICEBP		0x088
+#define SVM_EXIT_WBINVD		0x089
+/* only included in documentation, maybe wrong */
+#define SVM_EXIT_MONITOR	0x08a
+#define SVM_EXIT_MWAIT		0x08b
+#define SVM_EXIT_NPF  		0x400
+
+#define SVM_EXIT_ERR		-1
+
+#define SVM_CR0_SELECTIVE_MASK (1 << 3 | 1) /* TS and MP */
+
+#define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda"
+#define SVM_VMRUN  ".byte 0x0f, 0x01, 0xd8"
+#define SVM_VMSAVE ".byte 0x0f, 0x01, 0xdb"
+#define SVM_CLGI   ".byte 0x0f, 0x01, 0xdd"
+#define SVM_STGI   ".byte 0x0f, 0x01, 0xdc"
+#define SVM_INVLPGA ".byte 0x0f, 0x01, 0xdf"
+
+/* function references */
+
+void helper_stgi();
+void vmexit(uint64_t exit_code, uint64_t exit_info_1);
+int svm_check_intercept_param(uint32_t type, uint64_t param);
+static inline int svm_check_intercept(unsigned int type) {
+    return svm_check_intercept_param(type, 0);
+}
+
+
+#define INTERCEPTED(mask) (env->intercept & mask)
+#define INTERCEPTEDw(var, mask) (env->intercept ## var & mask)
+#define INTERCEPTEDl(var, mask) (env->intercept ## var & mask)
+
+#define SVM_LOAD_SEG(addr, seg_index, seg) \
+    cpu_x86_load_seg_cache(env, \
+                    R_##seg_index, \
+                    lduw_phys(addr + offsetof(struct vmcb, save.seg.selector)),\
+                    ldq_phys(addr + offsetof(struct vmcb, save.seg.base)),\
+                    ldl_phys(addr + offsetof(struct vmcb, save.seg.limit)),\
+                    vmcb2cpu_attrib(lduw_phys(addr + offsetof(struct vmcb, save.seg.attrib)), ldq_phys(addr + offsetof(struct vmcb, save.seg.base)), ldl_phys(addr + offsetof(struct vmcb, save.seg.limit))))
+
+#define SVM_LOAD_SEG2(addr, seg_qemu, seg_vmcb) \
+    env->seg_qemu.selector  = lduw_phys(addr + offsetof(struct vmcb, save.seg_vmcb.selector)); \
+    env->seg_qemu.base      = ldq_phys(addr + offsetof(struct vmcb, save.seg_vmcb.base)); \
+    env->seg_qemu.limit     = ldl_phys(addr + offsetof(struct vmcb, save.seg_vmcb.limit)); \
+    env->seg_qemu.flags     = vmcb2cpu_attrib(lduw_phys(addr + offsetof(struct vmcb, save.seg_vmcb.attrib)), env->seg_qemu.base, env->seg_qemu.limit)
+
+#define SVM_SAVE_SEG(addr, seg_qemu, seg_vmcb) \
+    stw_phys(addr + offsetof(struct vmcb, save.seg_vmcb.selector), env->seg_qemu.selector); \
+    stq_phys(addr + offsetof(struct vmcb, save.seg_vmcb.base), env->seg_qemu.base); \
+    stl_phys(addr + offsetof(struct vmcb, save.seg_vmcb.limit), env->seg_qemu.limit); \
+    stw_phys(addr + offsetof(struct vmcb, save.seg_vmcb.attrib), cpu2vmcb_attrib(env->seg_qemu.flags))
+
+#endif

Modified: trunk/src/host/qemu-neo1973/target-i386/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/translate.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-i386/translate.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -95,7 +95,7 @@
     int singlestep_enabled; /* "hardware" single step enabled */
     int jmp_opt; /* use direct block chaining for direct jumps */
     int mem_index; /* select memory access functions */
-    int flags; /* all execution flags */
+    uint64_t flags; /* all execution flags */
     struct TranslationBlock *tb;
     int popl_esp_hack; /* for correct popl with esp base handling */
     int rip_offset; /* only used in x86_64, but left for simplicity */
@@ -1995,6 +1995,98 @@
     }
 }
 
+#ifdef TARGET_X86_64
+#define SVM_movq_T1_im(x) gen_op_movq_T1_im64((x) >> 32, x)
+#else
+#define SVM_movq_T1_im(x) gen_op_movl_T1_im(x)
+#endif
+
+static inline int
+gen_svm_check_io(DisasContext *s, target_ulong pc_start, uint64_t type)
+{
+#if !defined(CONFIG_USER_ONLY)
+    if(s->flags & (1ULL << INTERCEPT_IOIO_PROT)) {
+        if (s->cc_op != CC_OP_DYNAMIC)
+            gen_op_set_cc_op(s->cc_op);
+        SVM_movq_T1_im(s->pc - s->cs_base);
+        gen_jmp_im(pc_start - s->cs_base);
+        gen_op_geneflags();
+        gen_op_svm_check_intercept_io((uint32_t)(type >> 32), (uint32_t)type);
+        s->cc_op = CC_OP_DYNAMIC;
+        /* FIXME: maybe we could move the io intercept vector to the TB as well
+                  so we know if this is an EOB or not ... let's assume it's not
+                  for now. */
+    }
+#endif
+    return 0;
+}
+
+static inline int svm_is_rep(int prefixes)
+{
+    return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
+}
+
+static inline int
+gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
+                              uint64_t type, uint64_t param)
+{
+    if(!(s->flags & (INTERCEPT_SVM_MASK)))
+	/* no SVM activated */
+        return 0;
+    switch(type) {
+        /* CRx and DRx reads/writes */
+        case SVM_EXIT_READ_CR0 ... SVM_EXIT_EXCP_BASE - 1:
+            if (s->cc_op != CC_OP_DYNAMIC) {
+                gen_op_set_cc_op(s->cc_op);
+                s->cc_op = CC_OP_DYNAMIC;
+            }
+            gen_jmp_im(pc_start - s->cs_base);
+            SVM_movq_T1_im(param);
+            gen_op_geneflags();
+            gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type);
+            /* this is a special case as we do not know if the interception occurs
+               so we assume there was none */
+            return 0;
+        case SVM_EXIT_MSR:
+            if(s->flags & (1ULL << INTERCEPT_MSR_PROT)) {
+                if (s->cc_op != CC_OP_DYNAMIC) {
+                    gen_op_set_cc_op(s->cc_op);
+                    s->cc_op = CC_OP_DYNAMIC;
+                }
+                gen_jmp_im(pc_start - s->cs_base);
+                SVM_movq_T1_im(param);
+                gen_op_geneflags();
+                gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type);
+                /* this is a special case as we do not know if the interception occurs
+                   so we assume there was none */
+                return 0;
+            }
+            break;
+        default:
+            if(s->flags & (1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR))) {
+                if (s->cc_op != CC_OP_DYNAMIC) {
+                    gen_op_set_cc_op(s->cc_op);
+		    s->cc_op = CC_OP_EFLAGS;
+                }
+                gen_jmp_im(pc_start - s->cs_base);
+                SVM_movq_T1_im(param);
+                gen_op_geneflags();
+                gen_op_svm_vmexit(type >> 32, type);
+                /* we can optimize this one so TBs don't get longer
+                   than up to vmexit */
+                gen_eob(s);
+                return 1;
+            }
+    }
+    return 0;
+}
+
+static inline int
+gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
+{
+    return gen_svm_check_intercept_param(s, pc_start, type, 0);
+}
+
 static inline void gen_stack_update(DisasContext *s, int addend)
 {
 #ifdef TARGET_X86_64
@@ -4880,6 +4972,12 @@
         else
             ot = dflag ? OT_LONG : OT_WORD;
         gen_check_io(s, ot, 1, pc_start - s->cs_base);
+        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
+        gen_op_andl_T0_ffff();
+        if (gen_svm_check_io(s, pc_start,
+                             SVM_IOIO_TYPE_MASK | (1 << (4+ot)) |
+                             svm_is_rep(prefixes) | 4 | (1 << (7+s->aflag))))
+            break;
         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
             gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
         } else {
@@ -4893,6 +4991,12 @@
         else
             ot = dflag ? OT_LONG : OT_WORD;
         gen_check_io(s, ot, 1, pc_start - s->cs_base);
+        gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
+        gen_op_andl_T0_ffff();
+        if (gen_svm_check_io(s, pc_start,
+                             (1 << (4+ot)) | svm_is_rep(prefixes) |
+                             4 | (1 << (7+s->aflag))))
+            break;
         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
             gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
         } else {
@@ -4902,6 +5006,7 @@
 
         /************************/
         /* port I/O */
+
     case 0xe4:
     case 0xe5:
         if ((b & 1) == 0)
@@ -4911,6 +5016,10 @@
         val = ldub_code(s->pc++);
         gen_op_movl_T0_im(val);
         gen_check_io(s, ot, 0, pc_start - s->cs_base);
+        if (gen_svm_check_io(s, pc_start,
+                             SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
+                             (1 << (4+ot))))
+            break;
         gen_op_in[ot]();
         gen_op_mov_reg_T1[ot][R_EAX]();
         break;
@@ -4923,6 +5032,9 @@
         val = ldub_code(s->pc++);
         gen_op_movl_T0_im(val);
         gen_check_io(s, ot, 0, pc_start - s->cs_base);
+        if (gen_svm_check_io(s, pc_start, svm_is_rep(prefixes) |
+                             (1 << (4+ot))))
+            break;
         gen_op_mov_TN_reg[ot][1][R_EAX]();
         gen_op_out[ot]();
         break;
@@ -4935,6 +5047,10 @@
         gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
         gen_op_andl_T0_ffff();
         gen_check_io(s, ot, 0, pc_start - s->cs_base);
+        if (gen_svm_check_io(s, pc_start,
+                             SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) |
+                             (1 << (4+ot))))
+            break;
         gen_op_in[ot]();
         gen_op_mov_reg_T1[ot][R_EAX]();
         break;
@@ -4947,6 +5063,9 @@
         gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
         gen_op_andl_T0_ffff();
         gen_check_io(s, ot, 0, pc_start - s->cs_base);
+        if (gen_svm_check_io(s, pc_start,
+                             svm_is_rep(prefixes) | (1 << (4+ot))))
+            break;
         gen_op_mov_TN_reg[ot][1][R_EAX]();
         gen_op_out[ot]();
         break;
@@ -5004,6 +5123,8 @@
         val = 0;
         goto do_lret;
     case 0xcf: /* iret */
+        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET))
+            break;
         if (!s->pe) {
             /* real mode */
             gen_op_iret_real(s->dflag);
@@ -5125,6 +5246,8 @@
         /************************/
         /* flags */
     case 0x9c: /* pushf */
+        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF))
+            break;
         if (s->vm86 && s->iopl != 3) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
         } else {
@@ -5135,6 +5258,8 @@
         }
         break;
     case 0x9d: /* popf */
+        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF))
+            break;
         if (s->vm86 && s->iopl != 3) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
         } else {
@@ -5348,6 +5473,9 @@
         /* XXX: correct lock test for all insn */
         if (prefixes & PREFIX_LOCK)
             goto illegal_op;
+        if (prefixes & PREFIX_REPZ) {
+            gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
+        }
         break;
     case 0x9b: /* fwait */
         if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
@@ -5361,10 +5489,14 @@
         }
         break;
     case 0xcc: /* int3 */
+        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
+            break;
         gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
         break;
     case 0xcd: /* int N */
         val = ldub_code(s->pc++);
+        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
+            break;
         if (s->vm86 && s->iopl != 3) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
         } else {
@@ -5374,12 +5506,16 @@
     case 0xce: /* into */
         if (CODE64(s))
             goto illegal_op;
+        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SWINT))
+            break;
         if (s->cc_op != CC_OP_DYNAMIC)
             gen_op_set_cc_op(s->cc_op);
         gen_jmp_im(pc_start - s->cs_base);
         gen_op_into(s->pc - pc_start);
         break;
     case 0xf1: /* icebp (undocumented, exits to external debugger) */
+        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP))
+            break;
 #if 1
         gen_debug(s, pc_start - s->cs_base);
 #else
@@ -5507,13 +5643,21 @@
         if (s->cpl != 0) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
         } else {
-            if (b & 2)
+            int retval = 0;
+            if (b & 2) {
+                retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 0);
                 gen_op_rdmsr();
-            else
+            } else {
+                retval = gen_svm_check_intercept_param(s, pc_start, SVM_EXIT_MSR, 1);
                 gen_op_wrmsr();
+            }
+            if(retval)
+                gen_eob(s);
         }
         break;
     case 0x131: /* rdtsc */
+        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RDTSC))
+            break;
         gen_jmp_im(pc_start - s->cs_base);
         gen_op_rdtsc();
         break;
@@ -5576,12 +5720,16 @@
         break;
 #endif
     case 0x1a2: /* cpuid */
+        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CPUID))
+            break;
         gen_op_cpuid();
         break;
     case 0xf4: /* hlt */
         if (s->cpl != 0) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
         } else {
+            if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_HLT))
+                break;
             if (s->cc_op != CC_OP_DYNAMIC)
                 gen_op_set_cc_op(s->cc_op);
             gen_jmp_im(s->pc - s->cs_base);
@@ -5597,6 +5745,8 @@
         case 0: /* sldt */
             if (!s->pe || s->vm86)
                 goto illegal_op;
+            if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ))
+                break;
             gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
             ot = OT_WORD;
             if (mod == 3)
@@ -5609,6 +5759,8 @@
             if (s->cpl != 0) {
                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
             } else {
+                if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE))
+                    break;
                 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
                 gen_jmp_im(pc_start - s->cs_base);
                 gen_op_lldt_T0();
@@ -5617,6 +5769,8 @@
         case 1: /* str */
             if (!s->pe || s->vm86)
                 goto illegal_op;
+            if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ))
+                break;
             gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
             ot = OT_WORD;
             if (mod == 3)
@@ -5629,6 +5783,8 @@
             if (s->cpl != 0) {
                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
             } else {
+                if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE))
+                    break;
                 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
                 gen_jmp_im(pc_start - s->cs_base);
                 gen_op_ltr_T0();
@@ -5660,6 +5816,8 @@
         case 0: /* sgdt */
             if (mod == 3)
                 goto illegal_op;
+            if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ))
+                break;
             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
             gen_op_movl_T0_env(offsetof(CPUX86State, gdt.limit));
             gen_op_st_T0_A0[OT_WORD + s->mem_index]();
@@ -5676,6 +5834,8 @@
                     if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
                         s->cpl != 0)
                         goto illegal_op;
+                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MONITOR))
+                        break;
                     gen_jmp_im(pc_start - s->cs_base);
 #ifdef TARGET_X86_64
                     if (s->aflag == 2) {
@@ -5700,6 +5860,8 @@
                         gen_op_set_cc_op(s->cc_op);
                         s->cc_op = CC_OP_DYNAMIC;
                     }
+                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_MWAIT))
+                        break;
                     gen_jmp_im(s->pc - s->cs_base);
                     gen_op_mwait();
                     gen_eob(s);
@@ -5708,6 +5870,8 @@
                     goto illegal_op;
                 }
             } else { /* sidt */
+                if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ))
+                    break;
                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                 gen_op_movl_T0_env(offsetof(CPUX86State, idt.limit));
                 gen_op_st_T0_A0[OT_WORD + s->mem_index]();
@@ -5720,11 +5884,63 @@
             break;
         case 2: /* lgdt */
         case 3: /* lidt */
-            if (mod == 3)
-                goto illegal_op;
-            if (s->cpl != 0) {
+            if (mod == 3) {
+                switch(rm) {
+                case 0: /* VMRUN */
+                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMRUN))
+                        break;
+                    if (s->cc_op != CC_OP_DYNAMIC)
+                        gen_op_set_cc_op(s->cc_op);
+                    gen_jmp_im(s->pc - s->cs_base);
+                    gen_op_vmrun();
+                    s->cc_op = CC_OP_EFLAGS;
+                    gen_eob(s);
+                    break;
+                case 1: /* VMMCALL */
+                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMMCALL))
+                         break;
+                    /* FIXME: cause #UD if hflags & SVM */
+                    gen_op_vmmcall();
+                    break;
+                case 2: /* VMLOAD */
+                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMLOAD))
+                         break;
+                    gen_op_vmload();
+                    break;
+                case 3: /* VMSAVE */
+                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VMSAVE))
+                         break;
+                    gen_op_vmsave();
+                    break;
+                case 4: /* STGI */
+                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_STGI))
+                         break;
+                    gen_op_stgi();
+                    break;
+                case 5: /* CLGI */
+                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_CLGI))
+                         break;
+                    gen_op_clgi();
+                    break;
+                case 6: /* SKINIT */
+                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_SKINIT))
+                         break;
+                    gen_op_skinit();
+                    break;
+                case 7: /* INVLPGA */
+                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPGA))
+                         break;
+                    gen_op_invlpga();
+                    break;
+                default:
+                    goto illegal_op;
+                }
+            } else if (s->cpl != 0) {
                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
             } else {
+                if (gen_svm_check_intercept(s, pc_start,
+                                            op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE))
+                    break;
                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                 gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
                 gen_add_A0_im(s, 2);
@@ -5741,6 +5957,8 @@
             }
             break;
         case 4: /* smsw */
+            if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0))
+                break;
             gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
             gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
             break;
@@ -5748,6 +5966,8 @@
             if (s->cpl != 0) {
                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
             } else {
+                if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0))
+                    break;
                 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
                 gen_op_lmsw_T0();
                 gen_jmp_im(s->pc - s->cs_base);
@@ -5772,6 +5992,8 @@
                         goto illegal_op;
                     }
                 } else {
+                    if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVLPG))
+                        break;
                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
                     gen_op_invlpg_A0();
                     gen_jmp_im(s->pc - s->cs_base);
@@ -5788,6 +6010,8 @@
         if (s->cpl != 0) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
         } else {
+            if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_INVD))
+                break;
             /* nothing to do */
         }
         break;
@@ -5908,11 +6132,13 @@
             case 4:
             case 8:
                 if (b & 2) {
+                    gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0 + reg);
                     gen_op_mov_TN_reg[ot][0][rm]();
                     gen_op_movl_crN_T0(reg);
                     gen_jmp_im(s->pc - s->cs_base);
                     gen_eob(s);
                 } else {
+                    gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0 + reg);
 #if !defined(CONFIG_USER_ONLY)
                     if (reg == 8)
                         gen_op_movtl_T0_cr8();
@@ -5945,11 +6171,13 @@
             if (reg == 4 || reg == 5 || reg >= 8)
                 goto illegal_op;
             if (b & 2) {
+                gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
                 gen_op_mov_TN_reg[ot][0][rm]();
                 gen_op_movl_drN_T0(reg);
                 gen_jmp_im(s->pc - s->cs_base);
                 gen_eob(s);
             } else {
+                gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
                 gen_op_movtl_T0_env(offsetof(CPUX86State,dr[reg]));
                 gen_op_mov_reg_T0[ot][rm]();
             }
@@ -5959,6 +6187,7 @@
         if (s->cpl != 0) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
         } else {
+            gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
             gen_op_clts();
             /* abort block because static cpu state changed */
             gen_jmp_im(s->pc - s->cs_base);
@@ -6050,6 +6279,8 @@
         /* ignore for now */
         break;
     case 0x1aa: /* rsm */
+        if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM))
+            break;
         if (!(s->flags & HF_SMM_MASK))
             goto illegal_op;
         if (s->cc_op != CC_OP_DYNAMIC) {
@@ -6462,7 +6693,8 @@
     DisasContext dc1, *dc = &dc1;
     target_ulong pc_ptr;
     uint16_t *gen_opc_end;
-    int flags, j, lj, cflags;
+    int j, lj, cflags;
+    uint64_t flags;
     target_ulong pc_start;
     target_ulong cs_base;
 

Modified: trunk/src/host/qemu-neo1973/target-m68k/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-m68k/cpu.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-m68k/cpu.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -53,6 +53,8 @@
 #define EXCP_RTE            0x100
 #define EXCP_HALT_INSN      0x101
 
+#define NB_MMU_MODES 2
+
 typedef struct CPUM68KState {
     uint32_t dregs[8];
     uint32_t aregs[8];
@@ -223,6 +225,15 @@
 #define cpu_gen_code cpu_m68k_gen_code
 #define cpu_signal_handler cpu_m68k_signal_handler
 
+/* MMU modes definitions */
+#define MMU_MODE0_SUFFIX _kernel
+#define MMU_MODE1_SUFFIX _user
+#define MMU_USER_IDX 1
+static inline int cpu_mmu_index (CPUState *env)
+{
+    return (env->sr & SR_S) == 0 ? 1 : 0;
+}
+
 #include "cpu-all.h"
 
 #endif

Modified: trunk/src/host/qemu-neo1973/target-m68k/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-m68k/exec.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-m68k/exec.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -38,7 +38,7 @@
 }
 
 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                              int is_user, int is_softmmu);
+                              int mmu_idx, int is_softmmu);
 
 #if !defined(CONFIG_USER_ONLY)
 #include "softmmu_exec.h"

Modified: trunk/src/host/qemu-neo1973/target-m68k/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-m68k/helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-m68k/helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -301,7 +301,7 @@
 #if defined(CONFIG_USER_ONLY)
 
 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                               int is_user, int is_softmmu)
+                               int mmu_idx, int is_softmmu)
 {
     env->exception_index = EXCP_ACCESS;
     env->mmu.ar = address;
@@ -311,13 +311,13 @@
 #else
 
 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                               int is_user, int is_softmmu)
+                               int mmu_idx, int is_softmmu)
 {
     int prot;
 
     address &= TARGET_PAGE_MASK;
     prot = PAGE_READ | PAGE_WRITE;
-    return tlb_set_page(env, address, address, prot, is_user, is_softmmu);
+    return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
 }
 
 /* Notify CPU of a pending interrupt.  Prioritization and vectoring should

Modified: trunk/src/host/qemu-neo1973/target-m68k/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-m68k/op_helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-m68k/op_helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -31,7 +31,11 @@
 extern int semihosting_enabled;
 
 #define MMUSUFFIX _mmu
-#define GETPC() (__builtin_return_address(0))
+#ifdef __s390__
+# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
+#else
+# define GETPC() (__builtin_return_address(0))
+#endif
 
 #define SHIFT 0
 #include "softmmu_template.h"
@@ -49,7 +53,7 @@
    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)
+void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 {
     TranslationBlock *tb;
     CPUState *saved_env;
@@ -60,7 +64,7 @@
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, is_user, 1);
+    ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
     if (__builtin_expect(ret, 0)) {
         if (retaddr) {
             /* now we have a real cpu fault */

Modified: trunk/src/host/qemu-neo1973/target-mips/TODO
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/TODO	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-mips/TODO	2007-10-29 21:14:04 UTC (rev 3303)
@@ -3,18 +3,36 @@
 
 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, the tb misses a flush
-  in that case.
-- gdb breakpoints inside the emulated system work only due to a hack
-  which disassembles over the end of the current tb.
+- Unimplemented ASEs:
+  - MIPS16
+  - MDMX
+  - SmartMIPS
+  - DSP r1
+  - DSP r2
+- MT ASE only partially implemented and not functional
+- Shadow register support only partially implemented,
+  lacks set switching on interrupt/exception.
+- 34K ITC not implemented.
+- A general lack of documentation, especially for technical internals.
+  Existing documentation is x86-centric.
+- Reverse endianness bit not implemented
+- The TLB emulation is very inefficient:
+  Qemu's softmmu implements a x86-style MMU, with separate entries
+  for read/write/execute, a TLB index which is just a modulo of the
+  virtual address, and a set of TLBs for each user/kernel/supervisor
+  MMU mode.
+  MIPS has a single entry for read/write/execute and only one MMU mode.
+  But it is fully associative with randomized entry indices, and uses
+  up to 256 ASID tags as additional matching criterion (which roughly
+  equates to 256 MMU modes). It also has a global flag which causes
+  entries to match regardless of ASID.
+  To cope with these differences, Qemu currently flushes the TLB at
+  each ASID change. Using the MMU modes to implement ASIDs hinges on
+  implementing the global bit efficiently.
 
 MIPS64
 ------
-- Only lighly tested but apparently functional as of 2007-05-31.
+- Userland emulation (both n32 and n64) not functional.
 
 "Generic" 4Kc system emulation
 ------------------------------
@@ -29,3 +47,9 @@
 - 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.
+
+mipssim system emulation
+------------------------
+- The mipsnet.c has a glitch: Booting from NFS root works up until
+  starting /sbin/init, then it Linux hangs with "NFS server not
+  responding".

Modified: trunk/src/host/qemu-neo1973/target-mips/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/cpu.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-mips/cpu.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -107,6 +107,8 @@
 #define FP_UNIMPLEMENTED  32
 };
 
+#define NB_MMU_MODES 3
+
 typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
 struct CPUMIPSMVPContext {
     int32_t CP0_MVPControl;
@@ -283,8 +285,7 @@
 #define CP0St_KX    7
 #define CP0St_SX    6
 #define CP0St_UX    5
-#define CP0St_UM    4
-#define CP0St_R0    3
+#define CP0St_KSU   3
 #define CP0St_ERL   2
 #define CP0St_EXL   1
 #define CP0St_IE    0
@@ -414,24 +415,30 @@
     int user_mode_only; /* user mode only simulation */
     uint32_t hflags;    /* CPU State */
     /* TMASK defines different execution modes */
-#define MIPS_HFLAG_TMASK  0x007F
+#define MIPS_HFLAG_TMASK  0x00FF
 #define MIPS_HFLAG_MODE   0x0007 /* execution modes                    */
-#define MIPS_HFLAG_UM     0x0001 /* user mode                          */
-#define MIPS_HFLAG_DM     0x0002 /* Debug mode                         */
-#define MIPS_HFLAG_SM     0x0004 /* Supervisor mode                    */
+    /* The KSU flags must be the lowest bits in hflags. The flag order
+       must be the same as defined for CP0 Status. This allows to use
+       the bits as the value of mmu_idx. */
+#define MIPS_HFLAG_KSU    0x0003 /* kernel/supervisor/user mode mask   */
+#define MIPS_HFLAG_UM       0x0002 /* user mode flag */
+#define MIPS_HFLAG_SM       0x0001 /* supervisor mode flag */
+#define MIPS_HFLAG_KM       0x0000 /* kernel mode flag */
+#define MIPS_HFLAG_DM     0x0004 /* Debug mode                         */
 #define MIPS_HFLAG_64     0x0008 /* 64-bit instructions enabled        */
-#define MIPS_HFLAG_FPU    0x0010 /* FPU enabled                        */
-#define MIPS_HFLAG_F64    0x0020 /* 64-bit FPU enabled                 */
-#define MIPS_HFLAG_RE     0x0040 /* Reversed endianness                */
+#define MIPS_HFLAG_CP0    0x0010 /* CP0 enabled                        */
+#define MIPS_HFLAG_FPU    0x0020 /* FPU enabled                        */
+#define MIPS_HFLAG_F64    0x0040 /* 64-bit FPU enabled                 */
+#define MIPS_HFLAG_RE     0x0080 /* Reversed endianness                */
     /* If translation is interrupted between the branch instruction and
      * the delay slot, record what type of branch it is so that we can
      * resume translation properly.  It might be possible to reduce
      * this from three bits to two.  */
-#define MIPS_HFLAG_BMASK  0x0380
-#define MIPS_HFLAG_B      0x0080 /* Unconditional branch               */
-#define MIPS_HFLAG_BC     0x0100 /* Conditional branch                 */
-#define MIPS_HFLAG_BL     0x0180 /* Likely branch                      */
-#define MIPS_HFLAG_BR     0x0200 /* branch to register (can't link TB) */
+#define MIPS_HFLAG_BMASK  0x0700
+#define MIPS_HFLAG_B      0x0100 /* Unconditional branch               */
+#define MIPS_HFLAG_BC     0x0200 /* Conditional branch                 */
+#define MIPS_HFLAG_BL     0x0300 /* Likely branch                      */
+#define MIPS_HFLAG_BR     0x0400 /* branch to register (can't link TB) */
     target_ulong btarget;        /* Jump / branch target               */
     int bcond;                   /* Branch condition (if needed)       */
 
@@ -441,6 +448,7 @@
     int CCRes; /* Cycle count resolution/divisor */
     uint32_t CP0_Status_rw_bitmask; /* Read/write bits in CP0_Status */
     uint32_t CP0_TCStatus_rw_bitmask; /* Read/write bits in CP0_TCStatus */
+    int insn_flags; /* Supported instruction set */
 
 #ifdef CONFIG_USER_ONLY
     target_ulong tls_value;
@@ -475,12 +483,27 @@
 void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
 int cpu_mips_register (CPUMIPSState *env, mips_def_t *def);
 
+void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
+                          int unused);
+
 #define CPUState CPUMIPSState
 #define cpu_init cpu_mips_init
 #define cpu_exec cpu_mips_exec
 #define cpu_gen_code cpu_mips_gen_code
 #define cpu_signal_handler cpu_mips_signal_handler
+#define cpu_list mips_cpu_list
 
+/* MMU modes definitions. We carefully match the indices with our
+   hflags layout. */
+#define MMU_MODE0_SUFFIX _kernel
+#define MMU_MODE1_SUFFIX _super
+#define MMU_MODE2_SUFFIX _user
+#define MMU_USER_IDX 2
+static inline int cpu_mmu_index (CPUState *env)
+{
+    return env->hflags & MIPS_HFLAG_KSU;
+}
+
 #include "cpu-all.h"
 
 /* Memory access type :

Modified: trunk/src/host/qemu-neo1973/target-mips/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/exec.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-mips/exec.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -56,7 +56,7 @@
 #include "softmmu_exec.h"
 #endif /* !defined(CONFIG_USER_ONLY) */
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 #if TARGET_LONG_BITS > HOST_LONG_BITS
 void do_dsll (void);
 void do_dsll32 (void);
@@ -70,6 +70,8 @@
 void do_dsrav (void);
 void do_dsrlv (void);
 void do_drotrv (void);
+void do_dclo (void);
+void do_dclz (void);
 #endif
 #endif
 
@@ -84,7 +86,7 @@
 void do_msub (void);
 void do_msubu (void);
 #endif
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 void do_ddiv (void);
 #if TARGET_LONG_BITS > HOST_LONG_BITS
 void do_ddivu (void);
@@ -100,42 +102,12 @@
                     int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags);
 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 TARGET_MIPS64
-void do_ldl_raw (uint64_t);
-void do_ldr_raw (uint64_t);
-uint64_t do_sdl_raw (uint64_t);
-uint64_t do_sdr_raw (uint64_t);
-#endif
-#if !defined(CONFIG_USER_ONLY)
-void do_lwl_user (uint32_t);
-void do_lwl_kernel (uint32_t);
-void do_lwr_user (uint32_t);
-void do_lwr_kernel (uint32_t);
-uint32_t do_swl_user (uint32_t);
-uint32_t do_swl_kernel (uint32_t);
-uint32_t do_swr_user (uint32_t);
-uint32_t do_swr_kernel (uint32_t);
-#ifdef TARGET_MIPS64
-void do_ldl_user (uint64_t);
-void do_ldl_kernel (uint64_t);
-void do_ldr_user (uint64_t);
-void do_ldr_kernel (uint64_t);
-uint64_t do_sdl_user (uint64_t);
-uint64_t do_sdl_kernel (uint64_t);
-uint64_t do_sdr_user (uint64_t);
-uint64_t do_sdr_kernel (uint64_t);
-#endif
-#endif
 void do_pmon (int function);
 
 void dump_sc (void);
 
 int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                               int is_user, int is_softmmu);
+                               int mmu_idx, int is_softmmu);
 void do_interrupt (CPUState *env);
 void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra);
 
@@ -153,6 +125,8 @@
 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_start_count(CPUState *env);
+void cpu_mips_stop_count(CPUState *env);
 void cpu_mips_update_irq (CPUState *env);
 void cpu_mips_clock_init (CPUState *env);
 void cpu_mips_tlb_flush (CPUState *env, int flush_global);
@@ -233,15 +207,16 @@
 FOP_PROTO(ngt)
 #undef FOP_PROTO
 
-static inline void env_to_regs(void)
+static always_inline void env_to_regs(void)
 {
 }
 
-static inline void regs_to_env(void)
+static always_inline void regs_to_env(void)
 {
 }
 
-static inline int cpu_halted(CPUState *env) {
+static always_inline int cpu_halted(CPUState *env)
+{
     if (!env->halted)
         return 0;
     if (env->interrupt_request &
@@ -252,4 +227,28 @@
     return EXCP_HALTED;
 }
 
+static always_inline void compute_hflags(CPUState *env)
+{
+    env->hflags &= ~(MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 |
+                     MIPS_HFLAG_FPU | MIPS_HFLAG_KSU);
+    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
+        !(env->CP0_Status & (1 << CP0St_ERL)) &&
+        !(env->hflags & MIPS_HFLAG_DM)) {
+        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
+    }
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
+        (env->CP0_Status & (1 << CP0St_PX)) ||
+        (env->CP0_Status & (1 << CP0St_UX)))
+        env->hflags |= MIPS_HFLAG_64;
+#endif
+    if ((env->CP0_Status & (1 << CP0St_CU0)) ||
+        !(env->hflags & MIPS_HFLAG_KSU))
+        env->hflags |= MIPS_HFLAG_CP0;
+    if (env->CP0_Status & (1 << CP0St_CU1))
+        env->hflags |= MIPS_HFLAG_FPU;
+    if (env->CP0_Status & (1 << CP0St_FR))
+        env->hflags |= MIPS_HFLAG_F64;
+}
+
 #endif /* !defined(__QEMU_MIPS_EXEC_H__) */

Modified: trunk/src/host/qemu-neo1973/target-mips/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-mips/helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -76,7 +76,7 @@
         target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
         target_ulong tag = address & ~mask;
         target_ulong VPN = tlb->VPN & ~mask;
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
         tag &= env->SEGMask;
 #endif
 
@@ -106,7 +106,9 @@
 {
     /* User mode can only access useg/xuseg */
     int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM;
-#ifdef TARGET_MIPS64
+    int supervisor_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_SM;
+    int kernel_mode = !user_mode && !supervisor_mode;
+#if defined(TARGET_MIPSN32) || defined(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;
@@ -120,14 +122,6 @@
     }
 #endif
 
-#ifdef TARGET_MIPS64
-    if (user_mode && address > 0x3FFFFFFFFFFFFFFFULL)
-        return TLBRET_BADADDR;
-#else
-    if (user_mode && address > 0x7FFFFFFFUL)
-        return TLBRET_BADADDR;
-#endif
-
     if (address <= (int32_t)0x7FFFFFFFUL) {
         /* useg */
         if (env->CP0_Status & (1 << CP0St_ERL)) {
@@ -136,39 +130,36 @@
         } else {
             ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
         }
-#ifdef TARGET_MIPS64
-/*
-   XXX: Assuming :
-   - PABITS = 36 (correct for MIPS64R1)
-*/
-    } else if (address < 0x3FFFFFFFFFFFFFFFULL) {
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+    } else if (address < 0x4000000000000000ULL) {
         /* xuseg */
 	if (UX && address < (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) {
             ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
 	} else {
 	    ret = TLBRET_BADADDR;
         }
-    } else if (address < 0x7FFFFFFFFFFFFFFFULL) {
+    } else if (address < 0x8000000000000000ULL) {
         /* xsseg */
-	if (SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) {
+	if ((supervisor_mode || kernel_mode) &&
+	    SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) {
             ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
 	} else {
 	    ret = TLBRET_BADADDR;
         }
-    } else if (address < 0xBFFFFFFFFFFFFFFFULL) {
+    } else if (address < 0xC000000000000000ULL) {
         /* xkphys */
-        /* XXX: check supervisor mode */
-        if (KX && (address & 0x07FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL)
-	{
-            *physical = address & 0X0000000FFFFFFFFFULL;
+        /* XXX: Assumes PABITS = 36 (correct for MIPS64R1) */
+        if (kernel_mode && KX &&
+            (address & 0x07FFFFFFFFFFFFFFULL) < 0x0000000FFFFFFFFFULL) {
+            *physical = address & 0x0000000FFFFFFFFFULL;
             *prot = PAGE_READ | PAGE_WRITE;
 	} else {
 	    ret = TLBRET_BADADDR;
 	}
-    } else if (address < 0xFFFFFFFF7FFFFFFFULL) {
+    } else if (address < 0xFFFFFFFF80000000ULL) {
         /* xkseg */
-        /* XXX: check supervisor mode */
-	if (KX && address < (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) {
+	if (kernel_mode && KX &&
+	    address < (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) {
             ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
 	} else {
 	    ret = TLBRET_BADADDR;
@@ -176,22 +167,35 @@
 #endif
     } else if (address < (int32_t)0xA0000000UL) {
         /* kseg0 */
-        /* XXX: check supervisor mode */
-        *physical = address - (int32_t)0x80000000UL;
-        *prot = PAGE_READ | PAGE_WRITE;
+        if (kernel_mode) {
+            *physical = address - (int32_t)0x80000000UL;
+            *prot = PAGE_READ | PAGE_WRITE;
+        } else {
+            ret = TLBRET_BADADDR;
+        }
     } else if (address < (int32_t)0xC0000000UL) {
         /* kseg1 */
-        /* XXX: check supervisor mode */
-        *physical = address - (int32_t)0xA0000000UL;
-        *prot = PAGE_READ | PAGE_WRITE;
+        if (kernel_mode) {
+            *physical = address - (int32_t)0xA0000000UL;
+            *prot = PAGE_READ | PAGE_WRITE;
+        } else {
+            ret = TLBRET_BADADDR;
+        }
     } else if (address < (int32_t)0xE0000000UL) {
-        /* kseg2 */
-        ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
+        /* sseg (kseg2) */
+        if (supervisor_mode || kernel_mode) {
+            ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
+        } else {
+            ret = TLBRET_BADADDR;
+        }
     } else {
         /* kseg3 */
-        /* XXX: check supervisor mode */
         /* XXX: debug segment is not emulated */
-        ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
+        if (kernel_mode) {
+            ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
+        } else {
+            ret = TLBRET_BADADDR;
+        }
     }
 #if 0
     if (logfile) {
@@ -225,7 +229,7 @@
 #endif /* !defined(CONFIG_USER_ONLY) */
 
 int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                               int is_user, int is_softmmu)
+                               int mmu_idx, int is_softmmu)
 {
     target_ulong physical;
     int prot;
@@ -237,8 +241,8 @@
 #if 0
         cpu_dump_state(env, logfile, fprintf, 0);
 #endif
-        fprintf(logfile, "%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d is_user %d smmu %d\n",
-                __func__, env->PC[env->current_tc], address, rw, is_user, is_softmmu);
+        fprintf(logfile, "%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d mmu_idx %d smmu %d\n",
+                __func__, env->PC[env->current_tc], address, rw, mmu_idx, is_softmmu);
     }
 
     rw &= 1;
@@ -261,7 +265,7 @@
     if (ret == TLBRET_MATCH) {
        ret = tlb_set_page(env, address & TARGET_PAGE_MASK,
                           physical & TARGET_PAGE_MASK, prot,
-                          is_user, is_softmmu);
+                          mmu_idx, is_softmmu);
     } else if (ret < 0) {
     do_fault:
         switch (ret) {
@@ -301,7 +305,7 @@
 	                   ((address >> 9) &   0x007ffff0);
         env->CP0_EntryHi =
             (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1));
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
         env->CP0_EntryHi &= env->SEGMask;
         env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) |
                             ((address & 0xC00000000000ULL) >> (env->SEGBITS - 9)) |
@@ -368,10 +372,8 @@
             env->CP0_DEPC = env->PC[env->current_tc];
         }
     enter_debug_mode:
-        env->hflags |= MIPS_HFLAG_DM;
-        if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
-            env->hflags |= MIPS_HFLAG_64;
-        env->hflags &= ~MIPS_HFLAG_UM;
+        env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
+        env->hflags &= ~(MIPS_HFLAG_KSU);
         /* EJTAG probe trap enable is not implemented... */
         if (!(env->CP0_Status & (1 << CP0St_EXL)))
             env->CP0_Cause &= ~(1 << CP0Ca_BD);
@@ -396,9 +398,8 @@
             env->CP0_ErrorEPC = env->PC[env->current_tc];
         }
         env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
-        if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
-            env->hflags |= MIPS_HFLAG_64;
-        env->hflags &= ~MIPS_HFLAG_UM;
+        env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
+        env->hflags &= ~(MIPS_HFLAG_KSU);
         if (!(env->CP0_Status & (1 << CP0St_EXL)))
             env->CP0_Cause &= ~(1 << CP0Ca_BD);
         env->PC[env->current_tc] = (int32_t)0xBFC00000;
@@ -424,7 +425,7 @@
     case EXCP_TLBL:
         cause = 2;
         if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
             int R = env->CP0_BadVAddr >> 62;
             int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
             int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
@@ -471,11 +472,8 @@
         goto set_EPC;
     case EXCP_TLBS:
         cause = 3;
-        goto set_EPC;
-    case EXCP_THREAD:
-        cause = 25;
         if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
             int R = env->CP0_BadVAddr >> 62;
             int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
             int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
@@ -487,6 +485,9 @@
 #endif
                 offset = 0x000;
         }
+        goto set_EPC;
+    case EXCP_THREAD:
+        cause = 25;
     set_EPC:
         if (!(env->CP0_Status & (1 << CP0St_EXL))) {
             if (env->hflags & MIPS_HFLAG_BMASK) {
@@ -499,9 +500,8 @@
                 env->CP0_Cause &= ~(1 << CP0Ca_BD);
             }
             env->CP0_Status |= (1 << CP0St_EXL);
-            if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
-                env->hflags |= MIPS_HFLAG_64;
-            env->hflags &= ~MIPS_HFLAG_UM;
+            env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
+            env->hflags &= ~(MIPS_HFLAG_KSU);
         }
         env->hflags &= ~MIPS_HFLAG_BMASK;
         if (env->CP0_Status & (1 << CP0St_BEV)) {
@@ -559,7 +559,7 @@
     mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
     if (tlb->V0) {
         addr = tlb->VPN & ~mask;
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
         if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
             addr |= 0x3FFFFF0000000000ULL;
         }
@@ -572,7 +572,7 @@
     }
     if (tlb->V1) {
         addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
         if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
             addr |= 0x3FFFFF0000000000ULL;
         }

Modified: trunk/src/host/qemu-neo1973/target-mips/mips-defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/mips-defs.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-mips/mips-defs.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -8,12 +8,49 @@
 #define TARGET_PAGE_BITS 12
 #define MIPS_TLB_MAX 128
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 #define TARGET_LONG_BITS 64
 #else
 #define TARGET_LONG_BITS 32
 #endif
 
+/* Masks used to mark instructions to indicate which ISA level they
+   were introduced in. */
+#define		ISA_MIPS1	0x00000001
+#define		ISA_MIPS2	0x00000002
+#define		ISA_MIPS3	0x00000004
+#define		ISA_MIPS4	0x00000008
+#define		ISA_MIPS5	0x00000010
+#define		ISA_MIPS32	0x00000020
+#define		ISA_MIPS32R2	0x00000040
+#define		ISA_MIPS64	0x00000080
+#define		ISA_MIPS64R2	0x00000100
+
+/* MIPS ASE */
+#define		ASE_MIPS16	0x00001000
+#define		ASE_MIPS3D	0x00002000
+#define		ASE_MDMX	0x00004000
+#define		ASE_DSP		0x00008000
+#define		ASE_DSPR2	0x00010000
+#define		ASE_MT		0x00020000
+#define		ASE_SMARTMIPS	0x00040000
+
+/* Chip specific instructions.   */
+/* Currently void */
+
+/* MIPS CPU defines.  */
+#define		CPU_MIPS1	(ISA_MIPS1)
+#define		CPU_MIPS2	(CPU_MIPS1 | ISA_MIPS2)
+#define		CPU_MIPS3	(CPU_MIPS2 | ISA_MIPS3)
+#define		CPU_MIPS4	(CPU_MIPS3 | ISA_MIPS4)
+#define		CPU_MIPS5	(CPU_MIPS4 | ISA_MIPS5)
+
+#define		CPU_MIPS32	(CPU_MIPS2 | ISA_MIPS32)
+#define		CPU_MIPS64	(CPU_MIPS5 | CPU_MIPS32 | ISA_MIPS64)
+
+#define		CPU_MIPS32R2	(CPU_MIPS32 | ISA_MIPS32R2)
+#define		CPU_MIPS64R2	(CPU_MIPS64 | CPU_MIPS32R2 | ISA_MIPS64R2)
+
 /* Strictly follow the architecture standard:
    - Disallow "special" instruction handling for PMON/SPIM.
    Note that we still maintain Count/Compare to match the host clock. */

Modified: trunk/src/host/qemu-neo1973/target-mips/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-mips/op.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -22,6 +22,7 @@
 
 #include "config.h"
 #include "exec.h"
+#include "host-utils.h"
 
 #ifndef CALL_FROM_TB0
 #define CALL_FROM_TB0(func) func()
@@ -285,6 +286,10 @@
 #include "op_mem.c"
 #undef MEMSUFFIX
 
+#define MEMSUFFIX _super
+#include "op_mem.c"
+#undef MEMSUFFIX
+
 #define MEMSUFFIX _kernel
 #include "op_mem.c"
 #undef MEMSUFFIX
@@ -296,8 +301,8 @@
 /* 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->hflags & MIPS_HFLAG_UM) &&
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+    if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
         !(env->CP0_Status & (1 << CP0St_UX)))
         T0 = (int64_t)(int32_t)(T0 + T1);
     else
@@ -379,7 +384,7 @@
     RETURN();
 }
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 /* Arithmetic */
 void op_dadd (void)
 {
@@ -448,7 +453,7 @@
     RETURN();
 }
 #endif
-#endif /* TARGET_MIPS64 */
+#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
 
 /* Logical */
 void op_and (void)
@@ -537,39 +542,17 @@
 
 void op_clo (void)
 {
-    int n;
-
-    if (T0 == ~((target_ulong)0)) {
-        T0 = 32;
-    } else {
-        for (n = 0; n < 32; n++) {
-            if (!(T0 & (1 << 31)))
-                break;
-            T0 = T0 << 1;
-        }
-        T0 = n;
-    }
+    T0 = clo32(T0);
     RETURN();
 }
 
 void op_clz (void)
 {
-    int n;
-
-    if (T0 == 0) {
-        T0 = 32;
-    } else {
-        for (n = 0; n < 32; n++) {
-            if (T0 & (1 << 31))
-                break;
-            T0 = T0 << 1;
-        }
-        T0 = n;
-    }
+    T0 = clz32(T0);
     RETURN();
 }
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 
 #if TARGET_LONG_BITS > HOST_LONG_BITS
 /* Those might call libgcc functions.  */
@@ -645,6 +628,18 @@
     RETURN();
 }
 
+void op_dclo (void)
+{
+    CALL_FROM_TB0(do_dclo);
+    RETURN();
+}
+
+void op_dclz (void)
+{
+    CALL_FROM_TB0(do_dclz);
+    RETURN();
+}
+
 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
 
 void op_dsll (void)
@@ -735,42 +730,20 @@
        T0 = T1;
     RETURN();
 }
-#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
 
 void op_dclo (void)
 {
-    int n;
-
-    if (T0 == ~((target_ulong)0)) {
-        T0 = 64;
-    } else {
-        for (n = 0; n < 64; n++) {
-            if (!(T0 & (1ULL << 63)))
-                break;
-            T0 = T0 << 1;
-        }
-        T0 = n;
-    }
+    T0 = clo64(T0);
     RETURN();
 }
 
 void op_dclz (void)
 {
-    int n;
-
-    if (T0 == 0) {
-        T0 = 64;
-    } else {
-        for (n = 0; n < 64; n++) {
-            if (T0 & (1ULL << 63))
-                break;
-            T0 = T0 << 1;
-        }
-        T0 = n;
-    }
+    T0 = clz64(T0);
     RETURN();
 }
-#endif
+#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
+#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
 
 /* 64 bits arithmetic */
 #if TARGET_LONG_BITS > HOST_LONG_BITS
@@ -812,13 +785,13 @@
 
 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
 
-static inline uint64_t get_HILO (void)
+static always_inline uint64_t get_HILO (void)
 {
     return ((uint64_t)env->HI[0][env->current_tc] << 32) |
             ((uint64_t)(uint32_t)env->LO[0][env->current_tc]);
 }
 
-static inline void set_HILO (uint64_t HILO)
+static always_inline void set_HILO (uint64_t HILO)
 {
     env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
     env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
@@ -873,16 +846,16 @@
 }
 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 void op_dmult (void)
 {
-    CALL_FROM_TB4(muls64, &(env->HI[0][env->current_tc]), &(env->LO[0][env->current_tc]), T0, T1);
+    CALL_FROM_TB4(muls64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
     RETURN();
 }
 
 void op_dmultu (void)
 {
-    CALL_FROM_TB4(mulu64, &(env->HI[0][env->current_tc]), &(env->LO[0][env->current_tc]), T0, T1);
+    CALL_FROM_TB4(mulu64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
     RETURN();
 }
 #endif
@@ -977,7 +950,7 @@
     RETURN();
 }
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 void op_save_btarget64 (void)
 {
     env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
@@ -1300,7 +1273,7 @@
     T0 = env->CP0_Status & ~0xf1000018;
     T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
     T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
-    T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_R0);
+    T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
     RETURN();
 }
 
@@ -1481,7 +1454,14 @@
 
 void op_mtc0_index (void)
 {
-    env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->tlb->nb_tlb);
+    int num = 1;
+    unsigned int tmp = env->tlb->nb_tlb;
+
+    do {
+        tmp >>= 1;
+        num <<= 1;
+    } while (tmp);
+    env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (num - 1));
     RETURN();
 }
 
@@ -1804,7 +1784,7 @@
 
     /* 1k pages not implemented */
     val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     val &= env->SEGMask;
 #endif
     old = env->CP0_EntryHi;
@@ -1841,27 +1821,8 @@
 
     val = T0 & mask;
     old = env->CP0_Status;
-    if (!(val & (1 << CP0St_EXL)) &&
-        !(val & (1 << CP0St_ERL)) &&
-        !(env->hflags & MIPS_HFLAG_DM) &&
-        (val & (1 << CP0St_UM)))
-        env->hflags |= MIPS_HFLAG_UM;
-#ifdef TARGET_MIPS64
-    if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) ||
-        ((env->hflags & MIPS_HFLAG_UM) &&
-        !(val & (1 << CP0St_PX)) &&
-        !(val & (1 << CP0St_UX))))
-        env->hflags &= ~MIPS_HFLAG_64;
-#endif
-    if (val & (1 << CP0St_CU1))
-        env->hflags |= MIPS_HFLAG_FPU;
-    else
-        env->hflags &= ~MIPS_HFLAG_FPU;
-    if (val & (1 << CP0St_FR))
-        env->hflags |= MIPS_HFLAG_F64;
-    else
-        env->hflags &= ~MIPS_HFLAG_F64;
     env->CP0_Status = (env->CP0_Status & ~mask) | val;
+    CALL_FROM_TB1(compute_hflags, env);
     if (loglevel & CPU_LOG_EXEC)
         CALL_FROM_TB2(do_mtc0_status_debug, old, val);
     CALL_FROM_TB1(cpu_mips_update_irq, env);
@@ -1876,16 +1837,15 @@
     env->CP0_Status = T0 & ~0xf1000018;
     tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
     tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
-    tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_R0)) << (CP0TCSt_TKSU - CP0St_R0));
+    tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
     env->CP0_TCStatus[other_tc] = tcstatus;
     RETURN();
 }
 
 void op_mtc0_intctl (void)
 {
-    /* vectored interrupts not implemented, timer on int 7,
-       no performance counters. */
-    env->CP0_IntCtl |= T0 & 0x000002e0;
+    /* vectored interrupts not implemented, no performance counters. */
+    env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (T0 & 0x000002e0);
     RETURN();
 }
 
@@ -1905,12 +1865,20 @@
 void op_mtc0_cause (void)
 {
     uint32_t mask = 0x00C00300;
+    uint32_t old = env->CP0_Cause;
 
-    if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
+    if (env->insn_flags & ISA_MIPS32R2)
         mask |= 1 << CP0Ca_DC;
 
     env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
 
+    if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
+        if (env->CP0_Cause & (1 << CP0Ca_DC))
+            CALL_FROM_TB1(cpu_mips_stop_count, env);
+        else
+            CALL_FROM_TB1(cpu_mips_start_count, env);
+    }
+
     /* Handle the software interrupt as an hardware one, as they
        are very similar */
     if (T0 & CP0Ca_IP_mask) {
@@ -2003,7 +1971,7 @@
 
 void op_mtc0_performance0 (void)
 {
-    env->CP0_Performance0 = T0; /* XXX */
+    env->CP0_Performance0 = T0 & 0x000007ff;
     RETURN();
 }
 
@@ -2043,7 +2011,7 @@
     RETURN();
 }
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 void op_dmfc0_yqmask (void)
 {
     T0 = env->CP0_YQMask;
@@ -2157,7 +2125,7 @@
     T0 = env->CP0_ErrorEPC;
     RETURN();
 }
-#endif /* TARGET_MIPS64 */
+#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
 
 /* MIPS MT functions */
 void op_mftgpr(void)
@@ -2317,15 +2285,6 @@
 # define DEBUG_FPU_STATE() do { } while(0)
 #endif
 
-void op_cp0_enabled(void)
-{
-    if (!(env->CP0_Status & (1 << CP0St_CU0)) &&
-        (env->hflags & MIPS_HFLAG_UM)) {
-        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 0);
-    }
-    RETURN();
-}
-
 void op_cfc1 (void)
 {
     CALL_FROM_TB1(do_cfc1, PARAM1);
@@ -2342,7 +2301,7 @@
 
 void op_mfc1 (void)
 {
-    T0 = WT0;
+    T0 = (int32_t)WT0;
     DEBUG_FPU_STATE();
     RETURN();
 }
@@ -2370,7 +2329,7 @@
 
 void op_mfhc1 (void)
 {
-    T0 = WTH0;
+    T0 = (int32_t)WTH0;
     DEBUG_FPU_STATE();
     RETURN();
 }
@@ -3008,18 +2967,7 @@
         env->PC[env->current_tc] = env->CP0_EPC;
         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;
-#ifdef TARGET_MIPS64
-    if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) ||
-        ((env->hflags & MIPS_HFLAG_UM) &&
-        !(env->CP0_Status & (1 << CP0St_PX)) &&
-        !(env->CP0_Status & (1 << CP0St_UX))))
-        env->hflags &= ~MIPS_HFLAG_64;
-#endif
+    CALL_FROM_TB1(compute_hflags, env);
     if (loglevel & CPU_LOG_EXEC)
         CALL_FROM_TB0(debug_post_eret);
     env->CP0_LLAddr = 1;
@@ -3031,19 +2979,8 @@
     if (loglevel & CPU_LOG_EXEC)
         CALL_FROM_TB0(debug_pre_eret);
     env->PC[env->current_tc] = 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;
-#ifdef TARGET_MIPS64
-    if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) ||
-        ((env->hflags & MIPS_HFLAG_UM) &&
-        !(env->CP0_Status & (1 << CP0St_PX)) &&
-        !(env->CP0_Status & (1 << CP0St_UX))))
-        env->hflags &= ~MIPS_HFLAG_64;
-#endif
+    env->hflags &= MIPS_HFLAG_DM;
+    CALL_FROM_TB1(compute_hflags, env);
     if (loglevel & CPU_LOG_EXEC)
         CALL_FROM_TB0(debug_post_eret);
     env->CP0_LLAddr = 1;
@@ -3052,9 +2989,8 @@
 
 void op_rdhwr_cpunum(void)
 {
-    if (!(env->hflags & MIPS_HFLAG_UM) ||
-        (env->CP0_HWREna & (1 << 0)) ||
-        (env->CP0_Status & (1 << CP0St_CU0)))
+    if ((env->hflags & MIPS_HFLAG_CP0) ||
+        (env->CP0_HWREna & (1 << 0)))
         T0 = env->CP0_EBase & 0x3ff;
     else
         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
@@ -3063,9 +2999,8 @@
 
 void op_rdhwr_synci_step(void)
 {
-    if (!(env->hflags & MIPS_HFLAG_UM) ||
-        (env->CP0_HWREna & (1 << 1)) ||
-        (env->CP0_Status & (1 << CP0St_CU0)))
+    if ((env->hflags & MIPS_HFLAG_CP0) ||
+        (env->CP0_HWREna & (1 << 1)))
         T0 = env->SYNCI_Step;
     else
         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
@@ -3074,9 +3009,8 @@
 
 void op_rdhwr_cc(void)
 {
-    if (!(env->hflags & MIPS_HFLAG_UM) ||
-        (env->CP0_HWREna & (1 << 2)) ||
-        (env->CP0_Status & (1 << CP0St_CU0)))
+    if ((env->hflags & MIPS_HFLAG_CP0) ||
+        (env->CP0_HWREna & (1 << 2)))
         T0 = env->CP0_Count;
     else
         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
@@ -3085,9 +3019,8 @@
 
 void op_rdhwr_ccres(void)
 {
-    if (!(env->hflags & MIPS_HFLAG_UM) ||
-        (env->CP0_HWREna & (1 << 3)) ||
-        (env->CP0_Status & (1 << CP0St_CU0)))
+    if ((env->hflags & MIPS_HFLAG_CP0) ||
+        (env->CP0_HWREna & (1 << 3)))
         T0 = env->CCRes;
     else
         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
@@ -3106,7 +3039,7 @@
     RETURN();
 }
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 void op_save_pc64 (void)
 {
     env->PC[env->current_tc] = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
@@ -3178,7 +3111,7 @@
     RETURN();
 }
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 void op_dext(void)
 {
     unsigned int pos = PARAM1;

Modified: trunk/src/host/qemu-neo1973/target-mips/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op_helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-mips/op_helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -20,8 +20,14 @@
 #include <stdlib.h>
 #include "exec.h"
 
-#define GETPC() (__builtin_return_address(0))
+#include "host-utils.h"
 
+#ifdef __s390__
+# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
+#else
+# define GETPC() (__builtin_return_address(0))
+#endif
+
 /*****************************************************************************/
 /* Exceptions processing helpers */
 
@@ -62,19 +68,7 @@
     do_raise_exception_direct_err (exception, 0);
 }
 
-#define MEMSUFFIX _raw
-#include "op_helper_mem.c"
-#undef MEMSUFFIX
-#if !defined(CONFIG_USER_ONLY)
-#define MEMSUFFIX _user
-#include "op_helper_mem.c"
-#undef MEMSUFFIX
-#define MEMSUFFIX _kernel
-#include "op_helper_mem.c"
-#undef MEMSUFFIX
-#endif
-
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 #if TARGET_LONG_BITS > HOST_LONG_BITS
 /* Those might call libgcc functions.  */
 void do_dsll (void)
@@ -153,17 +147,28 @@
     } else
        T0 = T1;
 }
+
+void do_dclo (void)
+{
+    T0 = clo64(T0);
+}
+
+void do_dclz (void)
+{
+    T0 = clz64(T0);
+}
+
 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
-#endif /* TARGET_MIPS64 */
+#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
 
 /* 64 bits arithmetic for 32 bits hosts */
 #if TARGET_LONG_BITS > HOST_LONG_BITS
-static inline uint64_t get_HILO (void)
+static always_inline uint64_t get_HILO (void)
 {
     return (env->HI[0][env->current_tc] << 32) | (uint32_t)env->LO[0][env->current_tc];
 }
 
-static inline void set_HILO (uint64_t HILO)
+static always_inline void set_HILO (uint64_t HILO)
 {
     env->LO[0][env->current_tc] = (int32_t)HILO;
     env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
@@ -223,7 +228,7 @@
 }
 #endif
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 void do_ddiv (void)
 {
     if (T1 != 0) {
@@ -242,7 +247,7 @@
     }
 }
 #endif
-#endif /* TARGET_MIPS64 */
+#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
 
 #if defined(CONFIG_USER_ONLY)
 void do_mfc0_random (void)
@@ -265,6 +270,16 @@
     cpu_abort(env, "mtc0 compare\n");
 }
 
+void cpu_mips_start_count(CPUState *env)
+{
+    cpu_abort(env, "start count\n");
+}
+
+void cpu_mips_stop_count(CPUState *env)
+{
+    cpu_abort(env, "stop count\n");
+}
+
 void cpu_mips_update_irq(CPUState *env)
 {
     cpu_abort(env, "mtc0 status / mtc0 cause\n");
@@ -304,8 +319,12 @@
             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);
+    switch (env->hflags & MIPS_HFLAG_KSU) {
+    case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break;
+    case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break;
+    case MIPS_HFLAG_KM: fputs("\n", logfile); break;
+    default: cpu_abort(env, "Invalid MMU mode!\n"); break;
+    }
 }
 
 void do_mtc0_status_irqraise_debug(void)
@@ -373,7 +392,7 @@
     /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
     tlb = &env->tlb->mmu.r4k.tlb[idx];
     tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     tlb->VPN &= env->SEGMask;
 #endif
     tlb->ASID = env->CP0_EntryHi & 0xFF;
@@ -507,10 +526,12 @@
         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);
+    switch (env->hflags & MIPS_HFLAG_KSU) {
+    case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break;
+    case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break;
+    case MIPS_HFLAG_KM: fputs("\n", logfile); break;
+    default: cpu_abort(env, "Invalid MMU mode!\n"); break;
+    }
 }
 
 void do_pmon (int function)
@@ -565,7 +586,7 @@
     do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
 }
 
-void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
+void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 {
     TranslationBlock *tb;
     CPUState *saved_env;
@@ -576,7 +597,7 @@
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_mips_handle_mmu_fault(env, addr, is_write, is_user, 1);
+    ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
     if (ret) {
         if (retaddr) {
             /* now we have a real cpu fault */
@@ -593,6 +614,14 @@
     env = saved_env;
 }
 
+void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
+                          int unused)
+{
+    if (is_exec)
+        do_raise_exception(EXCP_IBE);
+    else
+        do_raise_exception(EXCP_DBE);
+}
 #endif
 
 /* Complex FPU operations which may need stack space. */
@@ -603,6 +632,10 @@
 #define FLOAT_ONE64 (0x3ffULL << 52)
 #define FLOAT_TWO32 (1 << 30)
 #define FLOAT_TWO64 (1ULL << 62)
+#define FLOAT_QNAN32 0x7fbfffff
+#define FLOAT_QNAN64 0x7ff7ffffffffffffULL
+#define FLOAT_SNAN32 0x7fffffff
+#define FLOAT_SNAN64 0x7fffffffffffffffULL
 
 /* convert MIPS rounding mode in FCR31 to IEEE library */
 unsigned int ieee_rm[] = {
@@ -671,7 +704,7 @@
         do_raise_exception(EXCP_FPE);
 }
 
-inline char ieee_ex_to_mips(char xcpt)
+static always_inline char ieee_ex_to_mips(char xcpt)
 {
     return (xcpt & float_flag_inexact) >> 5 |
            (xcpt & float_flag_underflow) >> 3 |
@@ -680,7 +713,7 @@
            (xcpt & float_flag_invalid) << 4;
 }
 
-inline char mips_ex_to_ieee(char xcpt)
+static always_inline char mips_ex_to_ieee(char xcpt)
 {
     return (xcpt & FP_INEXACT) << 5 |
            (xcpt & FP_UNDERFLOW) << 3 |
@@ -689,7 +722,7 @@
            (xcpt & FP_INVALID) >> 4;
 }
 
-inline void update_fcr31(void)
+static always_inline void update_fcr31(void)
 {
     int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fpu->fp_status));
 
@@ -726,7 +759,7 @@
     DT2 = float64_to_int64(FDT0, &env->fpu->fp_status);
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        DT2 = 0x7fffffffffffffffULL;
+        DT2 = FLOAT_SNAN64;
 }
 FLOAT_OP(cvtl, s)
 {
@@ -734,7 +767,7 @@
     DT2 = float32_to_int64(FST0, &env->fpu->fp_status);
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        DT2 = 0x7fffffffffffffffULL;
+        DT2 = FLOAT_SNAN64;
 }
 
 FLOAT_OP(cvtps, pw)
@@ -751,7 +784,7 @@
     WTH2 = float32_to_int32(FSTH0, &env->fpu->fp_status);
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        WT2 = 0x7fffffff;
+        WT2 = FLOAT_SNAN32;
 }
 FLOAT_OP(cvts, d)
 {
@@ -789,7 +822,7 @@
     WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        WT2 = 0x7fffffff;
+        WT2 = FLOAT_SNAN32;
 }
 FLOAT_OP(cvtw, d)
 {
@@ -797,7 +830,7 @@
     WT2 = float64_to_int32(FDT0, &env->fpu->fp_status);
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        WT2 = 0x7fffffff;
+        WT2 = FLOAT_SNAN32;
 }
 
 FLOAT_OP(roundl, d)
@@ -807,7 +840,7 @@
     RESTORE_ROUNDING_MODE;
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        DT2 = 0x7fffffffffffffffULL;
+        DT2 = FLOAT_SNAN64;
 }
 FLOAT_OP(roundl, s)
 {
@@ -816,7 +849,7 @@
     RESTORE_ROUNDING_MODE;
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        DT2 = 0x7fffffffffffffffULL;
+        DT2 = FLOAT_SNAN64;
 }
 FLOAT_OP(roundw, d)
 {
@@ -825,7 +858,7 @@
     RESTORE_ROUNDING_MODE;
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        WT2 = 0x7fffffff;
+        WT2 = FLOAT_SNAN32;
 }
 FLOAT_OP(roundw, s)
 {
@@ -834,7 +867,7 @@
     RESTORE_ROUNDING_MODE;
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        WT2 = 0x7fffffff;
+        WT2 = FLOAT_SNAN32;
 }
 
 FLOAT_OP(truncl, d)
@@ -842,28 +875,28 @@
     DT2 = float64_to_int64_round_to_zero(FDT0, &env->fpu->fp_status);
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        DT2 = 0x7fffffffffffffffULL;
+        DT2 = FLOAT_SNAN64;
 }
 FLOAT_OP(truncl, s)
 {
     DT2 = float32_to_int64_round_to_zero(FST0, &env->fpu->fp_status);
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        DT2 = 0x7fffffffffffffffULL;
+        DT2 = FLOAT_SNAN64;
 }
 FLOAT_OP(truncw, d)
 {
     WT2 = float64_to_int32_round_to_zero(FDT0, &env->fpu->fp_status);
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        WT2 = 0x7fffffff;
+        WT2 = FLOAT_SNAN32;
 }
 FLOAT_OP(truncw, s)
 {
     WT2 = float32_to_int32_round_to_zero(FST0, &env->fpu->fp_status);
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        WT2 = 0x7fffffff;
+        WT2 = FLOAT_SNAN32;
 }
 
 FLOAT_OP(ceill, d)
@@ -873,7 +906,7 @@
     RESTORE_ROUNDING_MODE;
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        DT2 = 0x7fffffffffffffffULL;
+        DT2 = FLOAT_SNAN64;
 }
 FLOAT_OP(ceill, s)
 {
@@ -882,7 +915,7 @@
     RESTORE_ROUNDING_MODE;
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        DT2 = 0x7fffffffffffffffULL;
+        DT2 = FLOAT_SNAN64;
 }
 FLOAT_OP(ceilw, d)
 {
@@ -891,7 +924,7 @@
     RESTORE_ROUNDING_MODE;
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        WT2 = 0x7fffffff;
+        WT2 = FLOAT_SNAN32;
 }
 FLOAT_OP(ceilw, s)
 {
@@ -900,7 +933,7 @@
     RESTORE_ROUNDING_MODE;
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        WT2 = 0x7fffffff;
+        WT2 = FLOAT_SNAN32;
 }
 
 FLOAT_OP(floorl, d)
@@ -910,7 +943,7 @@
     RESTORE_ROUNDING_MODE;
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        DT2 = 0x7fffffffffffffffULL;
+        DT2 = FLOAT_SNAN64;
 }
 FLOAT_OP(floorl, s)
 {
@@ -919,7 +952,7 @@
     RESTORE_ROUNDING_MODE;
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        DT2 = 0x7fffffffffffffffULL;
+        DT2 = FLOAT_SNAN64;
 }
 FLOAT_OP(floorw, d)
 {
@@ -928,7 +961,7 @@
     RESTORE_ROUNDING_MODE;
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        WT2 = 0x7fffffff;
+        WT2 = FLOAT_SNAN32;
 }
 FLOAT_OP(floorw, s)
 {
@@ -937,7 +970,7 @@
     RESTORE_ROUNDING_MODE;
     update_fcr31();
     if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
-        WT2 = 0x7fffffff;
+        WT2 = FLOAT_SNAN32;
 }
 
 /* MIPS specific unary operations */
@@ -1021,11 +1054,7 @@
     FDT2 = float64_ ## name (FDT0, FDT1, &env->fpu->fp_status);    \
     update_fcr31();                                                \
     if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID)                \
-        FDT2 = 0x7ff7ffffffffffffULL;                              \
-    else if (GET_FP_CAUSE(env->fpu->fcr31) & FP_UNDERFLOW) {       \
-        if ((env->fpu->fcr31 & 0x3) == 0)                          \
-            FDT2 &= FLOAT_SIGN64;                                  \
-    }                     \
+        FDT2 = FLOAT_QNAN64;                                       \
 }                         \
 FLOAT_OP(name, s)         \
 {                         \
@@ -1033,11 +1062,7 @@
     FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status);    \
     update_fcr31();                                                \
     if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID)                \
-        FST2 = 0x7fbfffff;                                         \
-    else if (GET_FP_CAUSE(env->fpu->fcr31) & FP_UNDERFLOW) {       \
-        if ((env->fpu->fcr31 & 0x3) == 0)                          \
-            FST2 &= FLOAT_SIGN32;                                  \
-    }                     \
+        FST2 = FLOAT_QNAN32;                                       \
 }                         \
 FLOAT_OP(name, ps)        \
 {                         \
@@ -1046,13 +1071,8 @@
     FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fpu->fp_status); \
     update_fcr31();       \
     if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) {              \
-        FST2 = 0x7fbfffff;                                         \
-        FSTH2 = 0x7fbfffff;                                        \
-    } else if (GET_FP_CAUSE(env->fpu->fcr31) & FP_UNDERFLOW) {     \
-        if ((env->fpu->fcr31 & 0x3) == 0) {                        \
-            FST2 &= FLOAT_SIGN32;                                  \
-            FSTH2 &= FLOAT_SIGN32;                                 \
-        }                 \
+        FST2 = FLOAT_QNAN32;                                       \
+        FSTH2 = FLOAT_QNAN32;                                      \
     }                     \
 }
 FLOAT_BINOP(add)

Deleted: trunk/src/host/qemu-neo1973/target-mips/op_helper_mem.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op_helper_mem.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-mips/op_helper_mem.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,301 +0,0 @@
-#undef DEBUG_OP
-
-#ifdef TARGET_WORDS_BIGENDIAN
-#define GET_LMASK(v) ((v) & 3)
-#else
-#define GET_LMASK(v) (((v) & 3) ^ 3)
-#endif
-
-void glue(do_lwl, MEMSUFFIX) (uint32_t tmp)
-{
-#if defined (DEBUG_OP)
-    target_ulong sav = T0;
-#endif
-
-    switch (GET_LMASK(T0)) {
-    case 0:
-        T0 = (int32_t)tmp;
-        break;
-    case 1:
-        T0 = (int32_t)((tmp << 8) | (T1 & 0x000000FF));
-        break;
-    case 2:
-        T0 = (int32_t)((tmp << 16) | (T1 & 0x0000FFFF));
-        break;
-    case 3:
-        T0 = (int32_t)((tmp << 24) | (T1 & 0x00FFFFFF));
-        break;
-    }
-#if defined (DEBUG_OP)
-    if (logfile) {
-        fprintf(logfile, "%s: " TARGET_FMT_lx " - %08x " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
-                __func__, sav, tmp, T1, T0);
-    }
-#endif
-    RETURN();
-}
-
-void glue(do_lwr, MEMSUFFIX) (uint32_t tmp)
-{
-#if defined (DEBUG_OP)
-    target_ulong sav = T0;
-#endif
-
-    switch (GET_LMASK(T0)) {
-    case 0:
-        T0 = (int32_t)((tmp >> 24) | (T1 & 0xFFFFFF00));
-        break;
-    case 1:
-        T0 = (int32_t)((tmp >> 16) | (T1 & 0xFFFF0000));
-        break;
-    case 2:
-        T0 = (int32_t)((tmp >> 8) | (T1 & 0xFF000000));
-        break;
-    case 3:
-        T0 = (int32_t)tmp;
-        break;
-    }
-#if defined (DEBUG_OP)
-    if (logfile) {
-        fprintf(logfile, "%s: " TARGET_FMT_lx " - %08x " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
-                __func__, sav, tmp, T1, T0);
-    }
-#endif
-    RETURN();
-}
-
-uint32_t glue(do_swl, MEMSUFFIX) (uint32_t tmp)
-{
-#if defined (DEBUG_OP)
-    target_ulong sav = tmp;
-#endif
-
-    switch (GET_LMASK(T0)) {
-    case 0:
-        tmp = (int32_t)T1;
-        break;
-    case 1:
-        tmp = (int32_t)((tmp & 0xFF000000) | ((uint32_t)T1 >> 8));
-        break;
-    case 2:
-        tmp = (int32_t)((tmp & 0xFFFF0000) | ((uint32_t)T1 >> 16));
-        break;
-    case 3:
-        tmp = (int32_t)((tmp & 0xFFFFFF00) | ((uint32_t)T1 >> 24));
-        break;
-    }
-#if defined (DEBUG_OP)
-    if (logfile) {
-        fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => %08x\n",
-                __func__, T0, sav, T1, tmp);
-    }
-#endif
-    RETURN();
-    return tmp;
-}
-
-uint32_t glue(do_swr, MEMSUFFIX) (uint32_t tmp)
-{
-#if defined (DEBUG_OP)
-    target_ulong sav = tmp;
-#endif
-
-    switch (GET_LMASK(T0)) {
-    case 0:
-        tmp = (int32_t)((tmp & 0x00FFFFFF) | (T1 << 24));
-        break;
-    case 1:
-        tmp = (int32_t)((tmp & 0x0000FFFF) | (T1 << 16));
-        break;
-    case 2:
-        tmp = (int32_t)((tmp & 0x000000FF) | (T1 << 8));
-        break;
-    case 3:
-        tmp = (int32_t)T1;
-        break;
-    }
-#if defined (DEBUG_OP)
-    if (logfile) {
-        fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => %08x\n",
-                __func__, T0, sav, T1, tmp);
-    }
-#endif
-    RETURN();
-    return tmp;
-}
-
-#ifdef TARGET_MIPS64
-
-#ifdef TARGET_WORDS_BIGENDIAN
-#define GET_LMASK64(v) ((v) & 7)
-#else
-#define GET_LMASK64(v) (((v) & 7) ^ 7)
-#endif
-
-void glue(do_ldl, MEMSUFFIX) (uint64_t tmp)
-{
-#if defined (DEBUG_OP)
-    target_ulong sav = T0;
-#endif
-
-    switch (GET_LMASK64(T0)) {
-    case 0:
-        T0 = tmp;
-        break;
-    case 1:
-        T0 = (tmp << 8) | (T1 & 0x00000000000000FFULL);
-        break;
-    case 2:
-        T0 = (tmp << 16) | (T1 & 0x000000000000FFFFULL);
-        break;
-    case 3:
-        T0 = (tmp << 24) | (T1 & 0x0000000000FFFFFFULL);
-        break;
-    case 4:
-        T0 = (tmp << 32) | (T1 & 0x00000000FFFFFFFFULL);
-        break;
-    case 5:
-        T0 = (tmp << 40) | (T1 & 0x000000FFFFFFFFFFULL);
-        break;
-    case 6:
-        T0 = (tmp << 48) | (T1 & 0x0000FFFFFFFFFFFFULL);
-        break;
-    case 7:
-        T0 = (tmp << 56) | (T1 & 0x00FFFFFFFFFFFFFFULL);
-        break;
-    }
-#if defined (DEBUG_OP)
-    if (logfile) {
-        fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
-                __func__, sav, tmp, T1, T0);
-    }
-#endif
-    RETURN();
-}
-
-void glue(do_ldr, MEMSUFFIX) (uint64_t tmp)
-{
-#if defined (DEBUG_OP)
-    target_ulong sav = T0;
-#endif
-
-    switch (GET_LMASK64(T0)) {
-    case 0:
-        T0 = (tmp >> 56) | (T1 & 0xFFFFFFFFFFFFFF00ULL);
-        break;
-    case 1:
-        T0 = (tmp >> 48) | (T1 & 0xFFFFFFFFFFFF0000ULL);
-        break;
-    case 2:
-        T0 = (tmp >> 40) | (T1 & 0xFFFFFFFFFF000000ULL);
-        break;
-    case 3:
-        T0 = (tmp >> 32) | (T1 & 0xFFFFFFFF00000000ULL);
-        break;
-    case 4:
-        T0 = (tmp >> 24) | (T1 & 0xFFFFFF0000000000ULL);
-        break;
-    case 5:
-        T0 = (tmp >> 16) | (T1 & 0xFFFF000000000000ULL);
-        break;
-    case 6:
-        T0 = (tmp >> 8) | (T1 & 0xFF00000000000000ULL);
-        break;
-    case 7:
-        T0 = tmp;
-        break;
-    }
-#if defined (DEBUG_OP)
-    if (logfile) {
-        fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
-                __func__, sav, tmp, T1, T0);
-    }
-#endif
-    RETURN();
-}
-
-uint64_t glue(do_sdl, MEMSUFFIX) (uint64_t tmp)
-{
-#if defined (DEBUG_OP)
-    target_ulong sav = tmp;
-#endif
-
-    switch (GET_LMASK64(T0)) {
-    case 0:
-        tmp = T1;
-        break;
-    case 1:
-        tmp = (tmp & 0xFF00000000000000ULL) | (T1 >> 8);
-        break;
-    case 2:
-        tmp = (tmp & 0xFFFF000000000000ULL) | (T1 >> 16);
-        break;
-    case 3:
-        tmp = (tmp & 0xFFFFFF0000000000ULL) | (T1 >> 24);
-        break;
-    case 4:
-        tmp = (tmp & 0xFFFFFFFF00000000ULL) | (T1 >> 32);
-        break;
-    case 5:
-        tmp = (tmp & 0xFFFFFFFFFF000000ULL) | (T1 >> 40);
-        break;
-    case 6:
-        tmp = (tmp & 0xFFFFFFFFFFFF0000ULL) | (T1 >> 48);
-        break;
-    case 7:
-        tmp = (tmp & 0xFFFFFFFFFFFFFF00ULL) | (T1 >> 56);
-        break;
-    }
-#if defined (DEBUG_OP)
-    if (logfile) {
-        fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
-                __func__, T0, sav, T1, tmp);
-    }
-#endif
-    RETURN();
-    return tmp;
-}
-
-uint64_t glue(do_sdr, MEMSUFFIX) (uint64_t tmp)
-{
-#if defined (DEBUG_OP)
-    target_ulong sav = tmp;
-#endif
-
-    switch (GET_LMASK64(T0)) {
-    case 0:
-        tmp = (tmp & 0x00FFFFFFFFFFFFFFULL) | (T1 << 56);
-        break;
-    case 1:
-        tmp = (tmp & 0x0000FFFFFFFFFFFFULL) | (T1 << 48);
-        break;
-    case 2:
-        tmp = (tmp & 0x000000FFFFFFFFFFULL) | (T1 << 40);
-        break;
-    case 3:
-        tmp = (tmp & 0x00000000FFFFFFFFULL) | (T1 << 32);
-        break;
-    case 4:
-        tmp = (tmp & 0x0000000000FFFFFFULL) | (T1 << 24);
-        break;
-    case 5:
-        tmp = (tmp & 0x000000000000FFFFULL) | (T1 << 16);
-        break;
-    case 6:
-        tmp = (tmp & 0x00000000000000FFULL) | (T1 << 8);
-        break;
-    case 7:
-        tmp = T1;
-        break;
-    }
-#if defined (DEBUG_OP)
-    if (logfile) {
-        fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
-                __func__, T0, sav, T1, tmp);
-    }
-#endif
-    RETURN();
-    return tmp;
-}
-
-#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-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-mips/op_mem.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -75,34 +75,94 @@
 
 /* "half" load and stores.  We must do the memory access inline,
    or fault handling won't work.  */
-/* XXX: This is broken, CP0_BADVADDR has the wrong (aligned) value. */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define GET_LMASK(v) ((v) & 3)
+#define GET_OFFSET(addr, offset) (addr + (offset))
+#else
+#define GET_LMASK(v) (((v) & 3) ^ 3)
+#define GET_OFFSET(addr, offset) (addr - (offset))
+#endif
+
 void glue(op_lwl, MEMSUFFIX) (void)
 {
-    uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
-    CALL_FROM_TB1(glue(do_lwl, MEMSUFFIX), tmp);
+    target_ulong tmp;
+
+    tmp = glue(ldub, MEMSUFFIX)(T0);
+    T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
+
+    if (GET_LMASK(T0) <= 2) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 1));
+        T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
+    }
+
+    if (GET_LMASK(T0) <= 1) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 2));
+        T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
+    }
+
+    if (GET_LMASK(T0) == 0) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 3));
+        T1 = (T1 & 0xFFFFFF00) | tmp;
+    }
+    T1 = (int32_t)T1;
     RETURN();
 }
 
 void glue(op_lwr, MEMSUFFIX) (void)
 {
-    uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
-    CALL_FROM_TB1(glue(do_lwr, MEMSUFFIX), tmp);
+    target_ulong tmp;
+
+    tmp = glue(ldub, MEMSUFFIX)(T0);
+    T1 = (T1 & 0xFFFFFF00) | tmp;
+
+    if (GET_LMASK(T0) >= 1) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
+        T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
+    }
+
+    if (GET_LMASK(T0) >= 2) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
+        T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
+    }
+
+    if (GET_LMASK(T0) == 3) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
+        T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
+    }
+    T1 = (int32_t)T1;
     RETURN();
 }
 
 void glue(op_swl, MEMSUFFIX) (void)
 {
-    uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
-    tmp = CALL_FROM_TB1(glue(do_swl, MEMSUFFIX), tmp);
-    glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
+    glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 24));
+
+    if (GET_LMASK(T0) <= 2)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 16));
+
+    if (GET_LMASK(T0) <= 1)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 8));
+
+    if (GET_LMASK(T0) == 0)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)T1);
+
     RETURN();
 }
 
 void glue(op_swr, MEMSUFFIX) (void)
 {
-    uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
-    tmp = CALL_FROM_TB1(glue(do_swr, MEMSUFFIX), tmp);
-    glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
+    glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
+
+    if (GET_LMASK(T0) >= 1)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
+
+    if (GET_LMASK(T0) >= 2)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
+
+    if (GET_LMASK(T0) == 3)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
+
     RETURN();
 }
 
@@ -130,7 +190,7 @@
     RETURN();
 }
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 void glue(op_ld, MEMSUFFIX) (void)
 {
     T0 = glue(ldq, MEMSUFFIX)(T0);
@@ -145,33 +205,156 @@
 
 /* "half" load and stores.  We must do the memory access inline,
    or fault handling won't work.  */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define GET_LMASK64(v) ((v) & 7)
+#else
+#define GET_LMASK64(v) (((v) & 7) ^ 7)
+#endif
+
 void glue(op_ldl, MEMSUFFIX) (void)
 {
-    target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
-    CALL_FROM_TB1(glue(do_ldl, MEMSUFFIX), tmp);
+    uint64_t tmp;
+
+    tmp = glue(ldub, MEMSUFFIX)(T0);
+    T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
+
+    if (GET_LMASK64(T0) <= 6) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 1));
+        T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
+    }
+
+    if (GET_LMASK64(T0) <= 5) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 2));
+        T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
+    }
+
+    if (GET_LMASK64(T0) <= 4) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 3));
+        T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
+    }
+
+    if (GET_LMASK64(T0) <= 3) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 4));
+        T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
+    }
+
+    if (GET_LMASK64(T0) <= 2) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 5));
+        T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
+    }
+
+    if (GET_LMASK64(T0) <= 1) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 6));
+        T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
+    }
+
+    if (GET_LMASK64(T0) == 0) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 7));
+        T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
+    }
+
     RETURN();
 }
 
 void glue(op_ldr, MEMSUFFIX) (void)
 {
-    target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
-    CALL_FROM_TB1(glue(do_ldr, MEMSUFFIX), tmp);
+    uint64_t tmp;
+
+    tmp = glue(ldub, MEMSUFFIX)(T0);
+    T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
+
+    if (GET_LMASK64(T0) >= 1) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
+        T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp  << 8);
+    }
+
+    if (GET_LMASK64(T0) >= 2) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
+        T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
+    }
+
+    if (GET_LMASK64(T0) >= 3) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
+        T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
+    }
+
+    if (GET_LMASK64(T0) >= 4) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -4));
+        T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
+    }
+
+    if (GET_LMASK64(T0) >= 5) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -5));
+        T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
+    }
+
+    if (GET_LMASK64(T0) >= 6) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -6));
+        T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
+    }
+
+    if (GET_LMASK64(T0) == 7) {
+        tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -7));
+        T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
+    }
+
     RETURN();
 }
 
 void glue(op_sdl, MEMSUFFIX) (void)
 {
-    target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
-    tmp = CALL_FROM_TB1(glue(do_sdl, MEMSUFFIX), tmp);
-    glue(stq, MEMSUFFIX)(T0 & ~7, tmp);
+    glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 56));
+
+    if (GET_LMASK64(T0) <= 6)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 48));
+
+    if (GET_LMASK64(T0) <= 5)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 40));
+
+    if (GET_LMASK64(T0) <= 4)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)(T1 >> 32));
+
+    if (GET_LMASK64(T0) <= 3)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 4), (uint8_t)(T1 >> 24));
+
+    if (GET_LMASK64(T0) <= 2)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 5), (uint8_t)(T1 >> 16));
+
+    if (GET_LMASK64(T0) <= 1)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 6), (uint8_t)(T1 >> 8));
+
+    if (GET_LMASK64(T0) <= 0)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 7), (uint8_t)T1);
+
     RETURN();
 }
 
 void glue(op_sdr, MEMSUFFIX) (void)
 {
-    target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
-    tmp = CALL_FROM_TB1(glue(do_sdr, MEMSUFFIX), tmp);
-    glue(stq, MEMSUFFIX)(T0 & ~7, tmp);
+    glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
+
+    if (GET_LMASK64(T0) >= 1)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
+
+    if (GET_LMASK64(T0) >= 2)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
+
+    if (GET_LMASK64(T0) >= 3)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
+
+    if (GET_LMASK64(T0) >= 4)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -4), (uint8_t)(T1 >> 32));
+
+    if (GET_LMASK64(T0) >= 5)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -5), (uint8_t)(T1 >> 40));
+
+    if (GET_LMASK64(T0) >= 6)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -6), (uint8_t)(T1 >> 48));
+
+    if (GET_LMASK64(T0) == 7)
+        glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -7), (uint8_t)(T1 >> 56));
+
     RETURN();
 }
 
@@ -198,7 +381,7 @@
     }
     RETURN();
 }
-#endif /* TARGET_MIPS64 */
+#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
 
 void glue(op_lwc1, MEMSUFFIX) (void)
 {

Modified: trunk/src/host/qemu-neo1973/target-mips/op_template.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op_template.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-mips/op_template.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -82,7 +82,7 @@
 
 #undef SET_RESET
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 #define SET64(treg, tregname)                               \
     void glue(op_set64, tregname)(void)                     \
     {                                                       \

Modified: trunk/src/host/qemu-neo1973/target-mips/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/translate.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-mips/translate.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -142,7 +142,7 @@
     OPC_SRL      = 0x02 | OPC_SPECIAL, /* also ROTR */
     OPC_SRA      = 0x03 | OPC_SPECIAL,
     OPC_SLLV     = 0x04 | OPC_SPECIAL,
-    OPC_SRLV     = 0x06 | OPC_SPECIAL,
+    OPC_SRLV     = 0x06 | OPC_SPECIAL, /* also ROTRV */
     OPC_SRAV     = 0x07 | OPC_SPECIAL,
     OPC_DSLLV    = 0x14 | OPC_SPECIAL,
     OPC_DSRLV    = 0x16 | OPC_SPECIAL, /* also DROTRV */
@@ -436,7 +436,7 @@
 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,  \
 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,  \
 };                                               \
-static inline void func(int n)                   \
+static always_inline void func(int n)            \
 {                                                \
     NAME ## _table[n]();                         \
 }
@@ -470,7 +470,7 @@
 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,  \
 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,  \
 };                                               \
-static inline void func(int n)                   \
+static always_inline void func(int n)            \
 {                                                \
     NAME ## _table[n]();                         \
 }
@@ -521,7 +521,7 @@
     gen_op_cmp ## type ## _ ## fmt ## _le,                              \
     gen_op_cmp ## type ## _ ## fmt ## _ngt,                             \
 };                                                                      \
-static inline void gen_cmp ## type ## _ ## fmt(int n, long cc)          \
+static always_inline void gen_cmp ## type ## _ ## fmt(int n, long cc)   \
 {                                                                       \
     gen_op_cmp ## type ## _ ## fmt ## _table[n](cc);                    \
 }
@@ -590,7 +590,7 @@
     }                                                                         \
 } while (0)
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 #define GEN_LOAD_IMM_TN(Tn, Imm)                                              \
 do {                                                                          \
     if (Imm == 0) {                                                           \
@@ -636,9 +636,9 @@
     glue(gen_op_store_fpr_, FTn)(Fn);                                         \
 } while (0)
 
-static inline void gen_save_pc(target_ulong pc)
+static always_inline void gen_save_pc(target_ulong pc)
 {
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     if (pc == (int32_t)pc) {
         gen_op_save_pc(pc);
     } else {
@@ -649,9 +649,9 @@
 #endif
 }
 
-static inline void gen_save_btarget(target_ulong btarget)
+static always_inline void gen_save_btarget(target_ulong btarget)
 {
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     if (btarget == (int32_t)btarget) {
         gen_op_save_btarget(btarget);
     } else {
@@ -662,7 +662,7 @@
 #endif
 }
 
-static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
+static always_inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
 {
 #if defined MIPS_DEBUG_DISAS
     if (loglevel & CPU_LOG_TB_IN_ASM) {
@@ -694,7 +694,7 @@
     }
 }
 
-static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
+static always_inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
 {
     ctx->saved_hflags = ctx->hflags;
     switch (ctx->hflags & MIPS_HFLAG_BMASK) {
@@ -712,7 +712,7 @@
     }
 }
 
-static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
+static always_inline void generate_exception_err (DisasContext *ctx, int excp, int err)
 {
 #if defined MIPS_DEBUG_DISAS
     if (loglevel & CPU_LOG_TB_IN_ASM)
@@ -726,20 +726,26 @@
     ctx->bstate = BS_EXCP;
 }
 
-static inline void generate_exception (DisasContext *ctx, int excp)
+static always_inline void generate_exception (DisasContext *ctx, int excp)
 {
     generate_exception_err (ctx, excp, 0);
 }
 
-static inline void check_cp1_enabled(DisasContext *ctx)
+static always_inline void check_cp0_enabled(DisasContext *ctx)
 {
-    if (!(ctx->hflags & MIPS_HFLAG_FPU))
+    if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
         generate_exception_err(ctx, EXCP_CpU, 1);
 }
 
-static inline void check_cp1_64bitmode(DisasContext *ctx)
+static always_inline void check_cp1_enabled(DisasContext *ctx)
 {
-    if (!(ctx->hflags & MIPS_HFLAG_F64))
+    if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
+        generate_exception_err(ctx, EXCP_CpU, 1);
+}
+
+static always_inline void check_cp1_64bitmode(DisasContext *ctx)
+{
+    if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64)))
         generate_exception(ctx, EXCP_RI);
 }
 
@@ -756,23 +762,23 @@
  */
 void check_cp1_registers(DisasContext *ctx, int regs)
 {
-    if (!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))
+    if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
         generate_exception(ctx, EXCP_RI);
 }
 
 /* This code generates a "reserved instruction" exception if the
-   CPU is not a MIPS R2 (or higher) CPU. */
-static inline void check_mips_r2(CPUState *env, DisasContext *ctx)
+   CPU does not support the instruction set corresponding to flags. */
+static always_inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
 {
-    if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) < (1 << CP0C0_AR))
+    if (unlikely(!(env->insn_flags & flags)))
         generate_exception(ctx, EXCP_RI);
 }
 
-/* This code generates a "reserved instruction" exception if the
-   CPU is not MIPS MT capable. */
-static inline void check_mips_mt(CPUState *env, DisasContext *ctx)
+/* This code generates a "reserved instruction" exception if 64-bit
+   instructions are not enabled. */
+static always_inline void check_mips_64(DisasContext *ctx)
 {
-    if (!(env->CP0_Config3 & (1 << CP0C3_MT)))
+    if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
         generate_exception(ctx, EXCP_RI);
 }
 
@@ -784,17 +790,19 @@
 #define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
 #define OP_LD_TABLE(width)                                                    \
 static GenOpFunc *gen_op_l##width[] = {                                       \
+    &gen_op_l##width##_kernel,                                                \
+    &gen_op_l##width##_super,                                                 \
     &gen_op_l##width##_user,                                                  \
-    &gen_op_l##width##_kernel,                                                \
 }
 #define OP_ST_TABLE(width)                                                    \
 static GenOpFunc *gen_op_s##width[] = {                                       \
+    &gen_op_s##width##_kernel,                                                \
+    &gen_op_s##width##_super,                                                 \
     &gen_op_s##width##_user,                                                  \
-    &gen_op_s##width##_kernel,                                                \
 }
 #endif
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 OP_LD_TABLE(d);
 OP_LD_TABLE(dl);
 OP_LD_TABLE(dr);
@@ -844,7 +852,7 @@
     /* Don't do NOP if destination is zero: we must perform the actual
        memory access. */
     switch (opc) {
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     case OPC_LWU:
         op_ldst(lwu);
         GEN_STORE_TN_REG(rt, T0);
@@ -875,7 +883,7 @@
     case OPC_LDL:
         GEN_LOAD_REG_TN(T1, rt);
         op_ldst(ldl);
-        GEN_STORE_TN_REG(rt, T0);
+        GEN_STORE_TN_REG(rt, T1);
         opn = "ldl";
         break;
     case OPC_SDL:
@@ -886,7 +894,7 @@
     case OPC_LDR:
         GEN_LOAD_REG_TN(T1, rt);
         op_ldst(ldr);
-        GEN_STORE_TN_REG(rt, T0);
+        GEN_STORE_TN_REG(rt, T1);
         opn = "ldr";
         break;
     case OPC_SDR:
@@ -938,7 +946,7 @@
     case OPC_LWL:
 	GEN_LOAD_REG_TN(T1, rt);
         op_ldst(lwl);
-        GEN_STORE_TN_REG(rt, T0);
+        GEN_STORE_TN_REG(rt, T1);
         opn = "lwl";
         break;
     case OPC_SWL:
@@ -949,7 +957,7 @@
     case OPC_LWR:
 	GEN_LOAD_REG_TN(T1, rt);
         op_ldst(lwr);
-        GEN_STORE_TN_REG(rt, T0);
+        GEN_STORE_TN_REG(rt, T1);
         opn = "lwr";
         break;
     case OPC_SWR:
@@ -1024,8 +1032,8 @@
 }
 
 /* Arithmetic with immediate operand */
-static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
-                           int rs, int16_t imm)
+static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
+                           int rt, int rs, int16_t imm)
 {
     target_ulong uimm;
     const char *opn = "imm arith";
@@ -1040,7 +1048,7 @@
     switch (opc) {
     case OPC_ADDI:
     case OPC_ADDIU:
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     case OPC_DADDI:
     case OPC_DADDIU:
 #endif
@@ -1060,7 +1068,7 @@
     case OPC_SLL:
     case OPC_SRA:
     case OPC_SRL:
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     case OPC_DSLL:
     case OPC_DSRA:
     case OPC_DSRL:
@@ -1083,7 +1091,7 @@
         gen_op_add();
         opn = "addiu";
         break;
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     case OPC_DADDI:
         save_cpu_state(ctx, 1);
         gen_op_daddo();
@@ -1132,8 +1140,14 @@
             opn = "srl";
             break;
         case 1:
-            gen_op_rotr();
-            opn = "rotr";
+            /* rotr is decoded as srl on non-R2 CPUs */
+            if (env->insn_flags & ISA_MIPS32R2) {
+                gen_op_rotr();
+                opn = "rotr";
+            } else {
+                gen_op_srl();
+                opn = "srl";
+            }
             break;
         default:
             MIPS_INVAL("invalid srl flag");
@@ -1141,7 +1155,7 @@
             break;
         }
         break;
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     case OPC_DSLL:
         gen_op_dsll();
         opn = "dsll";
@@ -1157,8 +1171,14 @@
             opn = "dsrl";
             break;
         case 1:
-            gen_op_drotr();
-            opn = "drotr";
+            /* drotr is decoded as dsrl on non-R2 CPUs */
+            if (env->insn_flags & ISA_MIPS32R2) {
+                gen_op_drotr();
+                opn = "drotr";
+            } else {
+                gen_op_dsrl();
+                opn = "dsrl";
+            }
             break;
         default:
             MIPS_INVAL("invalid dsrl flag");
@@ -1181,8 +1201,14 @@
             opn = "dsrl32";
             break;
         case 1:
-            gen_op_drotr32();
-            opn = "drotr32";
+            /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
+            if (env->insn_flags & ISA_MIPS32R2) {
+                gen_op_drotr32();
+                opn = "drotr32";
+            } else {
+                gen_op_dsrl32();
+                opn = "dsrl32";
+            }
             break;
         default:
             MIPS_INVAL("invalid dsrl32 flag");
@@ -1201,7 +1227,7 @@
 }
 
 /* Arithmetic */
-static void gen_arith (DisasContext *ctx, uint32_t opc,
+static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
                        int rd, int rs, int rt)
 {
     const char *opn = "arith";
@@ -1234,7 +1260,7 @@
         gen_op_sub();
         opn = "subu";
         break;
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     case OPC_DADD:
         save_cpu_state(ctx, 1);
         gen_op_daddo();
@@ -1305,8 +1331,14 @@
             opn = "srlv";
             break;
         case 1:
-            gen_op_rotrv();
-            opn = "rotrv";
+            /* rotrv is decoded as srlv on non-R2 CPUs */
+            if (env->insn_flags & ISA_MIPS32R2) {
+                gen_op_rotrv();
+                opn = "rotrv";
+            } else {
+                gen_op_srlv();
+                opn = "srlv";
+            }
             break;
         default:
             MIPS_INVAL("invalid srlv flag");
@@ -1314,7 +1346,7 @@
             break;
         }
         break;
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     case OPC_DSLLV:
         gen_op_dsllv();
         opn = "dsllv";
@@ -1330,8 +1362,14 @@
             opn = "dsrlv";
             break;
         case 1:
-            gen_op_drotrv();
-            opn = "drotrv";
+            /* drotrv is decoded as dsrlv on non-R2 CPUs */
+            if (env->insn_flags & ISA_MIPS32R2) {
+                gen_op_drotrv();
+                opn = "drotrv";
+            } else {
+                gen_op_dsrlv();
+                opn = "dsrlv";
+            }
             break;
         default:
             MIPS_INVAL("invalid dsrlv flag");
@@ -1413,7 +1451,7 @@
         gen_op_multu();
         opn = "multu";
         break;
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     case OPC_DDIV:
         gen_op_ddiv();
         opn = "ddiv";
@@ -1474,7 +1512,7 @@
         gen_op_clz();
         opn = "clz";
         break;
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     case OPC_DCLO:
         gen_op_dclo();
         opn = "dclo";
@@ -1590,7 +1628,7 @@
     ctx->bstate = BS_STOP;
 }
 
-static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
+static always_inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
 {
     TranslationBlock *tb;
     tb = ctx->tb;
@@ -1910,6 +1948,9 @@
 {
     const char *rn = "invalid";
 
+    if (sel != 0)
+        check_insn(env, ctx, ISA_MIPS32);
+
     switch (reg) {
     case 0:
         switch (sel) {
@@ -1918,17 +1959,17 @@
             rn = "Index";
             break;
         case 1:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_mvpcontrol();
             rn = "MVPControl";
             break;
         case 2:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_mvpconf0();
             rn = "MVPConf0";
             break;
         case 3:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_mvpconf1();
             rn = "MVPConf1";
             break;
@@ -1943,37 +1984,37 @@
             rn = "Random";
             break;
         case 1:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_vpecontrol();
             rn = "VPEControl";
             break;
         case 2:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_vpeconf0();
             rn = "VPEConf0";
             break;
         case 3:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_vpeconf1();
             rn = "VPEConf1";
             break;
         case 4:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_yqmask();
             rn = "YQMask";
             break;
         case 5:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_vpeschedule();
             rn = "VPESchedule";
             break;
         case 6:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_vpeschefback();
             rn = "VPEScheFBack";
             break;
         case 7:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_vpeopt();
             rn = "VPEOpt";
             break;
@@ -1988,37 +2029,37 @@
             rn = "EntryLo0";
             break;
         case 1:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_tcstatus();
             rn = "TCStatus";
             break;
         case 2:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_tcbind();
             rn = "TCBind";
             break;
         case 3:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_tcrestart();
             rn = "TCRestart";
             break;
         case 4:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_tchalt();
             rn = "TCHalt";
             break;
         case 5:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_tccontext();
             rn = "TCContext";
             break;
         case 6:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_tcschedule();
             rn = "TCSchedule";
             break;
         case 7:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_tcschefback();
             rn = "TCScheFBack";
             break;
@@ -2057,7 +2098,7 @@
             rn = "PageMask";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_pagegrain();
             rn = "PageGrain";
             break;
@@ -2072,22 +2113,27 @@
             rn = "Wired";
             break;
         case 1:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsconf0();
             rn = "SRSConf0";
             break;
         case 2:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsconf1();
             rn = "SRSConf1";
             break;
         case 3:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsconf2();
             rn = "SRSConf2";
             break;
         case 4:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsconf3();
             rn = "SRSConf3";
             break;
         case 5:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsconf4();
             rn = "SRSConf4";
             break;
@@ -2098,7 +2144,7 @@
     case 7:
         switch (sel) {
         case 0:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_hwrena();
             rn = "HWREna";
             break;
@@ -2155,17 +2201,17 @@
             rn = "Status";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_intctl();
             rn = "IntCtl";
             break;
         case 2:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsctl();
             rn = "SRSCtl";
             break;
         case 3:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsmap();
             rn = "SRSMap";
             break;
@@ -2200,7 +2246,7 @@
             rn = "PRid";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_ebase();
             rn = "EBase";
             break;
@@ -2273,9 +2319,8 @@
     case 20:
         switch (sel) {
         case 0:
-#ifdef TARGET_MIPS64
-	    if (!(ctx->hflags & MIPS_HFLAG_64))
-	        goto die;
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+            check_insn(env, ctx, ISA_MIPS3);
             gen_op_mfc0_xcontext();
             rn = "XContext";
             break;
@@ -2471,6 +2516,9 @@
 {
     const char *rn = "invalid";
 
+    if (sel != 0)
+        check_insn(env, ctx, ISA_MIPS32);
+
     switch (reg) {
     case 0:
         switch (sel) {
@@ -2479,17 +2527,17 @@
             rn = "Index";
             break;
         case 1:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_mvpcontrol();
             rn = "MVPControl";
             break;
         case 2:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             /* ignored */
             rn = "MVPConf0";
             break;
         case 3:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             /* ignored */
             rn = "MVPConf1";
             break;
@@ -2504,37 +2552,37 @@
             rn = "Random";
             break;
         case 1:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_vpecontrol();
             rn = "VPEControl";
             break;
         case 2:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_vpeconf0();
             rn = "VPEConf0";
             break;
         case 3:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_vpeconf1();
             rn = "VPEConf1";
             break;
         case 4:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_yqmask();
             rn = "YQMask";
             break;
         case 5:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_vpeschedule();
             rn = "VPESchedule";
             break;
         case 6:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_vpeschefback();
             rn = "VPEScheFBack";
             break;
         case 7:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_vpeopt();
             rn = "VPEOpt";
             break;
@@ -2549,37 +2597,37 @@
             rn = "EntryLo0";
             break;
         case 1:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tcstatus();
             rn = "TCStatus";
             break;
         case 2:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tcbind();
             rn = "TCBind";
             break;
         case 3:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tcrestart();
             rn = "TCRestart";
             break;
         case 4:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tchalt();
             rn = "TCHalt";
             break;
         case 5:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tccontext();
             rn = "TCContext";
             break;
         case 6:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tcschedule();
             rn = "TCSchedule";
             break;
         case 7:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tcschefback();
             rn = "TCScheFBack";
             break;
@@ -2618,7 +2666,7 @@
             rn = "PageMask";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_pagegrain();
             rn = "PageGrain";
             break;
@@ -2633,22 +2681,27 @@
             rn = "Wired";
             break;
         case 1:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsconf0();
             rn = "SRSConf0";
             break;
         case 2:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsconf1();
             rn = "SRSConf1";
             break;
         case 3:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsconf2();
             rn = "SRSConf2";
             break;
         case 4:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsconf3();
             rn = "SRSConf3";
             break;
         case 5:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsconf4();
             rn = "SRSConf4";
             break;
@@ -2659,7 +2712,7 @@
     case 7:
         switch (sel) {
         case 0:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_hwrena();
             rn = "HWREna";
             break;
@@ -2717,21 +2770,21 @@
             rn = "Status";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_intctl();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "IntCtl";
             break;
         case 2:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsctl();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "SRSCtl";
             break;
         case 3:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsmap();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
@@ -2770,7 +2823,7 @@
             rn = "PRid";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_ebase();
             rn = "EBase";
             break;
@@ -2848,9 +2901,8 @@
     case 20:
         switch (sel) {
         case 0:
-#ifdef TARGET_MIPS64
-	    if (!(ctx->hflags & MIPS_HFLAG_64))
-	        goto die;
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+            check_insn(env, ctx, ISA_MIPS3);
             gen_op_mtc0_xcontext();
             rn = "XContext";
             break;
@@ -3059,11 +3111,14 @@
     generate_exception(ctx, EXCP_RI);
 }
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
 {
     const char *rn = "invalid";
 
+    if (sel != 0)
+        check_insn(env, ctx, ISA_MIPS64);
+
     switch (reg) {
     case 0:
         switch (sel) {
@@ -3072,17 +3127,17 @@
             rn = "Index";
             break;
         case 1:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_mvpcontrol();
             rn = "MVPControl";
             break;
         case 2:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_mvpconf0();
             rn = "MVPConf0";
             break;
         case 3:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_mvpconf1();
             rn = "MVPConf1";
             break;
@@ -3097,37 +3152,37 @@
             rn = "Random";
             break;
         case 1:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_vpecontrol();
             rn = "VPEControl";
             break;
         case 2:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_vpeconf0();
             rn = "VPEConf0";
             break;
         case 3:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_vpeconf1();
             rn = "VPEConf1";
             break;
         case 4:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_dmfc0_yqmask();
             rn = "YQMask";
             break;
         case 5:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_dmfc0_vpeschedule();
             rn = "VPESchedule";
             break;
         case 6:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_dmfc0_vpeschefback();
             rn = "VPEScheFBack";
             break;
         case 7:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_vpeopt();
             rn = "VPEOpt";
             break;
@@ -3142,37 +3197,37 @@
             rn = "EntryLo0";
             break;
         case 1:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_tcstatus();
             rn = "TCStatus";
             break;
         case 2:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mfc0_tcbind();
             rn = "TCBind";
             break;
         case 3:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_dmfc0_tcrestart();
             rn = "TCRestart";
             break;
         case 4:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_dmfc0_tchalt();
             rn = "TCHalt";
             break;
         case 5:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_dmfc0_tccontext();
             rn = "TCContext";
             break;
         case 6:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_dmfc0_tcschedule();
             rn = "TCSchedule";
             break;
         case 7:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_dmfc0_tcschefback();
             rn = "TCScheFBack";
             break;
@@ -3211,7 +3266,7 @@
             rn = "PageMask";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_pagegrain();
             rn = "PageGrain";
             break;
@@ -3226,22 +3281,27 @@
             rn = "Wired";
             break;
         case 1:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsconf0();
             rn = "SRSConf0";
             break;
         case 2:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsconf1();
             rn = "SRSConf1";
             break;
         case 3:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsconf2();
             rn = "SRSConf2";
             break;
         case 4:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsconf3();
             rn = "SRSConf3";
             break;
         case 5:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsconf4();
             rn = "SRSConf4";
             break;
@@ -3252,7 +3312,7 @@
     case 7:
         switch (sel) {
         case 0:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_hwrena();
             rn = "HWREna";
             break;
@@ -3309,17 +3369,17 @@
             rn = "Status";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_intctl();
             rn = "IntCtl";
             break;
         case 2:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsctl();
             rn = "SRSCtl";
             break;
         case 3:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_srsmap();
             rn = "SRSMap";
             break;
@@ -3354,7 +3414,7 @@
             rn = "PRid";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mfc0_ebase();
             rn = "EBase";
             break;
@@ -3418,6 +3478,7 @@
     case 20:
         switch (sel) {
         case 0:
+            check_insn(env, ctx, ISA_MIPS3);
             gen_op_dmfc0_xcontext();
             rn = "XContext";
             break;
@@ -3612,6 +3673,9 @@
 {
     const char *rn = "invalid";
 
+    if (sel != 0)
+        check_insn(env, ctx, ISA_MIPS64);
+
     switch (reg) {
     case 0:
         switch (sel) {
@@ -3620,17 +3684,17 @@
             rn = "Index";
             break;
         case 1:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_mvpcontrol();
             rn = "MVPControl";
             break;
         case 2:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             /* ignored */
             rn = "MVPConf0";
             break;
         case 3:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             /* ignored */
             rn = "MVPConf1";
             break;
@@ -3645,37 +3709,37 @@
             rn = "Random";
             break;
         case 1:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_vpecontrol();
             rn = "VPEControl";
             break;
         case 2:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_vpeconf0();
             rn = "VPEConf0";
             break;
         case 3:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_vpeconf1();
             rn = "VPEConf1";
             break;
         case 4:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_yqmask();
             rn = "YQMask";
             break;
         case 5:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_vpeschedule();
             rn = "VPESchedule";
             break;
         case 6:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_vpeschefback();
             rn = "VPEScheFBack";
             break;
         case 7:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_vpeopt();
             rn = "VPEOpt";
             break;
@@ -3690,37 +3754,37 @@
             rn = "EntryLo0";
             break;
         case 1:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tcstatus();
             rn = "TCStatus";
             break;
         case 2:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tcbind();
             rn = "TCBind";
             break;
         case 3:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tcrestart();
             rn = "TCRestart";
             break;
         case 4:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tchalt();
             rn = "TCHalt";
             break;
         case 5:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tccontext();
             rn = "TCContext";
             break;
         case 6:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tcschedule();
             rn = "TCSchedule";
             break;
         case 7:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             gen_op_mtc0_tcschefback();
             rn = "TCScheFBack";
             break;
@@ -3759,7 +3823,7 @@
             rn = "PageMask";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_pagegrain();
             rn = "PageGrain";
             break;
@@ -3774,22 +3838,27 @@
             rn = "Wired";
             break;
         case 1:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsconf0();
             rn = "SRSConf0";
             break;
         case 2:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsconf1();
             rn = "SRSConf1";
             break;
         case 3:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsconf2();
             rn = "SRSConf2";
             break;
         case 4:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsconf3();
             rn = "SRSConf3";
             break;
         case 5:
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsconf4();
             rn = "SRSConf4";
             break;
@@ -3800,7 +3869,7 @@
     case 7:
         switch (sel) {
         case 0:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_hwrena();
             rn = "HWREna";
             break;
@@ -3858,21 +3927,21 @@
             rn = "Status";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_intctl();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "IntCtl";
             break;
         case 2:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsctl();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "SRSCtl";
             break;
         case 3:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_srsmap();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
@@ -3911,7 +3980,7 @@
             rn = "PRid";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             gen_op_mtc0_ebase();
             rn = "EBase";
             break;
@@ -3980,6 +4049,7 @@
     case 20:
         switch (sel) {
         case 0:
+            check_insn(env, ctx, ISA_MIPS3);
             gen_op_mtc0_xcontext();
             rn = "XContext";
             break;
@@ -4184,7 +4254,7 @@
 #endif
     generate_exception(ctx, EXCP_RI);
 }
-#endif /* TARGET_MIPS64 */
+#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
 
 static void gen_mftr(CPUState *env, DisasContext *ctx, int rt,
                      int u, int sel, int h)
@@ -4530,13 +4600,13 @@
         break;
     case OPC_MTC0:
         GEN_LOAD_REG_TN(T0, rt);
+        save_cpu_state(ctx, 1);
         gen_mtc0(env, ctx, rd, ctx->opcode & 0x7);
         opn = "mtc0";
         break;
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     case OPC_DMFC0:
-        if (!(ctx->hflags & MIPS_HFLAG_64))
-            generate_exception(ctx, EXCP_RI);
+        check_insn(env, ctx, ISA_MIPS3);
         if (rt == 0) {
             /* Treat as NOP. */
             return;
@@ -4546,15 +4616,15 @@
         opn = "dmfc0";
         break;
     case OPC_DMTC0:
-        if (!(ctx->hflags & MIPS_HFLAG_64))
-            generate_exception(ctx, EXCP_RI);
+        check_insn(env, ctx, ISA_MIPS3);
         GEN_LOAD_REG_TN(T0, rt);
+        save_cpu_state(ctx, 1);
         gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7);
         opn = "dmtc0";
         break;
 #endif
     case OPC_MFTR:
-        check_mips_mt(env, ctx);
+        check_insn(env, ctx, ASE_MT);
         if (rd == 0) {
             /* Treat as NOP. */
             return;
@@ -4565,7 +4635,7 @@
         opn = "mftr";
         break;
     case OPC_MTTR:
-        check_mips_mt(env, ctx);
+        check_insn(env, ctx, ASE_MT);
         GEN_LOAD_REG_TN(T0, rt);
         gen_mttr(env, ctx, rd, (ctx->opcode >> 5) & 1,
                  ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
@@ -4597,21 +4667,26 @@
         break;
     case OPC_ERET:
         opn = "eret";
+        check_insn(env, ctx, ISA_MIPS2);
+        save_cpu_state(ctx, 1);
         gen_op_eret();
         ctx->bstate = BS_EXCP;
         break;
     case OPC_DERET:
         opn = "deret";
+        check_insn(env, ctx, ISA_MIPS32);
         if (!(ctx->hflags & MIPS_HFLAG_DM)) {
             MIPS_INVAL(opn);
             generate_exception(ctx, EXCP_RI);
         } else {
+            save_cpu_state(ctx, 1);
             gen_op_deret();
             ctx->bstate = BS_EXCP;
         }
         break;
     case OPC_WAIT:
         opn = "wait";
+        check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
         /* If we get an exception, we want to restart at next instruction */
         ctx->pc += 4;
         save_cpu_state(ctx, 1);
@@ -4629,12 +4704,15 @@
 }
 
 /* CP1 Branches (before delay slot) */
-static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
+static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
                                  int32_t cc, int32_t offset)
 {
     target_ulong btarget;
     const char *opn = "cp1 cond branch";
 
+    if (cc != 0)
+        check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
+
     btarget = ctx->pc + 4 + offset;
 
     switch (op) {
@@ -5324,7 +5402,6 @@
         opn = "cvt.d.l";
         break;
     case FOP(38, 20):
-    case FOP(38, 21):
         check_cp1_64bitmode(ctx);
         GEN_LOAD_FREG_FTN(WT0, fs);
         GEN_LOAD_FREG_FTN(WTH0, fs);
@@ -5800,10 +5877,9 @@
 /* MIPS16 extension to MIPS32 */
 /* SmartMIPS extension to MIPS32 */
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
 
 /* MDMX extension to MIPS64 */
-/* MIPS-3D extension to MIPS64 */
 
 #endif
 
@@ -5843,14 +5919,15 @@
         switch (op1) {
         case OPC_SLL:          /* Arithmetic with immediate */
         case OPC_SRL ... OPC_SRA:
-            gen_arith_imm(ctx, op1, rd, rt, sa);
+            gen_arith_imm(env, ctx, op1, rd, rt, sa);
             break;
+        case OPC_MOVZ ... OPC_MOVN:
+            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
         case OPC_SLLV:         /* Arithmetic */
         case OPC_SRLV ... OPC_SRAV:
-        case OPC_MOVZ ... OPC_MOVN:
         case OPC_ADD ... OPC_NOR:
         case OPC_SLT ... OPC_SLTU:
-            gen_arith(ctx, op1, rd, rs, rt);
+            gen_arith(env, ctx, op1, rd, rs, rt);
             break;
         case OPC_MULT ... OPC_DIVU:
             gen_muldiv(ctx, op1, rs, rt);
@@ -5899,6 +5976,7 @@
             break;
 
         case OPC_MOVCI:
+            check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
             if (env->CP0_Config1 & (1 << CP0C1_FP)) {
                 save_cpu_state(ctx, 1);
                 check_cp1_enabled(ctx);
@@ -5909,26 +5987,26 @@
             }
             break;
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
        /* MIPS64 specific opcodes */
         case OPC_DSLL:
         case OPC_DSRL ... OPC_DSRA:
         case OPC_DSLL32:
         case OPC_DSRL32 ... OPC_DSRA32:
-            if (!(ctx->hflags & MIPS_HFLAG_64))
-                generate_exception(ctx, EXCP_RI);
-            gen_arith_imm(ctx, op1, rd, rt, sa);
+            check_insn(env, ctx, ISA_MIPS3);
+            check_mips_64(ctx);
+            gen_arith_imm(env, ctx, op1, rd, rt, sa);
             break;
         case OPC_DSLLV:
         case OPC_DSRLV ... OPC_DSRAV:
         case OPC_DADD ... OPC_DSUBU:
-            if (!(ctx->hflags & MIPS_HFLAG_64))
-                generate_exception(ctx, EXCP_RI);
-            gen_arith(ctx, op1, rd, rs, rt);
+            check_insn(env, ctx, ISA_MIPS3);
+            check_mips_64(ctx);
+            gen_arith(env, ctx, op1, rd, rs, rt);
             break;
         case OPC_DMULT ... OPC_DDIVU:
-            if (!(ctx->hflags & MIPS_HFLAG_64))
-                generate_exception(ctx, EXCP_RI);
+            check_insn(env, ctx, ISA_MIPS3);
+            check_mips_64(ctx);
             gen_muldiv(ctx, op1, rs, rt);
             break;
 #endif
@@ -5943,18 +6021,21 @@
         switch (op1) {
         case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
         case OPC_MSUB ... OPC_MSUBU:
+            check_insn(env, ctx, ISA_MIPS32);
             gen_muldiv(ctx, op1, rs, rt);
             break;
         case OPC_MUL:
-            gen_arith(ctx, op1, rd, rs, rt);
+            gen_arith(env, ctx, op1, rd, rs, rt);
             break;
         case OPC_CLZ ... OPC_CLO:
+            check_insn(env, ctx, ISA_MIPS32);
             gen_cl(ctx, op1, rd, rs);
             break;
         case OPC_SDBBP:
             /* XXX: not clear which exception should be raised
              *      when in debug mode...
              */
+            check_insn(env, ctx, ISA_MIPS32);
             if (!(ctx->hflags & MIPS_HFLAG_DM)) {
                 generate_exception(ctx, EXCP_DBp);
             } else {
@@ -5962,10 +6043,10 @@
             }
             /* Treat as NOP. */
             break;
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
         case OPC_DCLZ ... OPC_DCLO:
-            if (!(ctx->hflags & MIPS_HFLAG_64))
-                generate_exception(ctx, EXCP_RI);
+            check_insn(env, ctx, ISA_MIPS64);
+            check_mips_64(ctx);
             gen_cl(ctx, op1, rd, rs);
             break;
 #endif
@@ -5976,14 +6057,15 @@
         }
         break;
     case OPC_SPECIAL3:
-         check_mips_r2(env, ctx);
          op1 = MASK_SPECIAL3(ctx->opcode);
          switch (op1) {
          case OPC_EXT:
          case OPC_INS:
+             check_insn(env, ctx, ISA_MIPS32R2);
              gen_bitops(ctx, op1, rt, rs, sa, rd);
              break;
          case OPC_BSHFL:
+             check_insn(env, ctx, ISA_MIPS32R2);
              op2 = MASK_BSHFL(ctx->opcode);
              switch (op2) {
              case OPC_WSBH:
@@ -6006,6 +6088,7 @@
             GEN_STORE_TN_REG(rd, T0);
             break;
         case OPC_RDHWR:
+            check_insn(env, ctx, ISA_MIPS32R2);
             switch (rd) {
             case 0:
                 save_cpu_state(ctx, 1);
@@ -6036,27 +6119,27 @@
             GEN_STORE_TN_REG(rt, T0);
             break;
         case OPC_FORK:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             GEN_LOAD_REG_TN(T0, rt);
             GEN_LOAD_REG_TN(T1, rs);
             gen_op_fork();
             break;
         case OPC_YIELD:
-            check_mips_mt(env, ctx);
+            check_insn(env, ctx, ASE_MT);
             GEN_LOAD_REG_TN(T0, rs);
             gen_op_yield();
             GEN_STORE_TN_REG(rd, T0);
             break;
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
-            if (!(ctx->hflags & MIPS_HFLAG_64))
-                generate_exception(ctx, EXCP_RI);
+            check_insn(env, ctx, ISA_MIPS64R2);
+            check_mips_64(ctx);
             gen_bitops(ctx, op1, rt, rs, sa, rd);
             break;
         case OPC_DBSHFL:
-            if (!(ctx->hflags & MIPS_HFLAG_64))
-                generate_exception(ctx, EXCP_RI);
+            check_insn(env, ctx, ISA_MIPS64R2);
+            check_mips_64(ctx);
             op2 = MASK_DBSHFL(ctx->opcode);
             switch (op2) {
             case OPC_DSBH:
@@ -6092,7 +6175,7 @@
             gen_trap(ctx, op1, rs, -1, imm);
             break;
         case OPC_SYNCI:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             /* Treat as NOP. */
             break;
         default:            /* Invalid */
@@ -6102,15 +6185,14 @@
         }
         break;
     case OPC_CP0:
-        save_cpu_state(ctx, 1);
-        gen_op_cp0_enabled();
+        check_cp0_enabled(ctx);
         op1 = MASK_CP0(ctx->opcode);
         switch (op1) {
         case OPC_MFC0:
         case OPC_MTC0:
         case OPC_MFTR:
         case OPC_MTTR:
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
         case OPC_DMFC0:
         case OPC_DMTC0:
 #endif
@@ -6120,31 +6202,34 @@
             gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
             break;
         case OPC_MFMC0:
-            check_mips_r2(env, ctx);
             op2 = MASK_MFMC0(ctx->opcode);
             switch (op2) {
             case OPC_DMT:
-                check_mips_mt(env, ctx);
+                check_insn(env, ctx, ASE_MT);
                 gen_op_dmt();
                 break;
             case OPC_EMT:
-                check_mips_mt(env, ctx);
+                check_insn(env, ctx, ASE_MT);
                 gen_op_emt();
                 break;
             case OPC_DVPE:
-                check_mips_mt(env, ctx);
+                check_insn(env, ctx, ASE_MT);
                 gen_op_dvpe();
                 break;
             case OPC_EVPE:
-                check_mips_mt(env, ctx);
+                check_insn(env, ctx, ASE_MT);
                 gen_op_evpe();
                 break;
             case OPC_DI:
+                check_insn(env, ctx, ISA_MIPS32R2);
+                save_cpu_state(ctx, 1);
                 gen_op_di();
                 /* Stop translation as we may have switched the execution mode */
                 ctx->bstate = BS_STOP;
                 break;
             case OPC_EI:
+                check_insn(env, ctx, ISA_MIPS32R2);
+                save_cpu_state(ctx, 1);
                 gen_op_ei();
                 /* Stop translation as we may have switched the execution mode */
                 ctx->bstate = BS_STOP;
@@ -6157,12 +6242,12 @@
             GEN_STORE_TN_REG(rt, T0);
             break;
         case OPC_RDPGPR:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             GEN_LOAD_SRSREG_TN(T0, rt);
             GEN_STORE_TN_REG(rd, T0);
             break;
         case OPC_WRPGPR:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, ISA_MIPS32R2);
             GEN_LOAD_REG_TN(T0, rt);
             GEN_STORE_TN_SRSREG(rd, T0);
             break;
@@ -6173,7 +6258,7 @@
         }
         break;
     case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
-         gen_arith_imm(ctx, op, rt, rs, imm);
+         gen_arith_imm(env, ctx, op, rt, rs, imm);
          break;
     case OPC_J ... OPC_JAL: /* Jump */
          offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
@@ -6191,9 +6276,11 @@
          gen_ldst(ctx, op, rt, rs, imm);
          break;
     case OPC_CACHE:
+        check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
         /* Treat as NOP. */
         break;
     case OPC_PREF:
+        check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
         /* Treat as NOP. */
         break;
 
@@ -6219,21 +6306,26 @@
             switch (op1) {
             case OPC_MFHC1:
             case OPC_MTHC1:
-                check_mips_r2(env, ctx);
+                check_insn(env, ctx, ISA_MIPS32R2);
             case OPC_MFC1:
             case OPC_CFC1:
             case OPC_MTC1:
             case OPC_CTC1:
-#ifdef TARGET_MIPS64
+                gen_cp1(ctx, op1, rt, rd);
+                break;
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
             case OPC_DMFC1:
             case OPC_DMTC1:
-#endif
+                check_insn(env, ctx, ISA_MIPS3);
                 gen_cp1(ctx, op1, rt, rd);
                 break;
-            case OPC_BC1:
+#endif
             case OPC_BC1ANY2:
             case OPC_BC1ANY4:
-                gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
+                check_insn(env, ctx, ASE_MIPS3D);
+                /* fall through */
+            case OPC_BC1:
+                gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
                                     (rt >> 2) & 0x7, imm << 2);
                 return;
             case OPC_S_FMT:
@@ -6306,7 +6398,7 @@
         }
         break;
 
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     /* MIPS64 opcodes */
     case OPC_LWU:
     case OPC_LDL ... OPC_LDR:
@@ -6315,24 +6407,22 @@
     case OPC_LD:
     case OPC_SCD:
     case OPC_SD:
-        if (!(ctx->hflags & MIPS_HFLAG_64))
-            generate_exception(ctx, EXCP_RI);
+        check_insn(env, ctx, ISA_MIPS3);
+        check_mips_64(ctx);
         gen_ldst(ctx, op, rt, rs, imm);
         break;
     case OPC_DADDI ... OPC_DADDIU:
-        if (!(ctx->hflags & MIPS_HFLAG_64))
-            generate_exception(ctx, EXCP_RI);
-        gen_arith_imm(ctx, op, rt, rs, imm);
+        check_insn(env, ctx, ISA_MIPS3);
+        check_mips_64(ctx);
+        gen_arith_imm(env, ctx, op, rt, rs, imm);
         break;
 #endif
-#ifdef MIPS_HAS_MIPS16
     case OPC_JALX:
+        check_insn(env, ctx, ASE_MIPS16);
         /* MIPS16: Not implemented. */
-#endif
-#ifdef MIPS_HAS_MDMX
     case OPC_MDMX:
+        check_insn(env, ctx, ASE_MDMX);
         /* MDMX: Not implemented. */
-#endif
     default:            /* Invalid */
         MIPS_INVAL("major opcode");
         generate_exception(ctx, EXCP_RI);
@@ -6381,7 +6471,7 @@
     }
 }
 
-static inline int
+static always_inline int
 gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
                                 int search_pc)
 {
@@ -6403,12 +6493,12 @@
     ctx.tb = tb;
     ctx.bstate = BS_NONE;
     /* Restore delay slot state from the tb context.  */
-    ctx.hflags = tb->flags;
+    ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
     restore_cpu_state(env, &ctx);
 #if defined(CONFIG_USER_ONLY)
-    ctx.mem_idx = 0;
+    ctx.mem_idx = MIPS_HFLAG_UM;
 #else
-    ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
+    ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
 #endif
 #ifdef DEBUG_DISAS
     if (loglevel & CPU_LOG_TB_CPU) {
@@ -6419,7 +6509,7 @@
 #endif
 #ifdef MIPS_DEBUG_DISAS
     if (loglevel & CPU_LOG_TB_IN_ASM)
-        fprintf(logfile, "\ntb %p super %d cond %04x\n",
+        fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
                 tb, ctx.mem_idx, ctx.hflags);
 #endif
     while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
@@ -6575,7 +6665,7 @@
     }
 }
 
-#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
+#if (defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
 /* Debug help: The architecture requires 32bit code to maintain proper
    sign-extened values on 64bit machines.  */
 
@@ -6630,7 +6720,7 @@
                 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
     if (env->hflags & MIPS_HFLAG_FPU)
         fpu_dump_state(env, f, cpu_fprintf, flags);
-#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
+#if (defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
     cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
 #endif
 }
@@ -6662,7 +6752,6 @@
     } else {
         env->CP0_ErrorEPC = env->PC[env->current_tc];
     }
-    env->hflags = 0;
     env->PC[env->current_tc] = (int32_t)0xBFC00000;
     env->CP0_Wired = 0;
     /* SMP not implemented */
@@ -6686,8 +6775,10 @@
 #endif
     env->exception_index = EXCP_NONE;
 #if defined(CONFIG_USER_ONLY)
-    env->hflags |= MIPS_HFLAG_UM;
+    env->hflags = MIPS_HFLAG_UM;
     env->user_mode_only = 1;
+#else
+    env->hflags = MIPS_HFLAG_CP0;
 #endif
 }
 

Modified: trunk/src/host/qemu-neo1973/target-mips/translate_init.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/translate_init.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-mips/translate_init.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -80,6 +80,7 @@
     int32_t CP0_SRSConf3;
     int32_t CP0_SRSConf4_rw_bitmask;
     int32_t CP0_SRSConf4;
+    int insn_flags;
 };
 
 /*****************************************************************************/
@@ -98,6 +99,7 @@
         .SYNCI_Step = 32,
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x1278FF17,
+        .insn_flags = CPU_MIPS32 | ASE_MIPS16,
     },
     {
         .name = "4KEcR1",
@@ -111,6 +113,7 @@
         .SYNCI_Step = 32,
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x1278FF17,
+        .insn_flags = CPU_MIPS32 | ASE_MIPS16,
     },
     {
         .name = "4KEc",
@@ -124,6 +127,7 @@
         .SYNCI_Step = 32,
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x1278FF17,
+        .insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
     },
     {
         .name = "24Kc",
@@ -137,7 +141,8 @@
         .SYNCI_Step = 32,
         .CCRes = 2,
         /* No DSP implemented. */
-        .CP0_Status_rw_bitmask = 0x1278FF17,
+        .CP0_Status_rw_bitmask = 0x1278FF1F,
+        .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP,
     },
     {
         .name = "24Kf",
@@ -151,9 +156,10 @@
         .SYNCI_Step = 32,
         .CCRes = 2,
         /* No DSP implemented. */
-        .CP0_Status_rw_bitmask = 0x3678FF17,
+        .CP0_Status_rw_bitmask = 0x3678FF1F,
         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
                     (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
+        .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP,
     },
     {
         .name = "34Kf",
@@ -167,7 +173,7 @@
         .SYNCI_Step = 32,
         .CCRes = 2,
         /* No DSP implemented. */
-        .CP0_Status_rw_bitmask = 0x3678FF17,
+        .CP0_Status_rw_bitmask = 0x3678FF1F,
         /* No DSP implemented. */
         .CP0_TCStatus_rw_bitmask = (0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) |
                     (1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) |
@@ -193,8 +199,9 @@
         .CP0_SRSConf4_rw_bitmask = 0x3fffffff,
         .CP0_SRSConf4 = (0x3fe << CP0SRSC4_SRS15) |
                     (0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13),
+        .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT,
     },
-#ifdef TARGET_MIPS64
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
     {
         .name = "R4000",
         .CP0_PRid = 0x00000400,
@@ -210,6 +217,7 @@
 	/* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */
         .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
         .SEGBITS = 40,
+        .insn_flags = CPU_MIPS3,
     },
     {
         .name = "5Kc",
@@ -225,6 +233,7 @@
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x32F8FFFF,
         .SEGBITS = 42,
+        .insn_flags = CPU_MIPS64,
     },
     {
         .name = "5Kf",
@@ -243,6 +252,7 @@
         .CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) |
                     (0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
         .SEGBITS = 42,
+        .insn_flags = CPU_MIPS64,
     },
     {
         .name = "20Kc",
@@ -264,7 +274,29 @@
                     (1 << FCR0_D) | (1 << FCR0_S) |
                     (0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
         .SEGBITS = 40,
+        .insn_flags = CPU_MIPS64 | ASE_MIPS3D,
     },
+    {
+	/* A generic CPU providing MIPS64 Release 2 features.
+           FIXME: Eventually this should be replaced by a real CPU model. */
+        .name = "MIPS64R2-generic",
+        .CP0_PRid = 0x00000000,
+        .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) | (0x1 << CP0C0_AR),
+        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
+		    (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
+		    (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
+		    (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
+        .CP0_Config2 = MIPS_CONFIG2,
+        .CP0_Config3 = MIPS_CONFIG3,
+        .SYNCI_Step = 32,
+        .CCRes = 2,
+        .CP0_Status_rw_bitmask = 0x36FBFFFF,
+        .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) | (1 << FCR0_L) |
+                    (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
+                    (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .SEGBITS = 40,
+        .insn_flags = CPU_MIPS64R2 | ASE_MIPS3D,
+    },
 #endif
 };
 
@@ -367,7 +399,10 @@
        implemented, 5 TCs implemented. */
     env->mvp->CP0_MVPConf0 = (1 << CP0MVPC0_M) | (1 << CP0MVPC0_TLBS) |
                              (0 << CP0MVPC0_GS) | (1 << CP0MVPC0_PCP) |
+#ifndef CONFIG_USER_ONLY
+                             /* Usermode has no TLB support */
                              (env->tlb->nb_tlb << CP0MVPC0_PTLBE) |
+#endif
 // TODO: actually do 2 VPEs.
 //                             (1 << CP0MVPC0_TCA) | (0x1 << CP0MVPC0_PVPE) |
 //                             (0x04 << CP0MVPC0_PTC);
@@ -402,8 +437,8 @@
     env->CP0_Status_rw_bitmask = def->CP0_Status_rw_bitmask;
     env->CP0_TCStatus_rw_bitmask = def->CP0_TCStatus_rw_bitmask;
     env->CP0_SRSCtl = def->CP0_SRSCtl;
-#ifdef TARGET_MIPS64
-    if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
+#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
+    if (def->insn_flags & ISA_MIPS3)
     {
         env->hflags |= MIPS_HFLAG_64;
         env->SEGBITS = def->SEGBITS;
@@ -423,6 +458,7 @@
     env->CP0_SRSConf3 = def->CP0_SRSConf3;
     env->CP0_SRSConf4_rw_bitmask = def->CP0_SRSConf4_rw_bitmask;
     env->CP0_SRSConf4 = def->CP0_SRSConf4;
+    env->insn_flags = def->insn_flags;
 
 #ifndef CONFIG_USER_ONLY
     mmu_init(env, def);

Modified: trunk/src/host/qemu-neo1973/target-ppc/STATUS
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/STATUS	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-ppc/STATUS	2007-10-29 21:14:04 UTC (rev 3303)
@@ -4,68 +4,521 @@
 ===============================================================================
 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
+INSN: instruction set.
+      OK => all instructions are emulated
+      KO => some insns are missing or some should be removed
+      ?  => unchecked
+SPR:  special purpose registers set
+      OK => all SPR registered (but some may be fake)
+      KO => some SPR are missing or should be removed
+      ?  => uncheked
+MSR:  MSR bits definitions
+      OK => all MSR bits properly defined
+      KO => MSR definition is incorrect
+      ?  => unchecked
+IRQ:  input signals definitions (mostly interrupts)
+      OK => input signals are properly defined
+      KO => input signals are not implemented (system emulation does not work)
+      ?  => input signals definitions may be incorrect
+MMU:  MMU model implementation
+      OK => MMU model is implemented and Linux is able to boot
+      KO => MMU model not implemented or bugged
+      ?  => MMU model not tested
+EXCP: exceptions model implementation
+      OK => exception model is implemented and Linux is able to boot
+      KO => exception model not implemented or known to be buggy
+      ?  => exception model may be incorrect or is untested
 
-PowerPC that should work but are not supported by standard Linux kernel
-(then remain mostly untested)
-- PowerPC 745
-- PowerPC 755
+Embedded PowerPC cores
+***
+PowerPC 401:
+INSN  OK
+SPR   OK 401A1
+MSR   OK
+IRQ   KO partially implemented
+MMU   OK
+EXCP  ?
 
-Work in progress:
-* embedded PowerPC cores
-- BookE PowerPC
-- e500 core (Freescale PowerQUICC)
-* main stream PowerPC cores
-- PowerPC 601
-- PowerPC 602
+PowerPC 401x2:
+INSN  OK
+SPR   OK 401B2 401C2 401D2 401E2 401F2
+MSR   OK
+IRQ   KO partially implemented
+MMU   OK
+EXCP  ?
 
-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 IOP480:
+INSN  OK
+SPR   OK IOP480
+MSR   OK
+IRQ   KO partially implemented
+MMU   OK
+EXCP  ?
 
+To be checked: 401G2 401B3 Cobra
+
+***
+PowerPC 403:
+INSN  OK
+SPR   OK 403GA 403GB
+MMU   OK
+MSR   OK
+IRQ   KO not implemented
+EXCP  ?
+
+PowerPC 403GCX:
+INSN  OK
+SPR   OK 403GCX
+MMU   OK
+MSR   OK
+IRQ   KO not implemented
+EXCP  ?
+
+To be checked: 403GC
+
+***
+PowerPC 405:
+Checked: 405CRa 405CRb 405CRc 405EP 405GPa 405GPb 405GPc 405GPd 405GPe 405GPR
+         Npe405H Npe405H2 Npe405L
+INSN  OK
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  OK
+Remarks: Linux 2.4 boots (at least 1 proprietary firmware).
+         uboot seems to freeze at boot time.
+To be checked: 405D2 405D4 405EZ 405LP Npe4GS3 STB03 STB04 STB25
+               x2vp4 x2vp7 x2vp20 x2vp50
+
+XXX: find what is IBM e407b4
+
+***
+PowerPC 440:
+Checked: 440EPa 440EPb 440GXa 440GXb 440GXc 440GXf 440SP 440SP2
+INSN  OK
+SPR   OK
+MSR   OK
+IRQ   KO not implemented
+MMU   ?
+EXCP  ?
+
+PowerPC 440GP:
+Checked: 440GPb 440GPc
+INSN  OK
+SPR   OK
+MSR   OK
+IRQ   KO not implemented
+MMU   ?
+EXCP  ?
+
+PowerPC 440x4:
+Checked: 440A4 440B4 440G4 440H4
+INSN  OK
+SPR   OK
+MSR   OK
+IRQ   KO not implemented
+MMU   ?
+EXCP  ?
+
+PowerPC 440x5:
+Checked: 440A5 440F5 440G5 440H6 440GRa
+INSN  OK
+SPR   OK
+MSR   OK
+IRQ   KO not implemented
+MMU   ?
+EXCP  ?
+
+To be checked: 440EPx 440GRx 440SPE
+
+***
+PowerPC 460: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+PowerPC 460F: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+***
+PowerPC e200: (not implemented)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+***
+PowerPC e300: (not implemented)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+***
+PowerPC e500: (not implemented)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+***
+PowerPC e600: (not implemented)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+***
+32 bits PowerPC
+PowerPC 601: (601 601v2)
+INSN  OK
+SPR   OK is HID15 only on 601v2 ?
+MSR   OK
+IRQ   KO not implemented
+MMU   ?
+EXCP  ?
+Remarks: some instructions should have a specific behavior (not implemented)
+
+PowerPC 602: 602
+INSN  OK
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   ?
+EXCP  ? at least timer and external interrupt are OK
+Remarks: Linux 2.4 crashes when entering user-mode.
+         Linux 2.6.22 boots on this CPU but does not recognize it.
+
+PowerPC 603: (603)
+INSN  OK
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  OK
+Remarks: Linux 2.4 boots and properly recognizes the CPU
+         Linux 2.6.22 idem.
+
+PowerPC 603e: (603e11)
+INSN  OK
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  OK
+Remarks: Linux 2.4 boots and properly recognizes the CPU
+         Linux 2.6.22 idem.
+
+PowerPC G2:
+INSN  OK
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  OK
+Remarks: Linux 2.4 boots, recognizes the CPU as a 82xx.
+         Linux 2.6.22 idem.
+
+PowerPC G2le:
+INSN  OK
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  OK
+Remarks: Linux 2.4 does not boots. Same symptoms as 602.
+         Linux 2.6.22 boots and properly recognizes the CPU.
+
+PowerPC 604:
+INSN  OK
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  OK
+Remarks: Linux 2.4 boots and properly recognizes the CPU.
+         Linux 2.6.22 idem.
+
+PowerPC 7x0:
+INSN  OK
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  OK
+Remarks: Linux 2.4 boots and properly recognizes the CPU.
+         Linux 2.6.22 idem.
+
+PowerPC 750fx:
+INSN  OK
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  OK
+Remarks: Linux 2.4 boots but does not properly recognizes the CPU.
+         Linux 2.6.22 boots and properly recognizes the CPU.
+
+PowerPC 7x5:
+INSN  ?
+SPR   ?
+MSR   ?
+IRQ   OK
+MMU   ?
+EXCP  OK
+Remarks: Linux 2.4 does not boot.
+         Linux 2.6.22 idem.
+
+PowerPC 7400:
+INSN  KO Altivec missing
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  ?  Altivec, ...
+Remarks: Linux 2.4 boots and properly recognize the CPU.
+         Linux 2.6.22 idem.
+
+PowerPC 7410:
+INSN  KO Altivec missing
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  ?  Altivec, ...
+Remarks: Linux 2.4 boots and properly recognize the CPU.
+         Linux 2.6.22 idem.
+   Note that UM says tlbld & tlbli are implemented but this may be a mistake
+   as TLB loads are managed by the hardware and the CPU does not implement the
+   needed registers.
+
+PowerPC 7441:
+INSN  KO Altivec missing
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  ?  Altivec, ...
+Remarks: Linux does not have the code to handle TLB miss on this CPU
+         Linux 2.6.22 idem.
+
+PowerPC 7450/7451:
+INSN  KO Altivec missing
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  ?  Altivec, ...
+Remarks: Linux does not have the code to handle TLB miss on this CPU
+         Linux 2.6.22 idem.
+
+PowerPC 7445/7447:
+INSN  KO Altivec missing
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  ?  Altivec, ...
+Remarks: Linux does not have the code to handle TLB miss on this CPU
+         Linux 2.6.22 idem.
+
+PowerPC 7455/7457:
+INSN  KO Altivec missing
+SPR   OK
+MSR   OK
+IRQ   OK
+MMU   OK
+EXCP  ?  Altivec, ...
+Remarks: Linux does not have the code to handle TLB miss on this CPU
+         Linux 2.6.22 idem.
+
+64 bits PowerPC
+PowerPC 620: (disabled)
+INSN  KO
+SPR   KO
+MSR   ?
+IRQ   KO
+MMU   KO
+EXCP  KO
+Remarks: not much documentation for this implementation...
+
+PowerPC 970:
+INSN  KO Altivec missing and more
+SPR   KO
+MSR   ?
+IRQ   OK
+MMU   OK
+EXCP  KO partially implemented
+Remarks: Should be able to boot but there is no hw platform currently emulated.
+
+PowerPC 970FX:
+INSN  KO Altivec missing and more
+SPR   KO
+MSR   ?
+IRQ   OK
+MMU   OK
+EXCP  KO partially implemented
+Remarks: Should be able to boot but there is no hw platform currently emulated.
+
+PowerPC 970GX:
+INSN  KO Altivec missing and more
+SPR   KO
+MSR   ?
+IRQ   OK
+MMU   OK
+EXCP  KO partially implemented
+Remarks: Should be able to boot but there is no hw platform currently emulated.
+
+PowerPC Cell:
+INSN  KO Altivec missing and more
+SPR   KO
+MSR   ?
+IRQ   ?
+MMU   ?
+EXCP  ? partially implemented
+Remarks: As the core is mostly a 970, should be able to boot.
+         SPE are not implemented.
+
+PowerPC 630: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+PowerPC 631: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+POWER4: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+POWER4+: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+POWER5: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+POWER5+: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+POWER6: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+RS64: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+RS64-II: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+RS64-III: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+RS64-IV: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+Original POWER
+POWER: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
+POWER2: (disabled: lack of detailed specifications)
+INSN  KO
+SPR   KO
+MSR   KO
+IRQ   KO
+MMU   KO
+EXCP  KO
+
 ===============================================================================
 PowerPC microcontrollers emulation status
 
 Implemementation should be sufficient to boot Linux:
+(there seem to be problems with uboot freezing at some point)
 - PowerPC 405CR
 - PowerPC 405EP
 
 TODO:
-- More PowerPC 40x microcontrollers emulation
-- PowerQUICC microcontrollers emulation
+- PowerPC 401 microcontrollers emulation
+- PowerPC 403 microcontrollers emulation
+- more PowerPC 405 microcontrollers emulation
+- Fixes / more features for implemented PowerPC 405 microcontrollers emulation
+- PowerPC 440 microcontrollers emulation
+- e200 microcontrollers emulation
+- e300 microcontrollers emulation
+- e500 microcontrollers emulation
+- e600 microcontrollers emulation
 
 ===============================================================================
 PowerPC based platforms emulation status
@@ -95,6 +548,8 @@
   Need to provide a flash image ready to boot for reproductible tests.
 
 TODO:
+- URGENT: fix PreP and heathrow platforms
+- PowerPC 64 reference platform
 - MCA based RS/6000 emulation
 - CHRP emulation (not PowerMac)
 - PPAR emulation
@@ -102,4 +557,3 @@
 - 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-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-ppc/cpu.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -82,488 +82,215 @@
 #define ELF_MACHINE     EM_PPC
 #endif
 
-/* XXX: this should be tunable: PowerPC 601 & 64 bits PowerPC
- *                              have different cache line sizes
- */
-#define ICACHE_LINE_SIZE 32
-#define DCACHE_LINE_SIZE 32
-
 /*****************************************************************************/
-/* PVR definitions for most known PowerPC */
+/* MMU model                                                                 */
 enum {
-    /* PowerPC 401 cores */
-    CPU_PPC_401A1     = 0x00210000,
-    CPU_PPC_401B2     = 0x00220000,
-    CPU_PPC_401C2     = 0x00230000,
-    CPU_PPC_401D2     = 0x00240000,
-    CPU_PPC_401E2     = 0x00250000,
-    CPU_PPC_401F2     = 0x00260000,
-    CPU_PPC_401G2     = 0x00270000,
-#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     = 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_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,
-#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_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_STB043    = xxx,
-#endif
-#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     = 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,
-    /* 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       = 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      = 0x00090100, /* Also 2110 & 2120 */
-    CPU_PPC_604R      = 0x000a0101,
-    /* PowerPC 74x/75x cores (aka G3) */
-    CPU_PPC_74x       = 0x00080000,
-    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_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_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      = 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_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,
-    CPU_PPC_630       = 0x00400000,
-    CPU_PPC_631       = 0x00410000,
-    CPU_PPC_POWER4    = 0x00350000,
-    CPU_PPC_POWER4P   = 0x00380000,
-    CPU_PPC_POWER5    = 0x003A0000,
-    CPU_PPC_POWER5P   = 0x003B0000,
-    CPU_PPC_970       = 0x00390000,
-    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,
-    CPU_PPC_RS64IV    = 0x00370000,
-    /* Original POWER */
-    /* XXX: should be POWER (RIOS), RSC3308, RSC4608,
-     * POWER2 (RIOS2) & RSC2 (P2SC) here
-     */
-#if 0
-    CPU_POWER         = xxx,
-#endif
-#if 0
-    CPU_POWER2        = xxx,
-#endif
+    POWERPC_MMU_UNKNOWN    = 0,
+    /* Standard 32 bits PowerPC MMU                            */
+    POWERPC_MMU_32B,
+    /* PowerPC 6xx MMU with software TLB                       */
+    POWERPC_MMU_SOFT_6xx,
+    /* PowerPC 74xx MMU with software TLB                      */
+    POWERPC_MMU_SOFT_74xx,
+    /* PowerPC 4xx MMU with software TLB                       */
+    POWERPC_MMU_SOFT_4xx,
+    /* PowerPC 4xx MMU with software TLB and zones protections */
+    POWERPC_MMU_SOFT_4xx_Z,
+    /* PowerPC 4xx MMU in real mode only                       */
+    POWERPC_MMU_REAL_4xx,
+    /* BookE MMU model                                         */
+    POWERPC_MMU_BOOKE,
+    /* BookE FSL MMU model                                     */
+    POWERPC_MMU_BOOKE_FSL,
+#if defined(TARGET_PPC64)
+    /* 64 bits PowerPC MMU                                     */
+    POWERPC_MMU_64B,
+#endif /* defined(TARGET_PPC64) */
 };
 
-/* System version register (used on MPC 8xxx) */
+/*****************************************************************************/
+/* Exception model                                                           */
 enum {
-    PPC_SVR_8540      = 0x80300000,
-    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,
+    POWERPC_EXCP_UNKNOWN   = 0,
+    /* Standard PowerPC exception model */
+    POWERPC_EXCP_STD,
+    /* PowerPC 40x exception model      */
+    POWERPC_EXCP_40x,
+    /* PowerPC 601 exception model      */
+    POWERPC_EXCP_601,
+    /* PowerPC 602 exception model      */
+    POWERPC_EXCP_602,
+    /* PowerPC 603 exception model      */
+    POWERPC_EXCP_603,
+    /* PowerPC 603e exception model     */
+    POWERPC_EXCP_603E,
+    /* PowerPC G2 exception model       */
+    POWERPC_EXCP_G2,
+    /* PowerPC 604 exception model      */
+    POWERPC_EXCP_604,
+    /* PowerPC 7x0 exception model      */
+    POWERPC_EXCP_7x0,
+    /* PowerPC 7x5 exception model      */
+    POWERPC_EXCP_7x5,
+    /* PowerPC 74xx exception model     */
+    POWERPC_EXCP_74xx,
+    /* BookE exception model            */
+    POWERPC_EXCP_BOOKE,
+#if defined(TARGET_PPC64)
+    /* PowerPC 970 exception model      */
+    POWERPC_EXCP_970,
+#endif /* defined(TARGET_PPC64) */
 };
 
 /*****************************************************************************/
-/* Instruction types */
+/* Exception vectors definitions                                             */
 enum {
-    PPC_NONE        = 0x00000000,
-    /* integer operations instructions             */
-    /* flow control instructions                   */
-    /* virtual memory instructions                 */
-    /* ld/st with reservation instructions         */
-    /* cache control instructions                  */
-    /* spr/msr access instructions                 */
-    PPC_INSNS_BASE  = 0x0000000000000001ULL,
-#define PPC_INTEGER PPC_INSNS_BASE
-#define PPC_FLOW    PPC_INSNS_BASE
-#define PPC_MEM     PPC_INSNS_BASE
-#define PPC_RES     PPC_INSNS_BASE
-#define PPC_CACHE   PPC_INSNS_BASE
-#define PPC_MISC    PPC_INSNS_BASE
-    /* floating point operations instructions      */
-    PPC_FLOAT       = 0x0000000000000002ULL,
-    /* more floating point operations instructions */
-    PPC_FLOAT_EXT   = 0x0000000000000004ULL,
-    /* external control instructions               */
-    PPC_EXTERN      = 0x0000000000000008ULL,
-    /* segment register access instructions        */
-    PPC_SEGMENT     = 0x0000000000000010ULL,
-    /* Optional cache control instructions         */
-    PPC_CACHE_OPT   = 0x0000000000000020ULL,
-    /* Optional floating point op instructions     */
-    PPC_FLOAT_OPT   = 0x0000000000000040ULL,
-    /* Optional memory control instructions        */
-    PPC_MEM_TLBIA   = 0x0000000000000080ULL,
-    PPC_MEM_TLBIE   = 0x0000000000000100ULL,
-    PPC_MEM_TLBSYNC = 0x0000000000000200ULL,
-    /* eieio & sync                                */
-    PPC_MEM_SYNC    = 0x0000000000000400ULL,
-    /* PowerPC 6xx TLB management instructions     */
-    PPC_6xx_TLB     = 0x0000000000000800ULL,
-    /* Altivec support                             */
-    PPC_ALTIVEC     = 0x0000000000001000ULL,
-    /* Time base support                           */
-    PPC_TB          = 0x0000000000002000ULL,
-    /* Embedded PowerPC dedicated instructions     */
-    PPC_EMB_COMMON  = 0x0000000000004000ULL,
-    /* PowerPC 40x exception model                 */
-    PPC_40x_EXCP    = 0x0000000000008000ULL,
-    /* PowerPC 40x specific instructions           */
-    PPC_40x_SPEC    = 0x0000000000010000ULL,
-    /* PowerPC 405 Mac instructions                */
-    PPC_405_MAC     = 0x0000000000020000ULL,
-    /* PowerPC 440 specific instructions           */
-    PPC_440_SPEC    = 0x0000000000040000ULL,
-    /* Specific extensions */
-    /* Power-to-PowerPC bridge (601)               */
-    PPC_POWER_BR    = 0x0000000000080000ULL,
-    /* PowerPC 602 specific */
-    PPC_602_SPEC    = 0x0000000000100000ULL,
-    /* Deprecated instructions                     */
-    /* Original POWER instruction set              */
-    PPC_POWER       = 0x0000000000200000ULL,
-    /* POWER2 instruction set extension            */
-    PPC_POWER2      = 0x0000000000400000ULL,
-    /* Power RTC support */
-    PPC_POWER_RTC   = 0x0000000000800000ULL,
-    /* 64 bits PowerPC instructions                */
-    /* 64 bits PowerPC instruction set             */
-    PPC_64B         = 0x0000000001000000ULL,
-    /* 64 bits hypervisor extensions               */
-    PPC_64H         = 0x0000000002000000ULL,
-    /* 64 bits PowerPC "bridge" features           */
-    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,
+    POWERPC_EXCP_NONE    = -1,
+    /* The 64 first entries are used by the PowerPC embedded specification   */
+    POWERPC_EXCP_CRITICAL = 0,  /* Critical input                            */
+    POWERPC_EXCP_MCHECK   = 1,  /* Machine check exception                   */
+    POWERPC_EXCP_DSI      = 2,  /* Data storage exception                    */
+    POWERPC_EXCP_ISI      = 3,  /* Instruction storage exception             */
+    POWERPC_EXCP_EXTERNAL = 4,  /* External input                            */
+    POWERPC_EXCP_ALIGN    = 5,  /* Alignment exception                       */
+    POWERPC_EXCP_PROGRAM  = 6,  /* Program exception                         */
+    POWERPC_EXCP_FPU      = 7,  /* Floating-point unavailable exception      */
+    POWERPC_EXCP_SYSCALL  = 8,  /* System call exception                     */
+    POWERPC_EXCP_APU      = 9,  /* Auxiliary processor unavailable           */
+    POWERPC_EXCP_DECR     = 10, /* Decrementer exception                     */
+    POWERPC_EXCP_FIT      = 11, /* Fixed-interval timer interrupt            */
+    POWERPC_EXCP_WDT      = 12, /* Watchdog timer interrupt                  */
+    POWERPC_EXCP_DTLB     = 13, /* Data TLB error                            */
+    POWERPC_EXCP_ITLB     = 14, /* Instruction TLB error                     */
+    POWERPC_EXCP_DEBUG    = 15, /* Debug interrupt                           */
+    /* Vectors 16 to 31 are reserved                                         */
+#if defined(TARGET_PPCEMB)
+    POWERPC_EXCP_SPEU     = 32, /* SPE/embedded floating-point unavailable   */
+    POWERPC_EXCP_EFPDI    = 33, /* Embedded floating-point data interrupt    */
+    POWERPC_EXCP_EFPRI    = 34, /* Embedded floating-point round interrupt   */
+    POWERPC_EXCP_EPERFM   = 35, /* Embedded performance monitor interrupt    */
+    POWERPC_EXCP_DOORI    = 36, /* Embedded doorbell interrupt               */
+    POWERPC_EXCP_DOORCI   = 37, /* Embedded doorbell critical interrupt      */
+#endif /* defined(TARGET_PPCEMB) */
+    /* Vectors 38 to 63 are reserved                                         */
+    /* Exceptions defined in the PowerPC server specification                */
+    POWERPC_EXCP_RESET    = 64, /* System reset exception                    */
+#if defined(TARGET_PPC64) /* PowerPC 64 */
+    POWERPC_EXCP_DSEG     = 65, /* Data segment exception                    */
+    POWERPC_EXCP_ISEG     = 66, /* Instruction segment exception             */
+#endif /* defined(TARGET_PPC64) */
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+    POWERPC_EXCP_HDECR    = 67, /* Hypervisor decrementer exception          */
+#endif /* defined(TARGET_PPC64H) */
+    POWERPC_EXCP_TRACE    = 68, /* Trace exception                           */
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+    POWERPC_EXCP_HDSI     = 69, /* Hypervisor data storage exception         */
+    POWERPC_EXCP_HISI     = 70, /* Hypervisor instruction storage exception  */
+    POWERPC_EXCP_HDSEG    = 71, /* Hypervisor data segment exception         */
+    POWERPC_EXCP_HISEG    = 72, /* Hypervisor instruction segment exception  */
+#endif /* defined(TARGET_PPC64H) */
+    POWERPC_EXCP_VPU      = 73, /* Vector unavailable exception              */
+    /* 40x specific exceptions                                               */
+    POWERPC_EXCP_PIT      = 74, /* Programmable interval timer interrupt     */
+    /* 601 specific exceptions                                               */
+    POWERPC_EXCP_IO       = 75, /* IO error exception                        */
+    POWERPC_EXCP_RUNM     = 76, /* Run mode exception                        */
+    /* 602 specific exceptions                                               */
+    POWERPC_EXCP_EMUL     = 77, /* Emulation trap exception                  */
+    /* 602/603 specific exceptions                                           */
+    POWERPC_EXCP_IFTLB    = 78, /* Instruction fetch TLB error               */
+    POWERPC_EXCP_DLTLB    = 79, /* Data load TLB miss                        */
+    POWERPC_EXCP_DSTLB    = 80, /* Data store TLB miss                       */
+    /* Exceptions available on most PowerPC                                  */
+    POWERPC_EXCP_FPA      = 81, /* Floating-point assist exception           */
+    POWERPC_EXCP_IABR     = 82, /* Instruction address breakpoint            */
+    POWERPC_EXCP_SMI      = 83, /* System management interrupt               */
+    POWERPC_EXCP_PERFM    = 84, /* Embedded performance monitor interrupt    */
+    /* 7xx/74xx specific exceptions                                          */
+    POWERPC_EXCP_THERM    = 85, /* Thermal interrupt                         */
+    /* 74xx specific exceptions                                              */
+    POWERPC_EXCP_VPUA     = 86, /* Vector assist exception                   */
+    /* 970FX specific exceptions                                             */
+    POWERPC_EXCP_SOFTP    = 87, /* Soft patch exception                      */
+    POWERPC_EXCP_MAINT    = 88, /* Maintenance exception                     */
+    /* EOL                                                                   */
+    POWERPC_EXCP_NB       = 96,
+    /* Qemu exceptions: used internally during code translation              */
+    POWERPC_EXCP_STOP         = 0x200, /* stop translation                   */
+    POWERPC_EXCP_BRANCH       = 0x201, /* branch instruction                 */
+    /* Qemu exceptions: special cases we want to stop translation            */
+    POWERPC_EXCP_SYNC         = 0x202, /* context synchronizing instruction  */
+    POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only      */
 };
 
-/* CPU run-time flags (MMU and exception model) */
+/* Exceptions error codes                                                    */
 enum {
-    /* MMU model */
-    PPC_FLAGS_MMU_MASK       = 0x000000FF,
-    /* Standard 32 bits PowerPC MMU */
-    PPC_FLAGS_MMU_32B        = 0x00000000,
-    /* Standard 64 bits PowerPC MMU */
-    PPC_FLAGS_MMU_64B        = 0x00000001,
-    /* PowerPC 601 MMU */
-    PPC_FLAGS_MMU_601        = 0x00000002,
-    /* PowerPC 6xx MMU with software TLB */
-    PPC_FLAGS_MMU_SOFT_6xx   = 0x00000003,
-    /* PowerPC 4xx MMU with software TLB */
-    PPC_FLAGS_MMU_SOFT_4xx   = 0x00000004,
-    /* PowerPC 403 MMU */
-    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 */
-    PPC_FLAGS_EXCP_MASK      = 0x0000FF00,
-    /* Standard PowerPC exception model */
-    PPC_FLAGS_EXCP_STD       = 0x00000000,
-    /* PowerPC 40x exception model */
-    PPC_FLAGS_EXCP_40x       = 0x00000100,
-    /* PowerPC 601 exception model */
-    PPC_FLAGS_EXCP_601       = 0x00000200,
-    /* PowerPC 602 exception model */
-    PPC_FLAGS_EXCP_602       = 0x00000300,
-    /* PowerPC 603 exception model */
-    PPC_FLAGS_EXCP_603       = 0x00000400,
-    /* PowerPC 604 exception model */
-    PPC_FLAGS_EXCP_604       = 0x00000500,
-    /* PowerPC 7x0 exception model */
-    PPC_FLAGS_EXCP_7x0       = 0x00000600,
-    /* PowerPC 7x5 exception model */
-    PPC_FLAGS_EXCP_7x5       = 0x00000700,
-    /* PowerPC 74xx exception model */
-    PPC_FLAGS_EXCP_74xx      = 0x00000800,
-    /* PowerPC 970 exception model */
-    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,
+    /* Exception subtypes for POWERPC_EXCP_ALIGN                             */
+    POWERPC_EXCP_ALIGN_FP      = 0x01,  /* FP alignment exception            */
+    POWERPC_EXCP_ALIGN_LST     = 0x02,  /* Unaligned mult/extern load/store  */
+    POWERPC_EXCP_ALIGN_LE      = 0x03,  /* Multiple little-endian access     */
+    POWERPC_EXCP_ALIGN_PROT    = 0x04,  /* Access cross protection boundary  */
+    POWERPC_EXCP_ALIGN_BAT     = 0x05,  /* Access cross a BAT/seg boundary   */
+    POWERPC_EXCP_ALIGN_CACHE   = 0x06,  /* Impossible dcbz access            */
+    /* Exception subtypes for POWERPC_EXCP_PROGRAM                           */
+    /* FP exceptions                                                         */
+    POWERPC_EXCP_FP            = 0x10,
+    POWERPC_EXCP_FP_OX         = 0x01,  /* FP overflow                       */
+    POWERPC_EXCP_FP_UX         = 0x02,  /* FP underflow                      */
+    POWERPC_EXCP_FP_ZX         = 0x03,  /* FP divide by zero                 */
+    POWERPC_EXCP_FP_XX         = 0x04,  /* FP inexact                        */
+    POWERPC_EXCP_FP_VXSNAN     = 0x05,  /* FP invalid SNaN op                */
+    POWERPC_EXCP_FP_VXISI      = 0x06,  /* FP invalid infinite subtraction   */
+    POWERPC_EXCP_FP_VXIDI      = 0x07,  /* FP invalid infinite divide        */
+    POWERPC_EXCP_FP_VXZDZ      = 0x08,  /* FP invalid zero divide            */
+    POWERPC_EXCP_FP_VXIMZ      = 0x09,  /* FP invalid infinite * zero        */
+    POWERPC_EXCP_FP_VXVC       = 0x0A,  /* FP invalid compare                */
+    POWERPC_EXCP_FP_VXSOFT     = 0x0B,  /* FP invalid operation              */
+    POWERPC_EXCP_FP_VXSQRT     = 0x0C,  /* FP invalid square root            */
+    POWERPC_EXCP_FP_VXCVI      = 0x0D,  /* FP invalid integer conversion     */
+    /* Invalid instruction                                                   */
+    POWERPC_EXCP_INVAL         = 0x20,
+    POWERPC_EXCP_INVAL_INVAL   = 0x01,  /* Invalid instruction               */
+    POWERPC_EXCP_INVAL_LSWX    = 0x02,  /* Invalid lswx instruction          */
+    POWERPC_EXCP_INVAL_SPR     = 0x03,  /* Invalid SPR access                */
+    POWERPC_EXCP_INVAL_FP      = 0x04,  /* Unimplemented mandatory fp instr  */
+    /* Privileged instruction                                                */
+    POWERPC_EXCP_PRIV          = 0x30,
+    POWERPC_EXCP_PRIV_OPC      = 0x01,  /* Privileged operation exception    */
+    POWERPC_EXCP_PRIV_REG      = 0x02,  /* Privileged register exception     */
+    /* Trap                                                                  */
+    POWERPC_EXCP_TRAP          = 0x40,
 };
 
-#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 */
-/* This generates an empty opcode table... */
-#define PPC_INSNS_TODO (PPC_NONE)
-#define PPC_FLAGS_TODO (0x00000000)
+/* Input pins model                                                          */
+enum {
+    PPC_FLAGS_INPUT_UNKNOWN = 0,
+    /* PowerPC 6xx bus                  */
+    PPC_FLAGS_INPUT_6xx,
+    /* BookE bus                        */
+    PPC_FLAGS_INPUT_BookE,
+    /* PowerPC 405 bus                  */
+    PPC_FLAGS_INPUT_405,
+    /* PowerPC 970 bus                  */
+    PPC_FLAGS_INPUT_970,
+    /* PowerPC 401 bus                  */
+    PPC_FLAGS_INPUT_401,
+};
 
-/* PowerPC 40x instruction set */
-#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_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_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 |          \
-                       PPC_FLAGS_INPUT_40x)
-/* PowerPC 440 */
-#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_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 |               \
-                       PPC_FLAGS_INPUT_6xx)
-/* PowerPC 602 */
-#define PPC_INSNS_602 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_6xx_TLB |       \
-                       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 |          \
-                       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 |           \
-                      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 |               \
-                       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 |               \
-                       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 |          \
-                       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 |             \
-                        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)
+#define PPC_INPUT(env) (env->bus_model)
 
-/* Default PowerPC will be 604/970 */
-#define PPC_INSNS_PPC32 PPC_INSNS_604
-#define PPC_FLAGS_PPC32 PPC_FLAGS_604
-#define PPC_INSNS_PPC64 PPC_INSNS_970
-#define PPC_FLAGS_PPC64 PPC_FLAGS_970
-#define PPC_INSNS_DEFAULT PPC_INSNS_604
-#define PPC_FLAGS_DEFAULT PPC_FLAGS_604
+/*****************************************************************************/
 typedef struct ppc_def_t ppc_def_t;
+typedef struct opc_handler_t opc_handler_t;
 
 /*****************************************************************************/
 /* Types used to describe some PowerPC registers */
 typedef struct CPUPPCState CPUPPCState;
-typedef struct opc_handler_t opc_handler_t;
 typedef struct ppc_tb_t ppc_tb_t;
 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_avr_t ppc_avr_t;
 typedef union ppc_tlb_t ppc_tlb_t;
 
 /* SPR access micro-ops generations callbacks */
@@ -573,13 +300,20 @@
 #if !defined(CONFIG_USER_ONLY)
     void (*oea_read)(void *opaque, int spr_num);
     void (*oea_write)(void *opaque, int spr_num);
+#if defined(TARGET_PPC64H)
+    void (*hea_read)(void *opaque, int spr_num);
+    void (*hea_write)(void *opaque, int spr_num);
 #endif
+#endif
     const unsigned char *name;
 };
 
 /* Altivec registers (128 bits) */
-struct ppc_avr_t {
-    uint32_t u[4];
+union ppc_avr_t {
+    uint8_t u8[16];
+    uint16_t u16[8];
+    uint32_t u32[4];
+    uint64_t u64[2];
 };
 
 /* Software TLB cache */
@@ -613,83 +347,170 @@
 #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_VR   25 /* altivec available                            x hflags */
+#define MSR_SPE  25 /* SPE enable for BookE                         x 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 update on ?                                       */
-#define MSR_CE   17 /* Critical interrupt enable on embedded PowerPC         */
+#define MSR_TGPR 17 /* TGPR usage on 602/603                        x        */
+#define MSR_CE   17 /* Critical interrupt enable on embedded PowerPC x       */
 #define MSR_ILE  16 /* Interrupt little-endian mode                          */
 #define MSR_EE   15 /* External interrupt enable                             */
 #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                hflags */
-#define MSR_SE   10 /* Single-step trace enable                       hflags */
-#define MSR_DWE  10 /* Debug wait enable on 405                              */
-#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_SE   10 /* Single-step trace enable                     x hflags */
+#define MSR_DWE  10 /* Debug wait enable on 405                     x        */
+#define MSR_UBLE 10 /* User BTB lock enable on e500                 x        */
+#define MSR_BE   9  /* Branch trace enable                          x hflags */
+#define MSR_DE   9  /* Debug interrupts enable on embedded PowerPC  x        */
 #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_EP   6  /* Exception prefix on 601                               */
 #define MSR_IR   5  /* Instruction relocate                                  */
-#define MSR_IS   5  /* Instruction address space on embedded PowerPC         */
 #define MSR_DR   4  /* Data relocate                                         */
-#define MSR_DS   4  /* Data address space on embedded PowerPC                */
 #define MSR_PE   3  /* Protection enable on 403                              */
-#define MSR_EP   3  /* Exception prefix on 601                               */
-#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                             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_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_dwe  env->msr[MSR_DWE]
-#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_al   env->msr[MSR_AL]
-#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_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_PX   2  /* Protection exclusive on 403                  x        */
+#define MSR_PMM  2  /* Performance monitor mark on POWER            x        */
+#define MSR_RI   1  /* Recoverable interrupt                        1        */
+#define MSR_LE   0  /* Little-endian mode                           1 hflags */
 
+#define msr_sf   ((env->msr >> MSR_SF)   & 1)
+#define msr_isf  ((env->msr >> MSR_ISF)  & 1)
+#define msr_hv   ((env->msr >> MSR_HV)   & 1)
+#define msr_cm   ((env->msr >> MSR_CM)   & 1)
+#define msr_icm  ((env->msr >> MSR_ICM)  & 1)
+#define msr_ucle ((env->msr >> MSR_UCLE) & 1)
+#define msr_vr   ((env->msr >> MSR_VR)   & 1)
+#define msr_spe  ((env->msr >> MSR_SE)   & 1)
+#define msr_ap   ((env->msr >> MSR_AP)   & 1)
+#define msr_sa   ((env->msr >> MSR_SA)   & 1)
+#define msr_key  ((env->msr >> MSR_KEY)  & 1)
+#define msr_pow  ((env->msr >> MSR_POW)  & 1)
+#define msr_tgpr ((env->msr >> MSR_TGPR) & 1)
+#define msr_ce   ((env->msr >> MSR_CE)   & 1)
+#define msr_ile  ((env->msr >> MSR_ILE)  & 1)
+#define msr_ee   ((env->msr >> MSR_EE)   & 1)
+#define msr_pr   ((env->msr >> MSR_PR)   & 1)
+#define msr_fp   ((env->msr >> MSR_FP)   & 1)
+#define msr_me   ((env->msr >> MSR_ME)   & 1)
+#define msr_fe0  ((env->msr >> MSR_FE0)  & 1)
+#define msr_se   ((env->msr >> MSR_SE)   & 1)
+#define msr_dwe  ((env->msr >> MSR_DWE)  & 1)
+#define msr_uble ((env->msr >> MSR_UBLE) & 1)
+#define msr_be   ((env->msr >> MSR_BE)   & 1)
+#define msr_de   ((env->msr >> MSR_DE)   & 1)
+#define msr_fe1  ((env->msr >> MSR_FE1)  & 1)
+#define msr_al   ((env->msr >> MSR_AL)   & 1)
+#define msr_ep   ((env->msr >> MSR_EP)   & 1)
+#define msr_ir   ((env->msr >> MSR_IR)   & 1)
+#define msr_dr   ((env->msr >> MSR_DR)   & 1)
+#define msr_pe   ((env->msr >> MSR_PE)   & 1)
+#define msr_px   ((env->msr >> MSR_PX)   & 1)
+#define msr_pmm  ((env->msr >> MSR_PMM)  & 1)
+#define msr_ri   ((env->msr >> MSR_RI)   & 1)
+#define msr_le   ((env->msr >> MSR_LE)   & 1)
+
+enum {
+    POWERPC_FLAG_NONE = 0x00000000,
+    /* Flag for MSR bit 25 signification (VRE/SPE)                           */
+    POWERPC_FLAG_SPE  = 0x00000001,
+    POWERPC_FLAG_VRE  = 0x00000002,
+    /* Flag for MSR bit 17 signification (TGPR/CE)                           */
+    POWERPC_FLAG_TGPR = 0x00000004,
+    POWERPC_FLAG_CE   = 0x00000008,
+    /* Flag for MSR bit 10 signification (SE/DWE/UBLE)                       */
+    POWERPC_FLAG_SE   = 0x00000010,
+    POWERPC_FLAG_DWE  = 0x00000020,
+    POWERPC_FLAG_UBLE = 0x00000040,
+    /* Flag for MSR bit 9 signification (BE/DE)                              */
+    POWERPC_FLAG_BE   = 0x00000080,
+    POWERPC_FLAG_DE   = 0x00000100,
+    /* Flag for MSR but 2 signification (PX/PMM)                             */
+    POWERPC_FLAG_PX   = 0x00000200,
+    POWERPC_FLAG_PMM  = 0x00000400,
+};
+
 /*****************************************************************************/
+/* Floating point status and control register                                */
+#define FPSCR_FX     31 /* Floating-point exception summary                  */
+#define FPSCR_FEX    30 /* Floating-point enabled exception summary          */
+#define FPSCR_VX     29 /* Floating-point invalid operation exception summ.  */
+#define FPSCR_OX     28 /* Floating-point overflow exception                 */
+#define FPSCR_UX     27 /* Floating-point underflow exception                */
+#define FPSCR_ZX     26 /* Floating-point zero divide exception              */
+#define FPSCR_XX     25 /* Floating-point inexact exception                  */
+#define FPSCR_VXSNAN 24 /* Floating-point invalid operation exception (sNan) */
+#define FPSCR_VXISI  23 /* Floating-point invalid operation exception (inf)  */
+#define FPSCR_VXIDI  22 /* Floating-point invalid operation exception (inf)  */
+#define FPSCR_VXZDZ  21 /* Floating-point invalid operation exception (zero) */
+#define FPSCR_VXIMZ  20 /* Floating-point invalid operation exception (inf)  */
+#define FPSCR_VXVC   19 /* Floating-point invalid operation exception (comp) */
+#define FPSCR_FR     18 /* Floating-point fraction rounded                   */
+#define FPSCR_FI     17 /* Floating-point fraction inexact                   */
+#define FPSCR_C      16 /* Floating-point result class descriptor            */
+#define FPSCR_FL     15 /* Floating-point less than or negative              */
+#define FPSCR_FG     14 /* Floating-point greater than or negative           */
+#define FPSCR_FE     13 /* Floating-point equal or zero                      */
+#define FPSCR_FU     12 /* Floating-point unordered or NaN                   */
+#define FPSCR_FPCC   12 /* Floating-point condition code                     */
+#define FPSCR_FPRF   12 /* Floating-point result flags                       */
+#define FPSCR_VXSOFT 10 /* Floating-point invalid operation exception (soft) */
+#define FPSCR_VXSQRT 9  /* Floating-point invalid operation exception (sqrt) */
+#define FPSCR_VXCVI  8  /* Floating-point invalid operation exception (int)  */
+#define FPSCR_VE     7  /* Floating-point invalid operation exception enable */
+#define FPSCR_OE     6  /* Floating-point overflow exception enable          */
+#define FPSCR_UE     5  /* Floating-point undeflow exception enable          */
+#define FPSCR_ZE     4  /* Floating-point zero divide exception enable       */
+#define FPSCR_XE     3  /* Floating-point inexact exception enable           */
+#define FPSCR_NI     2  /* Floating-point non-IEEE mode                      */
+#define FPSCR_RN1    1
+#define FPSCR_RN     0  /* Floating-point rounding control                   */
+#define fpscr_fex    (((env->fpscr) >> FPSCR_FEX)    & 0x1)
+#define fpscr_vx     (((env->fpscr) >> FPSCR_VX)     & 0x1)
+#define fpscr_ox     (((env->fpscr) >> FPSCR_OX)     & 0x1)
+#define fpscr_ux     (((env->fpscr) >> FPSCR_UX)     & 0x1)
+#define fpscr_zx     (((env->fpscr) >> FPSCR_ZX)     & 0x1)
+#define fpscr_xx     (((env->fpscr) >> FPSCR_XX)     & 0x1)
+#define fpscr_vxsnan (((env->fpscr) >> FPSCR_VXSNAN) & 0x1)
+#define fpscr_vxisi  (((env->fpscr) >> FPSCR_VXISI)  & 0x1)
+#define fpscr_vxidi  (((env->fpscr) >> FPSCR_VXIDI)  & 0x1)
+#define fpscr_vxzdz  (((env->fpscr) >> FPSCR_VXZDZ)  & 0x1)
+#define fpscr_vximz  (((env->fpscr) >> FPSCR_VXIMZ)  & 0x1)
+#define fpscr_vxvc   (((env->fpscr) >> FPSCR_VXVC)   & 0x1)
+#define fpscr_fpcc   (((env->fpscr) >> FPSCR_FPCC)   & 0xF)
+#define fpscr_vxsoft (((env->fpscr) >> FPSCR_VXSOFT) & 0x1)
+#define fpscr_vxsqrt (((env->fpscr) >> FPSCR_VXSQRT) & 0x1)
+#define fpscr_vxcvi  (((env->fpscr) >> FPSCR_VXCVI)  & 0x1)
+#define fpscr_ve     (((env->fpscr) >> FPSCR_VE)     & 0x1)
+#define fpscr_oe     (((env->fpscr) >> FPSCR_OE)     & 0x1)
+#define fpscr_ue     (((env->fpscr) >> FPSCR_UE)     & 0x1)
+#define fpscr_ze     (((env->fpscr) >> FPSCR_ZE)     & 0x1)
+#define fpscr_xe     (((env->fpscr) >> FPSCR_XE)     & 0x1)
+#define fpscr_ni     (((env->fpscr) >> FPSCR_NI)     & 0x1)
+#define fpscr_rn     (((env->fpscr) >> FPSCR_RN)     & 0x3)
+/* Invalid operation exception summary */
+#define fpscr_ix ((env->fpscr) & ((1 << FPSCR_VXSNAN) | (1 << FPSCR_VXISI)  | \
+                                  (1 << FPSCR_VXIDI)  | (1 << FPSCR_VXZDZ)  | \
+                                  (1 << FPSCR_VXIMZ)  | (1 << FPSCR_VXVC)   | \
+                                  (1 << FPSCR_VXSOFT) | (1 << FPSCR_VXSQRT) | \
+                                  (1 << FPSCR_VXCVI)))
+/* exception summary */
+#define fpscr_ex  (((env->fpscr) >> FPSCR_XX) & 0x1F)
+/* enabled exception summary */
+#define fpscr_eex (((env->fpscr) >> FPSCR_XX) & ((env->fpscr) >> FPSCR_XE) &  \
+                   0x1F)
+
+/*****************************************************************************/
 /* The whole PowerPC CPU context */
+#if defined(TARGET_PPC64H)
+#define NB_MMU_MODES 3
+#else
+#define NB_MMU_MODES 2
+#endif
+
 struct CPUPPCState {
     /* First are the most commonly used resources
      * during translated code execution
@@ -700,7 +521,7 @@
      */
     ppc_gpr_t t0, t1, t2;
 #endif
-    ppc_avr_t t0_avr, t1_avr, t2_avr;
+    ppc_avr_t avr0, avr1, avr2;
 
     /* general purpose registers */
     ppc_gpr_t gpr[32];
@@ -718,7 +539,7 @@
 
     /* Those ones are used in supervisor mode only */
     /* machine state register */
-    uint8_t msr[64];
+    target_ulong msr;
     /* temporary general purpose registers */
     ppc_gpr_t tgpr[4]; /* Used to speed-up TLB assist handlers */
 
@@ -731,7 +552,7 @@
     /* floating point registers */
     float64 fpr[32];
     /* floating point status and control register */
-    uint8_t fpscr[8];
+    uint32_t fpscr;
 
     CPU_COMMON
 
@@ -740,9 +561,14 @@
     int access_type; /* when a memory exception occurs, the access
                         type is stored here */
 
-    /* MMU context */
+    /* MMU context - only relevant for full system emulation */
+#if !defined(CONFIG_USER_ONLY)
+#if defined(TARGET_PPC64)
     /* Address space register */
     target_ulong asr;
+    /* PowerPC 64 SLB area */
+    int slb_nr;
+#endif
     /* segment registers */
     target_ulong sdr1;
     target_ulong sr[16];
@@ -750,17 +576,31 @@
     int nb_BATs;
     target_ulong DBAT[2][8];
     target_ulong IBAT[2][8];
+    /* PowerPC TLB registers (for 4xx and 60x software driven TLBs) */
+    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];
+#endif
 
     /* Other registers */
     /* Special purpose registers */
     target_ulong spr[1024];
+    ppc_spr_t spr_cb[1024];
     /* Altivec registers */
     ppc_avr_t avr[32];
     uint32_t vscr;
+#if defined(TARGET_PPCEMB)
     /* SPE registers */
     ppc_gpr_t spe_acc;
     float_status spe_status;
     uint32_t spe_fscr;
+#endif
 
     /* Internal devices resources */
     /* Time base and decrementer */
@@ -768,20 +608,17 @@
     /* Device control registers */
     ppc_dcr_t *dcr_env;
 
-    /* PowerPC TLB registers (for 4xx and 60x software driven TLBs) */
-    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];
+    int dcache_line_size;
+    int icache_line_size;
 
     /* Those resources are used during exception processing */
     /* CPU model definition */
-    uint64_t msr_mask;
+    target_ulong msr_mask;
+    uint8_t mmu_model;
+    uint8_t excp_model;
+    uint8_t bus_model;
+    uint8_t pad;
+    int bfd_mach;
     uint32_t flags;
 
     int exception_index;
@@ -794,23 +631,30 @@
      */
     uint32_t irq_input_state;
     void **irq_inputs;
+    /* Exception vectors */
+    target_ulong excp_vectors[POWERPC_EXCP_NB];
+    target_ulong excp_prefix;
+    target_ulong ivor_mask;
+    target_ulong ivpr_mask;
+    target_ulong hreset_vector;
 #endif
 
     /* Those resources are used only during code translation */
     /* Next instruction pointer */
     target_ulong nip;
-    /* SPR translation callbacks */
-    ppc_spr_t spr_cb[1024];
+
     /* opcode handlers */
     opc_handler_t *opcodes[0x40];
 
     /* Those resources are used only in Qemu core */
     jmp_buf jmp_env;
     int user_mode_only; /* user mode only simulation */
-    uint32_t hflags;
+    target_ulong hflags; /* hflags is a MSR & HFLAGS_MASK */
+    int mmu_idx;         /* precomputed MMU index to speed up mem accesses */
 
     /* Power management */
     int power_mode;
+    int (*check_pow)(CPUPPCState *env);
 
     /* temporary hack to handle OSI calls (only used if non NULL) */
     int (*osi_call)(struct CPUPPCState *env);
@@ -824,6 +668,7 @@
     target_phys_addr_t pg_addr[2]; /* PTE tables base addresses */
     target_ulong ptem;             /* Virtual segment ID | API  */
     int key;                       /* Access key                */
+    int nx;                        /* Non-execute area          */
 };
 
 /*****************************************************************************/
@@ -856,17 +701,18 @@
 #if defined(TARGET_PPC64)
 target_ulong ppc_load_asr (CPUPPCState *env);
 void ppc_store_asr (CPUPPCState *env, target_ulong value);
-#endif
+target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr);
+void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs);
+#endif /* defined(TARGET_PPC64) */
+#if 0 // Unused
 target_ulong do_load_sr (CPUPPCState *env, int srnum);
-void do_store_sr (CPUPPCState *env, int srnum, target_ulong 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);
-void ppc_store_msr_32 (CPUPPCState *env, uint32_t value);
+void do_store_sr (CPUPPCState *env, int srnum, target_ulong value);
+#endif /* !defined(CONFIG_USER_ONLY) */
+target_ulong ppc_load_xer (CPUPPCState *env);
+void ppc_store_xer (CPUPPCState *env, target_ulong value);
+void ppc_store_msr (CPUPPCState *env, target_ulong value);
 
-void do_compute_hflags (CPUPPCState *env);
 void cpu_ppc_reset (void *opaque);
 CPUPPCState *cpu_ppc_init (void);
 void cpu_ppc_close(CPUPPCState *env);
@@ -882,8 +728,18 @@
 uint32_t cpu_ppc_load_tbu (CPUPPCState *env);
 void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value);
 void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value);
+uint32_t cpu_ppc_load_atbl (CPUPPCState *env);
+uint32_t cpu_ppc_load_atbu (CPUPPCState *env);
+void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value);
+void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value);
 uint32_t cpu_ppc_load_decr (CPUPPCState *env);
 void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value);
+#if defined(TARGET_PPC64H)
+uint32_t cpu_ppc_load_hdecr (CPUPPCState *env);
+void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value);
+uint64_t cpu_ppc_load_purr (CPUPPCState *env);
+void cpu_ppc_store_purr (CPUPPCState *env, uint64_t value);
+#endif
 uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env);
 uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env);
 #if !defined(CONFIG_USER_ONLY)
@@ -896,6 +752,11 @@
 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);
+void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
+#if defined(TARGET_PPC64)
+void ppc_slb_invalidate_all (CPUPPCState *env);
+void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0);
+#endif
 int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid);
 #endif
 #endif
@@ -909,7 +770,20 @@
 #define cpu_exec cpu_ppc_exec
 #define cpu_gen_code cpu_ppc_gen_code
 #define cpu_signal_handler cpu_ppc_signal_handler
+#define cpu_list ppc_cpu_list
 
+/* MMU modes definitions */
+#define MMU_MODE0_SUFFIX _user
+#define MMU_MODE1_SUFFIX _kernel
+#if defined(TARGET_PPC64H)
+#define MMU_MODE2_SUFFIX _hypv
+#endif
+#define MMU_USER_IDX 0
+static inline int cpu_mmu_index (CPUState *env)
+{
+    return env->mmu_idx;
+}
+
 #include "cpu-all.h"
 
 /*****************************************************************************/
@@ -934,13 +808,14 @@
 #define SPR_LR           (0x008)
 #define SPR_CTR          (0x009)
 #define SPR_DSISR        (0x012)
-#define SPR_DAR          (0x013)
+#define SPR_DAR          (0x013) /* DAE for PowerPC 601 */
 #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_AMR          (0x01D)
 #define SPR_BOOKE_PID    (0x030)
 #define SPR_BOOKE_DECAR  (0x036)
 #define SPR_BOOKE_CSRR0  (0x03A)
@@ -951,6 +826,7 @@
 #define SPR_8xx_EIE      (0x050)
 #define SPR_8xx_EID      (0x051)
 #define SPR_8xx_NRE      (0x052)
+#define SPR_CTRL         (0x088)
 #define SPR_58x_CMPA     (0x090)
 #define SPR_58x_CMPB     (0x091)
 #define SPR_58x_CMPC     (0x092)
@@ -959,6 +835,7 @@
 #define SPR_58x_DER      (0x094)
 #define SPR_58x_COUNTA   (0x096)
 #define SPR_58x_COUNTB   (0x097)
+#define SPR_UCTRL        (0x098)
 #define SPR_58x_CMPE     (0x098)
 #define SPR_58x_CMPF     (0x099)
 #define SPR_58x_CMPG     (0x09A)
@@ -992,14 +869,18 @@
 #define SPR_EAR          (0x11A)
 #define SPR_TBL          (0x11C)
 #define SPR_TBU          (0x11D)
+#define SPR_TBU40        (0x11E)
 #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_HDSISR       (0x132)
+#define SPR_HDAR         (0x133)
 #define SPR_BOOKE_DBCR0  (0x134)
 #define SPR_IBCR         (0x135)
+#define SPR_PURR         (0x135)
 #define SPR_BOOKE_DBCR1  (0x135)
 #define SPR_DBCR         (0x136)
 #define SPR_HDEC         (0x136)
@@ -1010,9 +891,9 @@
 #define SPR_BOOKE_IAC1   (0x138)
 #define SPR_HRMOR        (0x139)
 #define SPR_BOOKE_IAC2   (0x139)
-#define SPR_HSSR0        (0x13A)
+#define SPR_HSRR0        (0x13A)
 #define SPR_BOOKE_IAC3   (0x13A)
-#define SPR_HSSR1        (0x13B)
+#define SPR_HSRR1        (0x13B)
 #define SPR_BOOKE_IAC4   (0x13B)
 #define SPR_LPCR         (0x13C)
 #define SPR_BOOKE_DAC1   (0x13C)
@@ -1039,11 +920,11 @@
 #define SPR_BOOKE_IVOR13 (0x19D)
 #define SPR_BOOKE_IVOR14 (0x19E)
 #define SPR_BOOKE_IVOR15 (0x19F)
-#define SPR_E500_SPEFSCR (0x200)
+#define SPR_BOOKE_SPEFSCR (0x200)
 #define SPR_E500_BBEAR   (0x201)
 #define SPR_E500_BBTAR   (0x202)
-#define SPR_BOOKE_ATBL   (0x20E)
-#define SPR_BOOKE_ATBU   (0x20F)
+#define SPR_ATBL         (0x20E)
+#define SPR_ATBU         (0x20F)
 #define SPR_IBAT0U       (0x210)
 #define SPR_BOOKE_IVOR32 (0x210)
 #define SPR_IBAT0L       (0x211)
@@ -1105,80 +986,145 @@
 #define SPR_BOOKE_TLB2CFG (0x2B2)
 #define SPR_BOOKE_TLB3CFG (0x2B3)
 #define SPR_BOOKE_EPR    (0x2BE)
+#define SPR_PERF0        (0x300)
+#define SPR_PERF1        (0x301)
+#define SPR_PERF2        (0x302)
+#define SPR_PERF3        (0x303)
+#define SPR_PERF4        (0x304)
+#define SPR_PERF5        (0x305)
+#define SPR_PERF6        (0x306)
+#define SPR_PERF7        (0x307)
+#define SPR_PERF8        (0x308)
+#define SPR_PERF9        (0x309)
+#define SPR_PERFA        (0x30A)
+#define SPR_PERFB        (0x30B)
+#define SPR_PERFC        (0x30C)
+#define SPR_PERFD        (0x30D)
+#define SPR_PERFE        (0x30E)
+#define SPR_PERFF        (0x30F)
+#define SPR_UPERF0       (0x310)
+#define SPR_UPERF1       (0x311)
+#define SPR_UPERF2       (0x312)
+#define SPR_UPERF3       (0x313)
+#define SPR_UPERF4       (0x314)
+#define SPR_UPERF5       (0x315)
+#define SPR_UPERF6       (0x316)
+#define SPR_UPERF7       (0x317)
+#define SPR_UPERF8       (0x318)
+#define SPR_UPERF9       (0x319)
+#define SPR_UPERFA       (0x31A)
+#define SPR_UPERFB       (0x31B)
+#define SPR_UPERFC       (0x31C)
+#define SPR_UPERFD       (0x31D)
+#define SPR_UPERFE       (0x31E)
+#define SPR_UPERFF       (0x31F)
 #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_ITV0     (0x374)
+#define SPR_440_ITV1     (0x375)
+#define SPR_440_ITV2     (0x376)
+#define SPR_440_ITV3     (0x377)
+#define SPR_440_CCR1     (0x378)
+#define SPR_DCRIPR       (0x37B)
+#define SPR_PPR          (0x380)
 #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_DTV0     (0x394)
+#define SPR_440_DTV1     (0x395)
+#define SPR_440_DTV2     (0x396)
+#define SPR_440_DTV3     (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_BOOKE_DCDBTRL (0x39C)
+#define SPR_BOOKE_DCDBTRH (0x39D)
+#define SPR_BOOKE_ICDBTRL (0x39E)
+#define SPR_BOOKE_ICDBTRH (0x39F)
+#define SPR_UMMCR2       (0x3A0)
+#define SPR_UPMC5        (0x3A1)
+#define SPR_UPMC6        (0x3A2)
+#define SPR_UBAMR        (0x3A7)
 #define SPR_UMMCR0       (0x3A8)
 #define SPR_UPMC1        (0x3A9)
 #define SPR_UPMC2        (0x3AA)
-#define SPR_USIA         (0x3AB)
+#define SPR_USIAR        (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_620_PMR0     (0x3B0)
+#define SPR_MMCR2        (0x3B0)
+#define SPR_PMC5         (0x3B1)
 #define SPR_40x_PID      (0x3B1)
+#define SPR_620_PMR1     (0x3B1)
+#define SPR_PMC6         (0x3B2)
 #define SPR_440_MMUCR    (0x3B2)
+#define SPR_620_PMR2     (0x3B2)
 #define SPR_4xx_CCR0     (0x3B3)
 #define SPR_BOOKE_EPLC   (0x3B3)
+#define SPR_620_PMR3     (0x3B3)
 #define SPR_405_IAC3     (0x3B4)
 #define SPR_BOOKE_EPSC   (0x3B4)
+#define SPR_620_PMR4     (0x3B4)
 #define SPR_405_IAC4     (0x3B5)
+#define SPR_620_PMR5     (0x3B5)
 #define SPR_405_DVC1     (0x3B6)
+#define SPR_620_PMR6     (0x3B6)
 #define SPR_405_DVC2     (0x3B7)
+#define SPR_620_PMR7     (0x3B7)
+#define SPR_BAMR         (0x3B7)
 #define SPR_MMCR0        (0x3B8)
+#define SPR_620_PMR8     (0x3B8)
 #define SPR_PMC1         (0x3B9)
 #define SPR_40x_SGR      (0x3B9)
+#define SPR_620_PMR9     (0x3B9)
 #define SPR_PMC2         (0x3BA)
 #define SPR_40x_DCWR     (0x3BA)
-#define SPR_SIA          (0x3BB)
+#define SPR_620_PMRA     (0x3BA)
+#define SPR_SIAR         (0x3BB)
 #define SPR_405_SLER     (0x3BB)
+#define SPR_620_PMRB     (0x3BB)
 #define SPR_MMCR1        (0x3BC)
 #define SPR_405_SU0R     (0x3BC)
+#define SPR_620_PMRC     (0x3BC)
+#define SPR_401_SKR      (0x3BC)
 #define SPR_PMC3         (0x3BD)
 #define SPR_405_DBCR1    (0x3BD)
+#define SPR_620_PMRD     (0x3BD)
 #define SPR_PMC4         (0x3BE)
+#define SPR_620_PMRE     (0x3BE)
 #define SPR_SDA          (0x3BF)
+#define SPR_620_PMRF     (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_BOOKE_ICDBDR (0x3D3)
+#define SPR_TLBMISS      (0x3D4)
 #define SPR_IMISS        (0x3D4)
 #define SPR_40x_ESR      (0x3D4)
+#define SPR_PTEHI        (0x3D5)
 #define SPR_ICMP         (0x3D5)
 #define SPR_40x_DEAR     (0x3D5)
+#define SPR_PTELO        (0x3D6)
 #define SPR_RPA          (0x3D6)
 #define SPR_40x_EVPR     (0x3D6)
+#define SPR_L3PM         (0x3D7)
 #define SPR_403_CDBCR    (0x3D7)
+#define SPR_L3OHCR       (0x3D8)
 #define SPR_TCR          (0x3D8)
 #define SPR_40x_TSR      (0x3D8)
 #define SPR_IBR          (0x3DA)
 #define SPR_40x_TCR      (0x3DA)
-#define SPR_ESASR        (0x3DB)
+#define SPR_ESASRR       (0x3DB)
 #define SPR_40x_PIT      (0x3DB)
 #define SPR_403_TBL      (0x3DC)
 #define SPR_403_TBU      (0x3DD)
@@ -1186,6 +1132,10 @@
 #define SPR_40x_SRR2     (0x3DE)
 #define SPR_SER          (0x3DF)
 #define SPR_40x_SRR3     (0x3DF)
+#define SPR_L3ITCR0      (0x3E8)
+#define SPR_L3ITCR1      (0x3E9)
+#define SPR_L3ITCR2      (0x3EA)
+#define SPR_L3ITCR3      (0x3EB)
 #define SPR_HID0         (0x3F0)
 #define SPR_40x_DBSR     (0x3F0)
 #define SPR_HID1         (0x3F1)
@@ -1193,22 +1143,32 @@
 #define SPR_40x_DBCR0    (0x3F2)
 #define SPR_601_HID2     (0x3F2)
 #define SPR_E500_L1CSR0  (0x3F2)
+#define SPR_ICTRL        (0x3F3)
 #define SPR_HID2         (0x3F3)
 #define SPR_E500_L1CSR1  (0x3F3)
 #define SPR_440_DBDR     (0x3F3)
+#define SPR_LDSTDB       (0x3F4)
 #define SPR_40x_IAC1     (0x3F4)
-#define SPR_BOOKE_MMUCSR0 (0x3F4)
+#define SPR_MMUCSR0      (0x3F4)
 #define SPR_DABR         (0x3F5)
 #define DABR_MASK (~(target_ulong)0x7)
 #define SPR_E500_BUCSR   (0x3F5)
 #define SPR_40x_IAC2     (0x3F5)
 #define SPR_601_HID5     (0x3F5)
 #define SPR_40x_DAC1     (0x3F6)
+#define SPR_MSSCR0       (0x3F6)
+#define SPR_970_HID5     (0x3F6)
+#define SPR_MSSSR0       (0x3F7)
+#define SPR_DABRX        (0x3F7)
 #define SPR_40x_DAC2     (0x3F7)
-#define SPR_BOOKE_MMUCFG (0x3F7)
-#define SPR_L2PM         (0x3F8)
+#define SPR_MMUCFG       (0x3F7)
+#define SPR_LDSTCR       (0x3F8)
+#define SPR_L2PMCR       (0x3F8)
 #define SPR_750_HID2     (0x3F8)
+#define SPR_620_HID8     (0x3F8)
 #define SPR_L2CR         (0x3F9)
+#define SPR_620_HID9     (0x3F9)
+#define SPR_L3CR         (0x3FA)
 #define SPR_IABR2        (0x3FA)
 #define SPR_40x_DCCR     (0x3FA)
 #define SPR_ICTC         (0x3FB)
@@ -1218,6 +1178,7 @@
 #define SPR_SP           (0x3FD)
 #define SPR_THRM2        (0x3FD)
 #define SPR_403_PBU1     (0x3FD)
+#define SPR_604_HID13    (0x3FD)
 #define SPR_LT           (0x3FE)
 #define SPR_THRM3        (0x3FE)
 #define SPR_FPECR        (0x3FE)
@@ -1225,6 +1186,7 @@
 #define SPR_PIR          (0x3FF)
 #define SPR_403_PBU2     (0x3FF)
 #define SPR_601_HID15    (0x3FF)
+#define SPR_604_HID15    (0x3FF)
 #define SPR_E500_SVR     (0x3FF)
 
 /*****************************************************************************/
@@ -1244,112 +1206,6 @@
     ACCESS_CACHE = 0x60, /* Cache manipulation               */
 };
 
-/*****************************************************************************/
-/* Exceptions */
-#define EXCP_NONE          -1
-/* PowerPC hardware exceptions : exception vectors defined in PowerPC book 3 */
-#define EXCP_RESET         0x0100 /* System reset                            */
-#define EXCP_MACHINE_CHECK 0x0200 /* Machine check exception                 */
-#define EXCP_DSI           0x0300 /* Data storage exception                  */
-#define EXCP_DSEG          0x0380 /* Data segment exception                  */
-#define EXCP_ISI           0x0400 /* Instruction storage exception           */
-#define EXCP_ISEG          0x0480 /* Instruction segment exception           */
-#define EXCP_EXTERNAL      0x0500 /* External interruption                   */
-#define EXCP_ALIGN         0x0600 /* Alignment exception                     */
-#define EXCP_PROGRAM       0x0700 /* Program exception                       */
-#define EXCP_NO_FP         0x0800 /* Floating point unavailable exception    */
-#define EXCP_DECR          0x0900 /* Decrementer exception                   */
-#define EXCP_HDECR         0x0980 /* Hypervisor decrementer exception        */
-#define EXCP_SYSCALL       0x0C00 /* System call                             */
-#define EXCP_TRACE         0x0D00 /* Trace exception                         */
-#define EXCP_PERF          0x0F00 /* Performance monitor exception           */
-/* Exceptions defined in PowerPC 32 bits programming environment manual      */
-#define EXCP_FP_ASSIST     0x0E00 /* Floating-point assist                   */
-/* Implementation specific exceptions                                        */
-/* 40x exceptions                                                            */
-#define EXCP_40x_PIT       0x1000 /* Programmable interval timer interrupt   */
-#define EXCP_40x_FIT       0x1010 /* Fixed interval timer interrupt          */
-#define EXCP_40x_WATCHDOG  0x1020 /* Watchdog timer exception                */
-#define EXCP_40x_DTLBMISS  0x1100 /* Data TLB miss exception                 */
-#define EXCP_40x_ITLBMISS  0x1200 /* Instruction TLB miss exception          */
-#define EXCP_40x_DEBUG     0x2000 /* Debug exception                         */
-/* 405 specific exceptions                                                   */
-#define EXCP_405_APU       0x0F20 /* APU unavailable exception               */
-/* TLB assist exceptions (602/603)                                           */
-#define EXCP_I_TLBMISS     0x1000 /* Instruction TLB miss                    */
-#define EXCP_DL_TLBMISS    0x1100 /* Data load TLB miss                      */
-#define EXCP_DS_TLBMISS    0x1200 /* Data store TLB miss                     */
-/* Breakpoint exceptions (602/603/604/620/740/745/750/755...)                */
-#define EXCP_IABR          0x1300 /* Instruction address breakpoint          */
-#define EXCP_SMI           0x1400 /* System management interrupt             */
-/* Altivec related exceptions                                                */
-#define EXCP_VPU           0x0F20 /* VPU unavailable exception               */
-/* 601 specific exceptions                                                   */
-#define EXCP_601_IO        0x0600 /* IO error exception                      */
-#define EXCP_601_RUNM      0x2000 /* Run mode exception                      */
-/* 602 specific exceptions                                                   */
-#define EXCP_602_WATCHDOG  0x1500 /* Watchdog exception                      */
-#define EXCP_602_EMUL      0x1600 /* Emulation trap exception                */
-/* G2 specific exceptions                                                    */
-#define EXCP_G2_CRIT       0x0A00 /* Critical interrupt                      */
-/* MPC740/745/750 & IBM 750 specific exceptions                              */
-#define EXCP_THRM          0x1700 /* Thermal management interrupt            */
-/* 74xx specific exceptions                                                  */
-#define EXCP_74xx_VPUA     0x1600 /* VPU assist exception                    */
-/* 970FX specific exceptions                                                 */
-#define EXCP_970_SOFTP     0x1500 /* Soft patch exception                    */
-#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             */
-#define EXCP_BRANCH        0x11001 /* branch instruction                     */
-#define EXCP_SYSCALL_USER  0x12000 /* System call in user mode only          */
-
-/* Error codes */
-enum {
-    /* Exception subtypes for EXCP_ALIGN                            */
-    EXCP_ALIGN_FP      = 0x01,  /* FP alignment exception           */
-    EXCP_ALIGN_LST     = 0x02,  /* Unaligned mult/extern load/store */
-    EXCP_ALIGN_LE      = 0x03,  /* Multiple little-endian access    */
-    EXCP_ALIGN_PROT    = 0x04,  /* Access cross protection boundary */
-    EXCP_ALIGN_BAT     = 0x05,  /* Access cross a BAT/seg boundary  */
-    EXCP_ALIGN_CACHE   = 0x06,  /* Impossible dcbz access           */
-    /* Exception subtypes for EXCP_PROGRAM                          */
-    /* FP exceptions */
-    EXCP_FP            = 0x10,
-    EXCP_FP_OX         = 0x01,  /* FP overflow                      */
-    EXCP_FP_UX         = 0x02,  /* FP underflow                     */
-    EXCP_FP_ZX         = 0x03,  /* FP divide by zero                */
-    EXCP_FP_XX         = 0x04,  /* FP inexact                       */
-    EXCP_FP_VXNAN      = 0x05,  /* FP invalid SNaN op               */
-    EXCP_FP_VXISI      = 0x06,  /* FP invalid infinite subtraction */
-    EXCP_FP_VXIDI      = 0x07,  /* FP invalid infinite divide       */
-    EXCP_FP_VXZDZ      = 0x08,  /* FP invalid zero divide           */
-    EXCP_FP_VXIMZ      = 0x09,  /* FP invalid infinite * zero       */
-    EXCP_FP_VXVC       = 0x0A,  /* FP invalid compare               */
-    EXCP_FP_VXSOFT     = 0x0B,  /* FP invalid operation             */
-    EXCP_FP_VXSQRT     = 0x0C,  /* FP invalid square root           */
-    EXCP_FP_VXCVI      = 0x0D,  /* FP invalid integer conversion    */
-    /* Invalid instruction */
-    EXCP_INVAL         = 0x20,
-    EXCP_INVAL_INVAL   = 0x01,  /* Invalid instruction              */
-    EXCP_INVAL_LSWX    = 0x02,  /* Invalid lswx instruction         */
-    EXCP_INVAL_SPR     = 0x03,  /* Invalid SPR access               */
-    EXCP_INVAL_FP      = 0x04,  /* Unimplemented mandatory fp instr */
-    /* Privileged instruction */
-    EXCP_PRIV          = 0x30,
-    EXCP_PRIV_OPC      = 0x01,  /* Privileged operation exception   */
-    EXCP_PRIV_REG      = 0x02,  /* Privileged register exception    */
-    /* Trap */
-    EXCP_TRAP          = 0x40,
-};
-
 /* Hardware interruption sources:
  * all those exception can be raised simulteaneously
  */
@@ -1362,6 +1218,9 @@
     PPC6xx_INPUT_MCP        = 3,
     PPC6xx_INPUT_SMI        = 4,
     PPC6xx_INPUT_INT        = 5,
+    PPC6xx_INPUT_TBEN       = 6,
+    PPC6xx_INPUT_WAKEUP     = 7,
+    PPC6xx_INPUT_NB,
 };
 
 enum {
@@ -1373,19 +1232,22 @@
     PPCBookE_INPUT_SMI        = 4,
     PPCBookE_INPUT_INT        = 5,
     PPCBookE_INPUT_CINT       = 6,
+    PPCBookE_INPUT_NB,
 };
 
 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,
+    /* PowerPC 40x input pins */
+    PPC40x_INPUT_RESET_CORE = 0,
+    PPC40x_INPUT_RESET_CHIP = 1,
+    PPC40x_INPUT_RESET_SYS  = 2,
+    PPC40x_INPUT_CINT       = 3,
+    PPC40x_INPUT_INT        = 4,
+    PPC40x_INPUT_HALT       = 5,
+    PPC40x_INPUT_DEBUG      = 6,
+    PPC40x_INPUT_NB,
 };
 
+#if defined(TARGET_PPC64)
 enum {
     /* PowerPC 970 input pins */
     PPC970_INPUT_HRESET     = 0,
@@ -1396,23 +1258,28 @@
     PPC970_INPUT_INT        = 5,
     PPC970_INPUT_THINT      = 6,
 };
+#endif
 
 /* 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                    */
+    PPC_INTERRUPT_RESET     = 0,  /* Reset exception                      */
+    PPC_INTERRUPT_WAKEUP,         /* Wakeup exception                     */
+    PPC_INTERRUPT_MCK,            /* Machine check exception              */
+    PPC_INTERRUPT_EXT,            /* External interrupt                   */
+    PPC_INTERRUPT_SMI,            /* System management interrupt          */
+    PPC_INTERRUPT_CEXT,           /* Critical external interrupt          */
+    PPC_INTERRUPT_DEBUG,          /* External debug exception             */
+    PPC_INTERRUPT_THERM,          /* 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             */
+    PPC_INTERRUPT_DECR,           /* Decrementer exception                */
+    PPC_INTERRUPT_HDECR,          /* Hypervisor decrementer exception     */
+    PPC_INTERRUPT_PIT,            /* Programmable inteval timer interrupt */
+    PPC_INTERRUPT_FIT,            /* Fixed interval timer interrupt       */
+    PPC_INTERRUPT_WDT,            /* Watchdog timer interrupt             */
+    PPC_INTERRUPT_CDOORBELL,      /* Critical doorbell interrupt          */
+    PPC_INTERRUPT_DOORBELL,       /* Doorbell interrupt                   */
+    PPC_INTERRUPT_PERFM,          /* Performance monitor interrupt        */
 };
 
 /*****************************************************************************/

Modified: trunk/src/host/qemu-neo1973/target-ppc/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/exec.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-ppc/exec.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -54,9 +54,9 @@
 #define T2_64 T2
 #endif
 /* Provision for Altivec */
-#define T0_avr (env->t0_avr)
-#define T1_avr (env->t1_avr)
-#define T2_avr (env->t2_avr)
+#define AVR0 (env->avr0)
+#define AVR1 (env->avr1)
+#define AVR2 (env->avr2)
 
 #define FT0 (env->ft0)
 #define FT1 (env->ft1)
@@ -68,23 +68,23 @@
 # define RETURN() __asm__ __volatile__("" : : : "memory");
 #endif
 
-static inline target_ulong rotl8 (target_ulong i, int n)
+static always_inline target_ulong rotl8 (target_ulong i, int n)
 {
     return (((uint8_t)i << n) | ((uint8_t)i >> (8 - n)));
 }
 
-static inline target_ulong rotl16 (target_ulong i, int n)
+static always_inline target_ulong rotl16 (target_ulong i, int n)
 {
     return (((uint16_t)i << n) | ((uint16_t)i >> (16 - n)));
 }
 
-static inline target_ulong rotl32 (target_ulong i, int n)
+static always_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)
+static always_inline target_ulong rotl64 (target_ulong i, int n)
 {
     return (((uint64_t)i << n) | ((uint64_t)i >> (64 - n)));
 }
@@ -100,29 +100,25 @@
 int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong vaddr,
                           int rw, int access_type, int check_BATs);
 
-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);
 
-static inline void env_to_regs (void)
+static always_inline void env_to_regs (void)
 {
 }
 
-static inline void regs_to_env (void)
+static always_inline void regs_to_env (void)
 {
 }
 
 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                              int is_user, int is_softmmu);
+                              int mmu_idx, int is_softmmu);
 
-static inline int cpu_halted (CPUState *env)
+static always_inline int cpu_halted (CPUState *env)
 {
     if (!env->halted)
         return 0;
-    if (env->msr[MSR_EE] && (env->interrupt_request & CPU_INTERRUPT_HARD)) {
+    if (msr_ee && (env->interrupt_request & CPU_INTERRUPT_HARD)) {
         env->halted = 0;
         return 0;
     }

Modified: trunk/src/host/qemu-neo1973/target-ppc/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-ppc/helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -27,10 +27,12 @@
 
 #include "cpu.h"
 #include "exec-all.h"
+#include "helper_regs.h"
 
 //#define DEBUG_MMU
 //#define DEBUG_BATS
 //#define DEBUG_SOFTWARE_TLB
+//#define DUMP_PAGE_TABLES
 //#define DEBUG_EXCEPTIONS
 //#define FLUSH_ALL_TLBS
 
@@ -39,16 +41,16 @@
 
 #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 mmu_idx, int is_softmmu)
 {
     int exception, error_code;
 
     if (rw == 2) {
-        exception = EXCP_ISI;
-        error_code = 0;
+        exception = POWERPC_EXCP_ISI;
+        error_code = 0x40000000;
     } else {
-        exception = EXCP_DSI;
-        error_code = 0;
+        exception = POWERPC_EXCP_DSI;
+        error_code = 0x40000000;
         if (rw)
             error_code |= 0x02000000;
         env->spr[SPR_DAR] = address;
@@ -67,23 +69,23 @@
 
 #else
 /* Common routines used by software and hardware TLBs emulation */
-static inline int pte_is_valid (target_ulong pte0)
+static always_inline int pte_is_valid (target_ulong pte0)
 {
     return pte0 & 0x80000000 ? 1 : 0;
 }
 
-static inline void pte_invalidate (target_ulong *pte0)
+static always_inline void pte_invalidate (target_ulong *pte0)
 {
     *pte0 &= ~0x80000000;
 }
 
 #if defined(TARGET_PPC64)
-static inline int pte64_is_valid (target_ulong pte0)
+static always_inline int pte64_is_valid (target_ulong pte0)
 {
     return pte0 & 0x0000000000000001ULL ? 1 : 0;
 }
 
-static inline void pte64_invalidate (target_ulong *pte0)
+static always_inline void pte64_invalidate (target_ulong *pte0)
 {
     *pte0 &= ~0x0000000000000001ULL;
 }
@@ -96,12 +98,76 @@
 #define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
 #endif
 
-static inline int _pte_check (mmu_ctx_t *ctx, int is_64b,
-                              target_ulong pte0, target_ulong pte1,
-                              int h, int rw)
+static always_inline int pp_check (int key, int pp, int nx)
 {
+    int access;
+
+    /* Compute access rights */
+    /* When pp is 3/7, the result is undefined. Set it to noaccess */
+    access = 0;
+    if (key == 0) {
+        switch (pp) {
+        case 0x0:
+        case 0x1:
+        case 0x2:
+            access |= PAGE_WRITE;
+            /* No break here */
+        case 0x3:
+        case 0x6:
+            access |= PAGE_READ;
+            break;
+        }
+    } else {
+        switch (pp) {
+        case 0x0:
+        case 0x6:
+            access = 0;
+            break;
+        case 0x1:
+        case 0x3:
+            access = PAGE_READ;
+            break;
+        case 0x2:
+            access = PAGE_READ | PAGE_WRITE;
+            break;
+        }
+    }
+    if (nx == 0)
+        access |= PAGE_EXEC;
+
+    return access;
+}
+
+static always_inline int check_prot (int prot, int rw, int access_type)
+{
+    int ret;
+
+    if (access_type == ACCESS_CODE) {
+        if (prot & PAGE_EXEC)
+            ret = 0;
+        else
+            ret = -2;
+    } else if (rw) {
+        if (prot & PAGE_WRITE)
+            ret = 0;
+        else
+            ret = -2;
+    } else {
+        if (prot & PAGE_READ)
+            ret = 0;
+        else
+            ret = -2;
+    }
+
+    return ret;
+}
+
+static always_inline int _pte_check (mmu_ctx_t *ctx, int is_64b,
+                                     target_ulong pte0, target_ulong pte1,
+                                     int h, int rw, int type)
+{
     target_ulong ptem, mmask;
-    int access, ret, pteh, ptev;
+    int access, ret, pteh, ptev, pp;
 
     access = 0;
     ret = -1;
@@ -122,11 +188,15 @@
         if (is_64b) {
             ptem = pte0 & PTE64_PTEM_MASK;
             mmask = PTE64_CHECK_MASK;
+            pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
+            ctx->nx |= (pte1 >> 2) & 1; /* No execute bit */
+            ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
         } else
 #endif
         {
             ptem = pte0 & PTE_PTEM_MASK;
             mmask = PTE_CHECK_MASK;
+            pp = pte1 & 0x00000003;
         }
         if (ptem == ctx->ptem) {
             if (ctx->raddr != (target_ulong)-1) {
@@ -138,42 +208,23 @@
                 }
             }
             /* 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;
-                }
-            }
+            access = pp_check(ctx->key, pp, ctx->nx);
             /* Keep the matching PTE informations */
             ctx->raddr = pte1;
             ctx->prot = access;
-            if ((rw == 0 && (access & PAGE_READ)) ||
-                (rw == 1 && (access & PAGE_WRITE))) {
+            ret = check_prot(ctx->prot, rw, type);
+            if (ret == 0) {
                 /* 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;
             }
         }
     }
@@ -181,22 +232,24 @@
     return ret;
 }
 
-static int pte32_check (mmu_ctx_t *ctx,
-                        target_ulong pte0, target_ulong pte1, int h, int rw)
+static always_inline int pte32_check (mmu_ctx_t *ctx,
+                                      target_ulong pte0, target_ulong pte1,
+                                      int h, int rw, int type)
 {
-    return _pte_check(ctx, 0, pte0, pte1, h, rw);
+    return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
 }
 
 #if defined(TARGET_PPC64)
-static int pte64_check (mmu_ctx_t *ctx,
-                        target_ulong pte0, target_ulong pte1, int h, int rw)
+static always_inline int pte64_check (mmu_ctx_t *ctx,
+                                      target_ulong pte0, target_ulong pte1,
+                                      int h, int rw, int type)
 {
-    return _pte_check(ctx, 1, pte0, pte1, h, rw);
+    return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
 }
 #endif
 
-static int pte_update_flags (mmu_ctx_t *ctx, target_ulong *pte1p,
-                             int ret, int rw)
+static always_inline int pte_update_flags (mmu_ctx_t *ctx, target_ulong *pte1p,
+                                           int ret, int rw)
 {
     int store = 0;
 
@@ -221,8 +274,8 @@
 }
 
 /* Software driven TLB helpers */
-static int ppc6xx_tlb_getnum (CPUState *env, target_ulong eaddr,
-                              int way, int is_code)
+static always_inline int ppc6xx_tlb_getnum (CPUState *env, target_ulong eaddr,
+                                            int way, int is_code)
 {
     int nr;
 
@@ -237,7 +290,7 @@
     return nr;
 }
 
-void ppc6xx_tlb_invalidate_all (CPUState *env)
+static always_inline void ppc6xx_tlb_invalidate_all (CPUState *env)
 {
     ppc6xx_tlb_t *tlb;
     int nr, max;
@@ -253,19 +306,15 @@
         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)
+static always_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;
@@ -292,8 +341,9 @@
 #endif
 }
 
-void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
-                                 int is_code)
+static always_inline void ppc6xx_tlb_invalidate_virt (CPUState *env,
+                                                      target_ulong eaddr,
+                                                      int is_code)
 {
     __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
 }
@@ -321,8 +371,9 @@
     env->last_way = way;
 }
 
-static int ppc6xx_tlb_check (CPUState *env, mmu_ctx_t *ctx,
-                             target_ulong eaddr, int rw, int access_type)
+static always_inline 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;
@@ -357,7 +408,7 @@
                     rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
         }
 #endif
-        switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw)) {
+        switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
         case -3:
             /* TLB inconsistency */
             return -1;
@@ -397,12 +448,12 @@
 }
 
 /* Perform BAT hit & translation */
-static int get_bat (CPUState *env, mmu_ctx_t *ctx,
-                    target_ulong virtual, int rw, int type)
+static always_inline int get_bat (CPUState *env, mmu_ctx_t *ctx,
+                                  target_ulong virtual, int rw, int type)
 {
     target_ulong *BATlt, *BATut, *BATu, *BATl;
     target_ulong base, BEPIl, BEPIu, bl;
-    int i;
+    int i, pp, pr;
     int ret = -1;
 
 #if defined (DEBUG_BATS)
@@ -411,6 +462,7 @@
                 type == ACCESS_CODE ? 'I' : 'D', virtual);
     }
 #endif
+    pr = msr_pr;
     switch (type) {
     case ACCESS_CODE:
         BATlt = env->IBAT[1];
@@ -445,25 +497,29 @@
         if ((virtual & 0xF0000000) == BEPIu &&
             ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
             /* BAT matches */
-            if ((msr_pr == 0 && (*BATu & 0x00000002)) ||
-                (msr_pr == 1 && (*BATu & 0x00000001))) {
+            if (((pr == 0) && (*BATu & 0x00000002)) ||
+                ((pr != 0) && (*BATu & 0x00000001))) {
                 /* Get physical address */
                 ctx->raddr = (*BATl & 0xF0000000) |
                     ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
                     (virtual & 0x0001F000);
-                if (*BATl & 0x00000001)
-                    ctx->prot = PAGE_READ;
-                if (*BATl & 0x00000002)
-                    ctx->prot = PAGE_WRITE | PAGE_READ;
+                /* Compute access rights */
+                pp = *BATl & 0x00000003;
+                ctx->prot = 0;
+                if (pp != 0) {
+                    ctx->prot = PAGE_READ | PAGE_EXEC;
+                    if (pp == 0x2)
+                        ctx->prot |= PAGE_WRITE;
+                }
+                ret = check_prot(ctx->prot, rw, type);
 #if defined (DEBUG_BATS)
-                if (loglevel != 0) {
+                if (ret == 0 && 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;
                 break;
             }
         }
@@ -487,12 +543,14 @@
         }
 #endif
     }
+
     /* No hit */
     return ret;
 }
 
 /* PTE table lookup */
-static inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h, int rw)
+static always_inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h,
+                                    int rw, int type)
 {
     target_ulong base, pte0, pte1;
     int i, good = -1;
@@ -505,22 +563,32 @@
         if (is_64b) {
             pte0 = ldq_phys(base + (i * 16));
             pte1 =  ldq_phys(base + (i * 16) + 8);
-            r = pte64_check(ctx, pte0, pte1, h, rw);
+            r = pte64_check(ctx, pte0, pte1, h, rw, type);
+#if defined (DEBUG_MMU)
+            if (loglevel != 0) {
+                fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX
+                        " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
+                        base + (i * 16), pte0, pte1,
+                        (int)(pte0 & 1), h, (int)((pte0 >> 1) & 1),
+                        ctx->ptem);
+            }
+#endif
         } else
 #endif
         {
             pte0 = ldl_phys(base + (i * 8));
             pte1 =  ldl_phys(base + (i * 8) + 4);
-            r = pte32_check(ctx, pte0, pte1, h, rw);
-        }
+            r = pte32_check(ctx, pte0, pte1, h, rw, type);
 #if defined (DEBUG_MMU)
-        if (loglevel != 0) {
-            fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX
-                    " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
-                    base + (i * 8), pte0, pte1,
-                    (int)(pte0 >> 31), h, (int)((pte0 >> 6) & 1), ctx->ptem);
+            if (loglevel != 0) {
+                fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX
+                        " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
+                        base + (i * 8), pte0, pte1,
+                        (int)(pte0 >> 31), h, (int)((pte0 >> 6) & 1),
+                        ctx->ptem);
+            }
+#endif
         }
-#endif
         switch (r) {
         case -3:
             /* PTE inconsistency */
@@ -571,59 +639,69 @@
     return ret;
 }
 
-static int find_pte32 (mmu_ctx_t *ctx, int h, int rw)
+static always_inline int find_pte32 (mmu_ctx_t *ctx, int h, int rw, int type)
 {
-    return _find_pte(ctx, 0, h, rw);
+    return _find_pte(ctx, 0, h, rw, type);
 }
 
 #if defined(TARGET_PPC64)
-static int find_pte64 (mmu_ctx_t *ctx, int h, int rw)
+static always_inline int find_pte64 (mmu_ctx_t *ctx, int h, int rw, int type)
 {
-    return _find_pte(ctx, 1, h, rw);
+    return _find_pte(ctx, 1, h, rw, type);
 }
 #endif
 
-static inline int find_pte (CPUState *env, mmu_ctx_t *ctx, int h, int rw)
+static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx,
+                                   int h, int rw, int type)
 {
 #if defined(TARGET_PPC64)
-    if (PPC_MMU(env) == PPC_FLAGS_MMU_64B ||
-        PPC_MMU(env) == PPC_FLAGS_MMU_64BRIDGE)
-        return find_pte64(ctx, h, rw);
+    if (env->mmu_model == POWERPC_MMU_64B)
+        return find_pte64(ctx, h, rw, type);
 #endif
 
-    return find_pte32(ctx, h, rw);
+    return find_pte32(ctx, h, rw, type);
 }
 
-static inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
-                                             int sdr_sh,
-                                             target_phys_addr_t hash,
-                                             target_phys_addr_t mask)
+#if defined(TARGET_PPC64)
+static always_inline int slb_is_valid (uint64_t slb64)
 {
-    return (sdr1 & ((target_ulong)(-1ULL) << sdr_sh)) | (hash & mask);
+    return slb64 & 0x0000000008000000ULL ? 1 : 0;
 }
 
-#if defined(TARGET_PPC64)
-static int slb_lookup (CPUState *env, target_ulong eaddr,
-                       target_ulong *vsid, target_ulong *page_mask, int *attr)
+static always_inline void slb_invalidate (uint64_t *slb64)
 {
+    *slb64 &= ~0x0000000008000000ULL;
+}
+
+static always_inline int slb_lookup (CPUPPCState *env, target_ulong eaddr,
+                                     target_ulong *vsid,
+                                     target_ulong *page_mask, int *attr)
+{
     target_phys_addr_t sr_base;
     target_ulong mask;
     uint64_t tmp64;
     uint32_t tmp;
     int n, ret;
-    int slb_nr;
 
     ret = -5;
     sr_base = env->spr[SPR_ASR];
+#if defined(DEBUG_SLB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: eaddr " ADDRX " base " PADDRX "\n",
+                __func__, eaddr, sr_base);
+    }
+#endif
     mask = 0x0000000000000000ULL; /* Avoid gcc warning */
-#if 0 /* XXX: Fix this */
-    slb_nr = env->slb_nr;
-#else
-    slb_nr = 32;
+    for (n = 0; n < env->slb_nr; n++) {
+        tmp64 = ldq_phys(sr_base);
+        tmp = ldl_phys(sr_base + 8);
+#if defined(DEBUG_SLB)
+        if (loglevel != 0) {
+            fprintf(logfile, "%s: seg %d " PADDRX " %016" PRIx64 " %08"
+                    PRIx32 "\n", __func__, n, sr_base, tmp64, tmp);
+        }
 #endif
-    for (n = 0; n < slb_nr; n++) {
-        tmp64 = ldq_phys(sr_base);
-        if (tmp64 & 0x0000000008000000ULL) {
+        if (slb_is_valid(tmp64)) {
             /* SLB entry is valid */
             switch (tmp64 & 0x0000000006000000ULL) {
             case 0x0000000000000000ULL:
@@ -641,11 +719,10 @@
             }
             if ((eaddr & mask) == (tmp64 & mask)) {
                 /* SLB match */
-                tmp = ldl_phys(sr_base + 8);
                 *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
                 *page_mask = ~mask;
                 *attr = tmp & 0xFF;
-                ret = 0;
+                ret = n;
                 break;
             }
         }
@@ -654,29 +731,153 @@
 
     return ret;
 }
+
+void ppc_slb_invalidate_all (CPUPPCState *env)
+{
+    target_phys_addr_t sr_base;
+    uint64_t tmp64;
+    int n, do_invalidate;
+
+    do_invalidate = 0;
+    sr_base = env->spr[SPR_ASR];
+    /* XXX: Warning: slbia never invalidates the first segment */
+    for (n = 1; n < env->slb_nr; n++) {
+        tmp64 = ldq_phys(sr_base);
+        if (slb_is_valid(tmp64)) {
+            slb_invalidate(&tmp64);
+            stq_phys(sr_base, tmp64);
+            /* XXX: given the fact that segment size is 256 MB or 1TB,
+             *      and we still don't have a tlb_flush_mask(env, n, mask)
+             *      in Qemu, we just invalidate all TLBs
+             */
+            do_invalidate = 1;
+        }
+        sr_base += 12;
+    }
+    if (do_invalidate)
+        tlb_flush(env, 1);
+}
+
+void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
+{
+    target_phys_addr_t sr_base;
+    target_ulong vsid, page_mask;
+    uint64_t tmp64;
+    int attr;
+    int n;
+
+    n = slb_lookup(env, T0, &vsid, &page_mask, &attr);
+    if (n >= 0) {
+        sr_base = env->spr[SPR_ASR];
+        sr_base += 12 * n;
+        tmp64 = ldq_phys(sr_base);
+        if (slb_is_valid(tmp64)) {
+            slb_invalidate(&tmp64);
+            stq_phys(sr_base, tmp64);
+            /* XXX: given the fact that segment size is 256 MB or 1TB,
+             *      and we still don't have a tlb_flush_mask(env, n, mask)
+             *      in Qemu, we just invalidate all TLBs
+             */
+            tlb_flush(env, 1);
+        }
+    }
+}
+
+target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
+{
+    target_phys_addr_t sr_base;
+    target_ulong rt;
+    uint64_t tmp64;
+    uint32_t tmp;
+
+    sr_base = env->spr[SPR_ASR];
+    sr_base += 12 * slb_nr;
+    tmp64 = ldq_phys(sr_base);
+    tmp = ldl_phys(sr_base + 8);
+    if (tmp64 & 0x0000000008000000ULL) {
+        /* SLB entry is valid */
+        /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
+        rt = tmp >> 8;             /* 65:88 => 40:63 */
+        rt |= (tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
+        /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
+        rt |= ((tmp >> 4) & 0xF) << 27;
+    } else {
+        rt = 0;
+    }
+#if defined(DEBUG_SLB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: " PADDRX " %016" PRIx64 " %08" PRIx32 " => %d "
+                ADDRX "\n", __func__, sr_base, tmp64, tmp, slb_nr, rt);
+    }
+#endif
+
+    return rt;
+}
+
+void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs)
+{
+    target_phys_addr_t sr_base;
+    uint64_t tmp64;
+    uint32_t tmp;
+
+    sr_base = env->spr[SPR_ASR];
+    sr_base += 12 * slb_nr;
+    /* Copy Rs bits 37:63 to SLB 62:88 */
+    tmp = rs << 8;
+    tmp64 = (rs >> 24) & 0x7;
+    /* Copy Rs bits 33:36 to SLB 89:92 */
+    tmp |= ((rs >> 27) & 0xF) << 4;
+    /* Set the valid bit */
+    tmp64 |= 1 << 27;
+    /* Set ESID */
+    tmp64 |= (uint32_t)slb_nr << 28;
+#if defined(DEBUG_SLB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: %d " ADDRX " => " PADDRX " %016" PRIx64 " %08"
+                PRIx32 "\n", __func__, slb_nr, rs, sr_base, tmp64, tmp);
+    }
+#endif
+    /* Write SLB entry to memory */
+    stq_phys(sr_base, tmp64);
+    stl_phys(sr_base + 8, tmp);
+}
 #endif /* defined(TARGET_PPC64) */
 
 /* Perform segment based translation */
-static int get_segment (CPUState *env, mmu_ctx_t *ctx,
-                        target_ulong eaddr, int rw, int type)
+static always_inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
+                                                    int sdr_sh,
+                                                    target_phys_addr_t hash,
+                                                    target_phys_addr_t mask)
 {
-    target_phys_addr_t sdr, hash, mask, sdr_mask;
+    return (sdr1 & ((target_ulong)(-1ULL) << sdr_sh)) | (hash & mask);
+}
+
+static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
+                                      target_ulong eaddr, int rw, int type)
+{
+    target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
     target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
 #if defined(TARGET_PPC64)
     int attr;
 #endif
-    int ds, nx, vsid_sh, sdr_sh;
+    int ds, vsid_sh, sdr_sh, pr;
     int ret, ret2;
 
+    pr = msr_pr;
 #if defined(TARGET_PPC64)
-    if (PPC_MMU(env) == PPC_FLAGS_MMU_64B) {
+    if (env->mmu_model == POWERPC_MMU_64B) {
+#if defined (DEBUG_MMU)
+        if (loglevel != 0) {
+            fprintf(logfile, "Check SLBs\n");
+        }
+#endif
         ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr);
         if (ret < 0)
             return ret;
-        ctx->key = ((attr & 0x40) && msr_pr == 1) ||
-            ((attr & 0x80) && msr_pr == 0) ? 1 : 0;
+        ctx->key = ((attr & 0x40) && (pr != 0)) ||
+            ((attr & 0x80) && (pr == 0)) ? 1 : 0;
         ds = 0;
-        nx = attr & 0x20 ? 1 : 0;
+        ctx->nx = attr & 0x20 ? 1 : 0;
         vsid_mask = 0x00003FFFFFFFFF80ULL;
         vsid_sh = 7;
         sdr_sh = 18;
@@ -686,10 +887,10 @@
     {
         sr = env->sr[eaddr >> 28];
         page_mask = 0x0FFFFFFF;
-        ctx->key = (((sr & 0x20000000) && msr_pr == 1) ||
-                    ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0;
+        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
+                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
         ds = sr & 0x80000000 ? 1 : 0;
-        nx = sr & 0x10000000 ? 1 : 0;
+        ctx->nx = sr & 0x10000000 ? 1 : 0;
         vsid = sr & 0x00FFFFFF;
         vsid_mask = 0x01FFFFC0;
         vsid_sh = 6;
@@ -701,31 +902,56 @@
                     " nip=0x" ADDRX " lr=0x" ADDRX
                     " ir=%d dr=%d pr=%d %d t=%d\n",
                     eaddr, (int)(eaddr >> 28), sr, env->nip,
-                    env->lr, msr_ir, msr_dr, msr_pr, rw, type);
+                    env->lr, (int)msr_ir, (int)msr_dr, pr != 0 ? 1 : 0,
+                    rw, type);
         }
-        if (!ds && loglevel != 0) {
-            fprintf(logfile, "pte segment: key=%d n=0x" ADDRX "\n",
-                    ctx->key, sr & 0x10000000);
-        }
 #endif
     }
+#if defined (DEBUG_MMU)
+    if (loglevel != 0) {
+        fprintf(logfile, "pte segment: key=%d ds %d nx %d vsid " ADDRX "\n",
+                ctx->key, ds, ctx->nx, vsid);
+    }
+#endif
     ret = -1;
     if (!ds) {
         /* Check if instruction fetch is allowed, if needed */
-        if (type != ACCESS_CODE || nx == 0) {
+        if (type != ACCESS_CODE || ctx->nx == 0) {
             /* Page address translation */
-            pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS;
-            hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
             /* Primary table address */
             sdr = env->sdr1;
-            mask = ((sdr & 0x000001FF) << sdr_sh) | sdr_mask;
+            pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS;
+#if defined(TARGET_PPC64)
+            if (env->mmu_model == POWERPC_MMU_64B) {
+                htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
+                /* XXX: this is false for 1 TB segments */
+                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
+            } else
+#endif
+            {
+                htab_mask = sdr & 0x000001FF;
+                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
+            }
+            mask = (htab_mask << sdr_sh) | sdr_mask;
+#if defined (DEBUG_MMU)
+            if (loglevel != 0) {
+                fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX " mask "
+                        PADDRX " " ADDRX "\n", sdr, sdr_sh, hash, mask,
+                        page_mask);
+            }
+#endif
             ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask);
             /* Secondary table address */
             hash = (~hash) & vsid_mask;
+#if defined (DEBUG_MMU)
+            if (loglevel != 0) {
+                fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX " mask "
+                        PADDRX "\n", sdr, sdr_sh, hash, mask);
+            }
+#endif
             ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
 #if defined(TARGET_PPC64)
-            if (PPC_MMU(env) == PPC_FLAGS_MMU_64B ||
-                PPC_MMU(env) == PPC_FLAGS_MMU_64BRIDGE) {
+            if (env->mmu_model == POWERPC_MMU_64B) {
                 /* Only 5 bits of the page index are used in the AVPN */
                 ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
             } else
@@ -735,7 +961,8 @@
             }
             /* Initialize real address with an invalid value */
             ctx->raddr = (target_ulong)-1;
-            if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
+            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
+                         env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
                 /* Software TLB search */
                 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
             } else {
@@ -748,7 +975,7 @@
                 }
 #endif
                 /* Primary table lookup */
-                ret = find_pte(env, ctx, 0, rw);
+                ret = find_pte(env, ctx, 0, rw, type);
                 if (ret < 0) {
                     /* Secondary table lookup */
 #if defined (DEBUG_MMU)
@@ -760,11 +987,32 @@
                                 (uint32_t)hash, ctx->pg_addr[1]);
                     }
 #endif
-                    ret2 = find_pte(env, ctx, 1, rw);
+                    ret2 = find_pte(env, ctx, 1, rw, type);
                     if (ret2 != -1)
                         ret = ret2;
                 }
             }
+#if defined (DUMP_PAGE_TABLES)
+            if (loglevel != 0) {
+                target_phys_addr_t curaddr;
+                uint32_t a0, a1, a2, a3;
+                fprintf(logfile,
+                        "Page table: " PADDRX " len " PADDRX "\n",
+                        sdr, mask + 0x80);
+                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
+                     curaddr += 16) {
+                    a0 = ldl_phys(curaddr);
+                    a1 = ldl_phys(curaddr + 4);
+                    a2 = ldl_phys(curaddr + 8);
+                    a3 = ldl_phys(curaddr + 12);
+                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
+                        fprintf(logfile,
+                                PADDRX ": %08x %08x %08x %08x\n",
+                                curaddr, a0, a1, a2, a3);
+                    }
+                }
+            }
+#endif
         } else {
 #if defined (DEBUG_MMU)
             if (loglevel != 0)
@@ -820,10 +1068,10 @@
 }
 
 /* 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,
-                             uint32_t pid, int ext, int i)
+static always_inline int ppcemb_tlb_check (CPUState *env, ppcemb_tlb_t *tlb,
+                                           target_phys_addr_t *raddrp,
+                                           target_ulong address,
+                                           uint32_t pid, int ext, int i)
 {
     target_ulong mask;
 
@@ -834,11 +1082,13 @@
         return -1;
     }
     mask = ~(tlb->size - 1);
+#if defined (DEBUG_SOFTWARE_TLB)
     if (loglevel != 0) {
         fprintf(logfile, "%s: TLB %d address " ADDRX " PID %d <=> "
                 ADDRX " " ADDRX " %d\n",
                 __func__, i, address, pid, tlb->EPN, mask, (int)tlb->PID);
     }
+#endif
     /* Check PID */
     if (tlb->PID != 0 && tlb->PID != pid)
         return -1;
@@ -846,10 +1096,12 @@
     if ((address & mask) != tlb->EPN)
         return -1;
     *raddrp = (tlb->RPN & mask) | (address & ~mask);
+#if (TARGET_PHYS_ADDR_BITS >= 36)
     if (ext) {
         /* Extend the physical address to 36 bits */
         *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
     }
+#endif
 
     return 0;
 }
@@ -863,7 +1115,7 @@
 
     /* Default return value is no match */
     ret = -1;
-    for (i = 0; i < 64; i++) {
+    for (i = 0; i < env->nb_tlb; i++) {
         tlb = &env->tlb[i].tlbe;
         if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
             ret = i;
@@ -875,23 +1127,41 @@
 }
 
 /* Helpers specific to PowerPC 40x implementations */
-void ppc4xx_tlb_invalidate_all (CPUState *env)
+static always_inline 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.
+        tlb->prot &= ~PAGE_VALID;
+    }
+    tlb_flush(env, 1);
+}
+
+static always_inline void ppc4xx_tlb_invalidate_virt (CPUState *env,
+                                                      target_ulong eaddr,
+                                                      uint32_t pid)
+{
+#if !defined(FLUSH_ALL_TLBS)
+    ppcemb_tlb_t *tlb;
+    target_phys_addr_t raddr;
+    target_ulong page, end;
+    int i;
+
+    for (i = 0; i < env->nb_tlb; i++) {
+        tlb = &env->tlb[i].tlbe;
+        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
             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;
+            break;
         }
     }
-    tlb_flush(env, 1);
+#else
+    ppc4xx_tlb_invalidate_all(env);
+#endif
 }
 
 int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
@@ -899,10 +1169,11 @@
 {
     ppcemb_tlb_t *tlb;
     target_phys_addr_t raddr;
-    int i, ret, zsel, zpr;
+    int i, ret, zsel, zpr, pr;
 
     ret = -1;
     raddr = -1;
+    pr = msr_pr;
     for (i = 0; i < env->nb_tlb; i++) {
         tlb = &env->tlb[i].tlbe;
         if (ppcemb_tlb_check(env, tlb, &raddr, address,
@@ -910,96 +1181,58 @@
             continue;
         zsel = (tlb->attr >> 4) & 0xF;
         zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
+#if defined (DEBUG_SOFTWARE_TLB)
         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;
-                }
+#endif
+        /* Check execute enable bit */
+        switch (zpr) {
+        case 0x2:
+            if (pr != 0)
+                goto check_perms;
+            /* No break here */
+        case 0x3:
+            /* All accesses granted */
+            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+            ret = 0;
+            break;
+        case 0x0:
+            if (pr != 0) {
+                ctx->prot = 0;
+                ret = -2;
                 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;
-            }
+            /* No break here */
+        case 0x1:
+        check_perms:
+            /* Check from TLB entry */
+            /* XXX: there is a problem here or in the TLB fill code... */
+            ctx->prot = tlb->prot;
+            ctx->prot |= PAGE_EXEC;
+            ret = check_prot(ctx->prot, rw, access_type);
+            break;
         }
         if (ret >= 0) {
             ctx->raddr = raddr;
+#if defined (DEBUG_SOFTWARE_TLB)
             if (loglevel != 0) {
                 fprintf(logfile, "%s: access granted " ADDRX " => " REGX
                         " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
                         ret);
             }
+#endif
             return 0;
         }
     }
+#if defined (DEBUG_SOFTWARE_TLB)
     if (loglevel != 0) {
         fprintf(logfile, "%s: access refused " ADDRX " => " REGX
                 " %d %d\n", __func__, address, raddr, ctx->prot,
                 ret);
     }
+#endif
 
     return ret;
 }
@@ -1028,13 +1261,13 @@
         if (ppcemb_tlb_check(env, tlb, &raddr, address,
                              env->spr[SPR_BOOKE_PID], 1, i) < 0)
             continue;
-        if (msr_pr)
+        if (msr_pr != 0)
             prot = tlb->prot & 0xF;
         else
             prot = (tlb->prot >> 4) & 0xF;
         /* Check the address space */
         if (access_type == ACCESS_CODE) {
-            if (msr_is != (tlb->attr & 1))
+            if (msr_ir != (tlb->attr & 1))
                 continue;
             ctx->prot = prot;
             if (prot & PAGE_EXEC) {
@@ -1043,7 +1276,7 @@
             }
             ret = -3;
         } else {
-            if (msr_ds != (tlb->attr & 1))
+            if (msr_dr != (tlb->attr & 1))
                 continue;
             ctx->prot = prot;
             if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
@@ -1059,30 +1292,31 @@
     return ret;
 }
 
-static int check_physical (CPUState *env, mmu_ctx_t *ctx,
-                           target_ulong eaddr, int rw)
+static always_inline 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;
+    ctx->prot = PAGE_READ | PAGE_EXEC;
     ret = 0;
-    switch (PPC_MMU(env)) {
-    case PPC_FLAGS_MMU_32B:
-    case PPC_FLAGS_MMU_SOFT_6xx:
-    case PPC_FLAGS_MMU_601:
-    case PPC_FLAGS_MMU_SOFT_4xx:
+    switch (env->mmu_model) {
+    case POWERPC_MMU_32B:
+    case POWERPC_MMU_SOFT_6xx:
+    case POWERPC_MMU_SOFT_74xx:
+    case POWERPC_MMU_SOFT_4xx:
+    case POWERPC_MMU_REAL_4xx:
+    case POWERPC_MMU_BOOKE:
         ctx->prot |= PAGE_WRITE;
         break;
 #if defined(TARGET_PPC64)
-    case PPC_FLAGS_MMU_64B:
-    case PPC_FLAGS_MMU_64BRIDGE:
-#endif
+    case POWERPC_MMU_64B:
         /* Real address are 60 bits long */
-        ctx->raddr &= 0x0FFFFFFFFFFFFFFFUL;
+        ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
         ctx->prot |= PAGE_WRITE;
         break;
-    case PPC_FLAGS_MMU_403:
+#endif
+    case POWERPC_MMU_SOFT_4xx_Z:
         if (unlikely(msr_pe != 0)) {
             /* 403 family add some particular protections,
              * using PBL/PBU registers for accesses with no translation.
@@ -1105,10 +1339,8 @@
                 ctx->prot |= PAGE_WRITE;
             }
         }
-    case PPC_FLAGS_MMU_BOOKE:
-        ctx->prot |= PAGE_WRITE;
         break;
-    case PPC_FLAGS_MMU_BOOKE_FSL:
+    case POWERPC_MMU_BOOKE_FSL:
         /* XXX: TODO */
         cpu_abort(env, "BookE FSL MMU model not implemented\n");
         break;
@@ -1124,6 +1356,7 @@
                           int rw, int access_type, int check_BATs)
 {
     int ret;
+
 #if 0
     if (loglevel != 0) {
         fprintf(logfile, "%s\n", __func__);
@@ -1135,39 +1368,38 @@
         ret = check_physical(env, ctx, eaddr, rw);
     } else {
         ret = -1;
-        switch (PPC_MMU(env)) {
-        case PPC_FLAGS_MMU_32B:
-        case PPC_FLAGS_MMU_SOFT_6xx:
+        switch (env->mmu_model) {
+        case POWERPC_MMU_32B:
+        case POWERPC_MMU_SOFT_6xx:
+        case POWERPC_MMU_SOFT_74xx:
             /* 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:
+        case POWERPC_MMU_64B:
 #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:
+        case POWERPC_MMU_SOFT_4xx:
+        case POWERPC_MMU_SOFT_4xx_Z:
             ret = mmu40x_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:
+        case POWERPC_MMU_BOOKE:
             ret = mmubooke_get_physical_address(env, ctx, eaddr,
                                                 rw, access_type);
             break;
-        case PPC_FLAGS_MMU_BOOKE_FSL:
+        case POWERPC_MMU_BOOKE_FSL:
             /* XXX: TODO */
             cpu_abort(env, "BookE FSL MMU model not implemented\n");
             return -1;
+        case POWERPC_MMU_REAL_4xx:
+            cpu_abort(env, "PowerPC 401 does not do any translation\n");
+            return -1;
         default:
             cpu_abort(env, "Unknown or invalid MMU model\n");
             return -1;
@@ -1195,10 +1427,9 @@
 
 /* Perform address translation */
 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                              int is_user, int is_softmmu)
+                              int mmu_idx, int is_softmmu)
 {
     mmu_ctx_t ctx;
-    int exception = 0, error_code = 0;
     int access_type;
     int ret = 0;
 
@@ -1215,57 +1446,53 @@
     }
     ret = get_physical_address(env, &ctx, address, rw, access_type, 1);
     if (ret == 0) {
-        ret = tlb_set_page(env, address & TARGET_PAGE_MASK,
-                           ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
-                           is_user, is_softmmu);
+        ret = tlb_set_page_exec(env, address & TARGET_PAGE_MASK,
+                                ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
+                                mmu_idx, is_softmmu);
     } else if (ret < 0) {
 #if defined (DEBUG_MMU)
         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 or TLB */
-                switch (PPC_MMU(env)) {
-                case PPC_FLAGS_MMU_SOFT_6xx:
-                    exception = EXCP_I_TLBMISS;
+                switch (env->mmu_model) {
+                case POWERPC_MMU_SOFT_6xx:
+                    env->exception_index = POWERPC_EXCP_IFTLB;
+                    env->error_code = 1 << 18;
                     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;
+                case POWERPC_MMU_SOFT_74xx:
+                    env->exception_index = POWERPC_EXCP_IFTLB;
+                    goto tlb_miss_74xx;
+                case POWERPC_MMU_SOFT_4xx:
+                case POWERPC_MMU_SOFT_4xx_Z:
+                    env->exception_index = POWERPC_EXCP_ITLB;
+                    env->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;
+                case POWERPC_MMU_32B:
 #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;
+                case POWERPC_MMU_64B:
 #endif
-                case PPC_FLAGS_MMU_601:
+                    env->exception_index = POWERPC_EXCP_ISI;
+                    env->error_code = 0x40000000;
+                    break;
+                case POWERPC_MMU_BOOKE:
                     /* XXX: TODO */
                     cpu_abort(env, "MMU model not implemented\n");
                     return -1;
-                case PPC_FLAGS_MMU_BOOKE:
+                case POWERPC_MMU_BOOKE_FSL:
                     /* 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");
+                case POWERPC_MMU_REAL_4xx:
+                    cpu_abort(env, "PowerPC 401 should never raise any MMU "
+                              "exceptions\n");
                     return -1;
                 default:
                     cpu_abort(env, "Unknown or invalid MMU model\n");
@@ -1274,79 +1501,94 @@
                 break;
             case -2:
                 /* Access rights violation */
-                error_code = 0x08000000;
+                env->exception_index = POWERPC_EXCP_ISI;
+                env->error_code = 0x08000000;
                 break;
             case -3:
                 /* No execute protection violation */
-                error_code = 0x10000000;
+                env->exception_index = POWERPC_EXCP_ISI;
+                env->error_code = 0x10000000;
                 break;
             case -4:
                 /* Direct store exception */
                 /* No code fetch is allowed in direct-store areas */
-                error_code = 0x10000000;
+                env->exception_index = POWERPC_EXCP_ISI;
+                env->error_code = 0x10000000;
                 break;
+#if defined(TARGET_PPC64)
             case -5:
                 /* No match in segment table */
-                exception = EXCP_ISEG;
-                error_code = 0;
+                env->exception_index = POWERPC_EXCP_ISEG;
+                env->error_code = 0;
                 break;
+#endif
             }
         } else {
-            exception = EXCP_DSI;
             switch (ret) {
             case -1:
                 /* No matches in page tables or TLB */
-                switch (PPC_MMU(env)) {
-                case PPC_FLAGS_MMU_SOFT_6xx:
+                switch (env->mmu_model) {
+                case POWERPC_MMU_SOFT_6xx:
                     if (rw == 1) {
-                        exception = EXCP_DS_TLBMISS;
-                        error_code = 1 << 16;
+                        env->exception_index = POWERPC_EXCP_DSTLB;
+                        env->error_code = 1 << 16;
                     } else {
-                        exception = EXCP_DL_TLBMISS;
-                        error_code = 0;
+                        env->exception_index = POWERPC_EXCP_DLTLB;
+                        env->error_code = 0;
                     }
                     env->spr[SPR_DMISS] = address;
                     env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
                 tlb_miss:
-                    error_code |= ctx.key << 19;
+                    env->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;
+                    break;
+                case POWERPC_MMU_SOFT_74xx:
+                    if (rw == 1) {
+                        env->exception_index = POWERPC_EXCP_DSTLB;
+                    } else {
+                        env->exception_index = POWERPC_EXCP_DLTLB;
+                    }
+                tlb_miss_74xx:
+                    /* Implement LRU algorithm */
+                    env->error_code = ctx.key << 19;
+                    env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
+                        ((env->last_way + 1) & (env->nb_ways - 1));
+                    env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
+                    break;
+                case POWERPC_MMU_SOFT_4xx:
+                case POWERPC_MMU_SOFT_4xx_Z:
+                    env->exception_index = POWERPC_EXCP_DTLB;
+                    env->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;
+                case POWERPC_MMU_32B:
 #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;
+                case POWERPC_MMU_64B:
 #endif
-                case PPC_FLAGS_MMU_601:
+                    env->exception_index = POWERPC_EXCP_DSI;
+                    env->error_code = 0;
+                    env->spr[SPR_DAR] = address;
+                    if (rw == 1)
+                        env->spr[SPR_DSISR] = 0x42000000;
+                    else
+                        env->spr[SPR_DSISR] = 0x40000000;
+                    break;
+                case POWERPC_MMU_BOOKE:
                     /* XXX: TODO */
                     cpu_abort(env, "MMU model not implemented\n");
                     return -1;
-                case PPC_FLAGS_MMU_BOOKE:
+                case POWERPC_MMU_BOOKE_FSL:
                     /* 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");
+                case POWERPC_MMU_REAL_4xx:
+                    cpu_abort(env, "PowerPC 401 should never raise any MMU "
+                              "exceptions\n");
                     return -1;
                 default:
                     cpu_abort(env, "Unknown or invalid MMU model\n");
@@ -1355,50 +1597,66 @@
                 break;
             case -2:
                 /* Access rights violation */
-                error_code = 0x08000000;
+                env->exception_index = POWERPC_EXCP_DSI;
+                env->error_code = 0;
+                env->spr[SPR_DAR] = address;
+                if (rw == 1)
+                    env->spr[SPR_DSISR] = 0x0A000000;
+                else
+                    env->spr[SPR_DSISR] = 0x08000000;
                 break;
             case -4:
                 /* Direct store exception */
                 switch (access_type) {
                 case ACCESS_FLOAT:
                     /* Floating point load/store */
-                    exception = EXCP_ALIGN;
-                    error_code = EXCP_ALIGN_FP;
+                    env->exception_index = POWERPC_EXCP_ALIGN;
+                    env->error_code = POWERPC_EXCP_ALIGN_FP;
+                    env->spr[SPR_DAR] = address;
                     break;
                 case ACCESS_RES:
-                    /* lwarx, ldarx or srwcx. */
-                    error_code = 0x04000000;
+                    /* lwarx, ldarx or stwcx. */
+                    env->exception_index = POWERPC_EXCP_DSI;
+                    env->error_code = 0;
+                    env->spr[SPR_DAR] = address;
+                    if (rw == 1)
+                        env->spr[SPR_DSISR] = 0x06000000;
+                    else
+                        env->spr[SPR_DSISR] = 0x04000000;
                     break;
                 case ACCESS_EXT:
                     /* eciwx or ecowx */
-                    error_code = 0x04100000;
+                    env->exception_index = POWERPC_EXCP_DSI;
+                    env->error_code = 0;
+                    env->spr[SPR_DAR] = address;
+                    if (rw == 1)
+                        env->spr[SPR_DSISR] = 0x06100000;
+                    else
+                        env->spr[SPR_DSISR] = 0x04100000;
                     break;
                 default:
                     printf("DSI: invalid exception (%d)\n", ret);
-                    exception = EXCP_PROGRAM;
-                    error_code = EXCP_INVAL | EXCP_INVAL_INVAL;
+                    env->exception_index = POWERPC_EXCP_PROGRAM;
+                    env->error_code =
+                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
+                    env->spr[SPR_DAR] = address;
                     break;
                 }
                 break;
+#if defined(TARGET_PPC64)
             case -5:
                 /* No match in segment table */
-                exception = EXCP_DSEG;
-                error_code = 0;
+                env->exception_index = POWERPC_EXCP_DSEG;
+                env->error_code = 0;
+                env->spr[SPR_DAR] = address;
                 break;
+#endif
             }
-            if (exception == EXCP_DSI && rw == 1)
-                error_code |= 0x02000000;
-            /* 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);
+        printf("%s: set exception to %d %02x\n", __func__,
+               env->exception, env->error_code);
 #endif
-        env->exception_index = exception;
-        env->error_code = error_code;
         ret = 1;
     }
 
@@ -1408,8 +1666,9 @@
 /*****************************************************************************/
 /* BATs management */
 #if !defined(FLUSH_ALL_TLBS)
-static inline void do_invalidate_BAT (CPUPPCState *env,
-                                      target_ulong BATu, target_ulong mask)
+static always_inline void do_invalidate_BAT (CPUPPCState *env,
+                                             target_ulong BATu,
+                                             target_ulong mask)
 {
     target_ulong base, end, page;
 
@@ -1430,8 +1689,8 @@
 }
 #endif
 
-static inline void dump_store_bat (CPUPPCState *env, char ID, int ul, int nr,
-                                   target_ulong value)
+static always_inline void dump_store_bat (CPUPPCState *env, char ID,
+                                          int ul, int nr, target_ulong value)
 {
 #if defined (DEBUG_BATS)
     if (loglevel != 0) {
@@ -1525,20 +1784,112 @@
     env->DBAT[1][nr] = value;
 }
 
-
 /*****************************************************************************/
 /* TLB management */
 void ppc_tlb_invalidate_all (CPUPPCState *env)
 {
-    if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
+    switch (env->mmu_model) {
+    case POWERPC_MMU_SOFT_6xx:
+    case POWERPC_MMU_SOFT_74xx:
         ppc6xx_tlb_invalidate_all(env);
-    } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
+        break;
+    case POWERPC_MMU_SOFT_4xx:
+    case POWERPC_MMU_SOFT_4xx_Z:
         ppc4xx_tlb_invalidate_all(env);
-    } else {
+        break;
+    case POWERPC_MMU_REAL_4xx:
+        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
+        break;
+    case POWERPC_MMU_BOOKE:
+        /* XXX: TODO */
+        cpu_abort(env, "MMU model not implemented\n");
+        break;
+    case POWERPC_MMU_BOOKE_FSL:
+        /* XXX: TODO */
+        cpu_abort(env, "MMU model not implemented\n");
+        break;
+    case POWERPC_MMU_32B:
+#if defined(TARGET_PPC64)
+    case POWERPC_MMU_64B:
+#endif /* defined(TARGET_PPC64) */
         tlb_flush(env, 1);
+        break;
+    default:
+        /* XXX: TODO */
+        cpu_abort(env, "Unknown MMU model\n");
+        break;
     }
 }
 
+void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
+{
+#if !defined(FLUSH_ALL_TLBS)
+    addr &= TARGET_PAGE_MASK;
+    switch (env->mmu_model) {
+    case POWERPC_MMU_SOFT_6xx:
+    case POWERPC_MMU_SOFT_74xx:
+        ppc6xx_tlb_invalidate_virt(env, addr, 0);
+        if (env->id_tlbs == 1)
+            ppc6xx_tlb_invalidate_virt(env, addr, 1);
+        break;
+    case POWERPC_MMU_SOFT_4xx:
+    case POWERPC_MMU_SOFT_4xx_Z:
+        ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
+        break;
+    case POWERPC_MMU_REAL_4xx:
+        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
+        break;
+    case POWERPC_MMU_BOOKE:
+        /* XXX: TODO */
+        cpu_abort(env, "MMU model not implemented\n");
+        break;
+    case POWERPC_MMU_BOOKE_FSL:
+        /* XXX: TODO */
+        cpu_abort(env, "MMU model not implemented\n");
+        break;
+    case POWERPC_MMU_32B:
+        /* tlbie invalidate TLBs for all segments */
+        addr &= ~((target_ulong)-1 << 28);
+        /* XXX: this case should be optimized,
+         * giving a mask to tlb_flush_page
+         */
+        tlb_flush_page(env, addr | (0x0 << 28));
+        tlb_flush_page(env, addr | (0x1 << 28));
+        tlb_flush_page(env, addr | (0x2 << 28));
+        tlb_flush_page(env, addr | (0x3 << 28));
+        tlb_flush_page(env, addr | (0x4 << 28));
+        tlb_flush_page(env, addr | (0x5 << 28));
+        tlb_flush_page(env, addr | (0x6 << 28));
+        tlb_flush_page(env, addr | (0x7 << 28));
+        tlb_flush_page(env, addr | (0x8 << 28));
+        tlb_flush_page(env, addr | (0x9 << 28));
+        tlb_flush_page(env, addr | (0xA << 28));
+        tlb_flush_page(env, addr | (0xB << 28));
+        tlb_flush_page(env, addr | (0xC << 28));
+        tlb_flush_page(env, addr | (0xD << 28));
+        tlb_flush_page(env, addr | (0xE << 28));
+        tlb_flush_page(env, addr | (0xF << 28));
+        break;
+#if defined(TARGET_PPC64)
+    case POWERPC_MMU_64B:
+        /* tlbie invalidate TLBs for all segments */
+        /* XXX: given the fact that there are too many segments to invalidate,
+         *      and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
+         *      we just invalidate all TLBs
+         */
+        tlb_flush(env, 1);
+        break;
+#endif /* defined(TARGET_PPC64) */
+    default:
+        /* XXX: TODO */
+        cpu_abort(env, "Unknown MMU model\n");
+        break;
+    }
+#else
+    ppc_tlb_invalidate_all(env);
+#endif
+}
+
 /*****************************************************************************/
 /* Special registers manipulation */
 #if defined(TARGET_PPC64)
@@ -1569,15 +1920,20 @@
     }
 #endif
     if (env->sdr1 != value) {
+        /* XXX: for PowerPC 64, should check that the HTABSIZE value
+         *      is <= 28
+         */
         env->sdr1 = value;
         tlb_flush(env, 1);
     }
 }
 
+#if 0 // Unused
 target_ulong do_load_sr (CPUPPCState *env, int srnum)
 {
     return env->sr[srnum];
 }
+#endif
 
 void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
 {
@@ -1605,201 +1961,38 @@
 }
 #endif /* !defined (CONFIG_USER_ONLY) */
 
-uint32_t ppc_load_xer (CPUPPCState *env)
+target_ulong ppc_load_xer (CPUPPCState *env)
 {
-    return (xer_so << XER_SO) |
-        (xer_ov << XER_OV) |
-        (xer_ca << XER_CA) |
-        (xer_bc << XER_BC) |
-        (xer_cmp << XER_CMP);
+    return hreg_load_xer(env);
 }
 
-void ppc_store_xer (CPUPPCState *env, uint32_t value)
+void ppc_store_xer (CPUPPCState *env, target_ulong 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) & 0x7F;
+    hreg_store_xer(env, value);
 }
 
-/* Swap temporary saved registers with GPRs */
-static inline void swap_gpr_tgpr (CPUPPCState *env)
-{
-    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;
-}
-
 /* GDBstub can read and write MSR... */
-target_ulong do_load_msr (CPUPPCState *env)
+void ppc_store_msr (CPUPPCState *env, target_ulong value)
 {
-    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);
+    hreg_store_msr(env, value);
 }
 
-void do_store_msr (CPUPPCState *env, target_ulong value)
-{
-    int enter_pm;
-
-    value &= env->msr_mask;
-    if (((value >> MSR_IR) & 1) != msr_ir ||
-        ((value >> MSR_DR) & 1) != msr_dr) {
-        /* Flush all tlb when changing translation mode */
-        tlb_flush(env, 1);
-        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
-    }
-#if 0
-    if (loglevel != 0) {
-        fprintf(logfile, "%s: T0 %08lx\n", __func__, value);
-    }
-#endif
-    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)
-            enter_pm = 1;
-        break;
-    default:
-        break;
-    }
-    if (enter_pm) {
-        if (likely(!env->halted)) {
-            /* power save: exit cpu loop */
-            env->halted = 1;
-            env->exception_index = EXCP_HLT;
-            cpu_loop_exit();
-        }
-    }
-}
-
-#if defined(TARGET_PPC64)
-void ppc_store_msr_32 (CPUPPCState *env, uint32_t value)
-{
-    do_store_msr(env,
-                 (do_load_msr(env) & ~0xFFFFFFFFULL) | (value & 0xFFFFFFFF));
-}
-#endif
-
-void do_compute_hflags (CPUPPCState *env)
-{
-    /* 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
-}
-
 /*****************************************************************************/
 /* Exception processing */
 #if defined (CONFIG_USER_ONLY)
 void do_interrupt (CPUState *env)
 {
-    env->exception_index = -1;
+    env->exception_index = POWERPC_EXCP_NONE;
+    env->error_code = 0;
 }
 
 void ppc_hw_interrupt (CPUState *env)
 {
-    env->exception_index = -1;
+    env->exception_index = POWERPC_EXCP_NONE;
+    env->error_code = 0;
 }
 #else /* defined (CONFIG_USER_ONLY) */
-static void dump_syscall (CPUState *env)
+static always_inline void dump_syscall (CPUState *env)
 {
     fprintf(logfile, "syscall r0=0x" REGX " r3=0x" REGX " r4=0x" REGX
             " r5=0x" REGX " r6=0x" REGX " nip=0x" ADDRX "\n",
@@ -1807,346 +2000,474 @@
             env->gpr[5], env->gpr[6], env->nip);
 }
 
-void do_interrupt (CPUState *env)
+/* Note that this function should be greatly optimized
+ * when called with a constant excp, from ppc_hw_interrupt
+ */
+static always_inline void powerpc_excp (CPUState *env,
+                                        int excp_model, int excp)
 {
-    target_ulong msr, *srr_0, *srr_1, *asrr_0, *asrr_1;
-    int excp, idx;
+    target_ulong msr, new_msr, vector;
+    int srr0, srr1, asrr0, asrr1;
+#if defined(TARGET_PPC64H)
+    int lpes0, lpes1, lev;
 
-    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" ADDRX " => 0x%08x (%02x)\n",
-                    env->nip, excp, env->error_code);
-            cpu_dump_state(env, logfile, fprintf, 0);
-        }
-    }
+    lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
+    lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
 #endif
+
     if (loglevel & CPU_LOG_INT) {
         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 */
+    msr = env->msr;
+    new_msr = msr;
+    srr0 = SPR_SRR0;
+    srr1 = SPR_SRR1;
+    asrr0 = -1;
+    asrr1 = -1;
+    msr &= ~((target_ulong)0x783F0000);
     switch (excp) {
-    /* Generic PowerPC exceptions */
-    case EXCP_RESET: /* 0x0100 */
-        switch (PPC_EXCP(env)) {
-        case PPC_FLAGS_EXCP_40x:
-            srr_0 = &env->spr[SPR_40x_SRR2];
-            srr_1 = &env->spr[SPR_40x_SRR3];
+    case POWERPC_EXCP_NONE:
+        /* Should never happen */
+        return;
+    case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
+        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
+        switch (excp_model) {
+        case POWERPC_EXCP_40x:
+            srr0 = SPR_40x_SRR2;
+            srr1 = 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];
+        case POWERPC_EXCP_BOOKE:
+            srr0 = SPR_BOOKE_CSRR0;
+            srr1 = SPR_BOOKE_CSRR1;
             break;
+        case POWERPC_EXCP_G2:
+            break;
         default:
-            if (msr_ip)
-                excp += 0xFFC00;
-            excp |= 0xFFC00000;
-            break;
+            goto excp_invalid;
         }
         goto store_next;
-    case EXCP_MACHINE_CHECK: /* 0x0200 */
-        switch (PPC_EXCP(env)) {
-        case PPC_FLAGS_EXCP_40x:
-            srr_0 = &env->spr[SPR_40x_SRR2];
-            srr_1 = &env->spr[SPR_40x_SRR3];
+    case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
+        if (msr_me == 0) {
+            /* Machine check exception is not enabled.
+             * Enter checkstop state.
+             */
+            if (loglevel != 0) {
+                fprintf(logfile, "Machine check while not allowed. "
+                        "Entering checkstop state\n");
+            } else {
+                fprintf(stderr, "Machine check while not allowed. "
+                        "Entering checkstop state\n");
+            }
+            env->halted = 1;
+            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+        }
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+        new_msr &= ~((target_ulong)1 << MSR_ME);
+#if defined(TARGET_PPC64H)
+        new_msr |= (target_ulong)1 << MSR_HV;
+#endif
+        /* XXX: should also have something loaded in DAR / DSISR */
+        switch (excp_model) {
+        case POWERPC_EXCP_40x:
+            srr0 = SPR_40x_SRR2;
+            srr1 = 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;
+        case POWERPC_EXCP_BOOKE:
+            srr0 = SPR_BOOKE_MCSRR0;
+            srr1 = SPR_BOOKE_MCSRR1;
+            asrr0 = SPR_BOOKE_CSRR0;
+            asrr1 = SPR_BOOKE_CSRR1;
             break;
         default:
             break;
         }
-        msr_me = 0;
-        break;
-    case EXCP_DSI: /* 0x0300 */
-        /* Store exception cause */
-        /* data location address has been stored
-         * when the fault has been detected
-         */
-        idx = 2;
-        msr &= ~0xFFFF0000;
+        goto store_next;
+    case POWERPC_EXCP_DSI:       /* Data storage exception                   */
 #if defined (DEBUG_EXCEPTIONS)
         if (loglevel != 0) {
             fprintf(logfile, "DSI exception: DSISR=0x" ADDRX" DAR=0x" ADDRX
                     "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
         }
 #endif
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            new_msr |= (target_ulong)1 << MSR_HV;
+#endif
         goto store_next;
-    case EXCP_ISI: /* 0x0400 */
-        /* Store exception cause */
-        idx = 3;
-        msr &= ~0xFFFF0000;
-        msr |= env->error_code;
+    case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
 #if defined (DEBUG_EXCEPTIONS)
         if (loglevel != 0) {
             fprintf(logfile, "ISI exception: msr=0x" ADDRX ", nip=0x" ADDRX
                     "\n", msr, env->nip);
         }
 #endif
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            new_msr |= (target_ulong)1 << MSR_HV;
+#endif
+        msr |= env->error_code;
         goto store_next;
-    case EXCP_EXTERNAL: /* 0x0500 */
-        idx = 4;
+    case POWERPC_EXCP_EXTERNAL:  /* External input                           */
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+        if (lpes0 == 1)
+            new_msr |= (target_ulong)1 << MSR_HV;
+#endif
         goto store_next;
-    case EXCP_ALIGN: /* 0x0600 */
-        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;
-            /* data location address has been stored
-             * when the fault has been detected
-             */
-        } else {
-            /* IO error exception on PowerPC 601 */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "601 IO error exception is not implemented yet !\n");
-        }
+    case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            new_msr |= (target_ulong)1 << MSR_HV;
+#endif
+        /* XXX: this is false */
+        /* Get rS/rD and rA from faulting opcode */
+        env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
         goto store_current;
-    case EXCP_PROGRAM: /* 0x0700 */
-        idx = 6;
-        msr &= ~0xFFFF0000;
+    case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
         switch (env->error_code & ~0xF) {
-        case EXCP_FP:
-            if (msr_fe0 == 0 && msr_fe1 == 0) {
+        case POWERPC_EXCP_FP:
+            if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
 #if defined (DEBUG_EXCEPTIONS)
                 if (loglevel != 0) {
                     fprintf(logfile, "Ignore floating point exception\n");
                 }
 #endif
+                env->exception_index = POWERPC_EXCP_NONE;
+                env->error_code = 0;
                 return;
             }
+            new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+            if (lpes1 == 0)
+                new_msr |= (target_ulong)1 << MSR_HV;
+#endif
             msr |= 0x00100000;
-            /* 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;
+            if (msr_fe0 != msr_fe1) {
+                msr |= 0x00010000;
+                goto store_current;
+            }
             break;
-        case EXCP_INVAL:
+        case POWERPC_EXCP_INVAL:
 #if defined (DEBUG_EXCEPTIONS)
             if (loglevel != 0) {
                 fprintf(logfile, "Invalid instruction at 0x" ADDRX "\n",
                         env->nip);
             }
 #endif
+            new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+            if (lpes1 == 0)
+                new_msr |= (target_ulong)1 << MSR_HV;
+#endif
             msr |= 0x00080000;
             break;
-        case EXCP_PRIV:
+        case POWERPC_EXCP_PRIV:
+            new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+            if (lpes1 == 0)
+                new_msr |= (target_ulong)1 << MSR_HV;
+#endif
             msr |= 0x00040000;
             break;
-        case EXCP_TRAP:
-            idx = 15;
+        case POWERPC_EXCP_TRAP:
+            new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+            if (lpes1 == 0)
+                new_msr |= (target_ulong)1 << MSR_HV;
+#endif
             msr |= 0x00020000;
             break;
         default:
             /* Should never occur */
+            cpu_abort(env, "Invalid program exception %d. Aborting\n",
+                      env->error_code);
             break;
         }
-        msr |= 0x00010000;
+        goto store_next;
+    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            new_msr |= (target_ulong)1 << MSR_HV;
+#endif
         goto store_current;
-    case EXCP_NO_FP: /* 0x0800 */
-        idx = 7;
-        msr &= ~0xFFFF0000;
-        goto store_current;
-    case EXCP_DECR:
-        goto store_next;
-    case EXCP_SYSCALL: /* 0x0C00 */
-        idx = 8;
+    case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
         /* NOTE: this is a temporary hack to support graphics OSI
            calls from the MOL driver */
+        /* XXX: To be removed */
         if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
             env->osi_call) {
-            if (env->osi_call(env) != 0)
+            if (env->osi_call(env) != 0) {
+                env->exception_index = POWERPC_EXCP_NONE;
+                env->error_code = 0;
                 return;
+            }
         }
         if (loglevel & CPU_LOG_INT) {
             dump_syscall(env);
         }
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+        lev = env->error_code;
+        if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
+            new_msr |= (target_ulong)1 << MSR_HV;
+#endif
         goto store_next;
-    case EXCP_TRACE: /* 0x0D00 */
+    case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+        goto store_current;
+    case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            new_msr |= (target_ulong)1 << MSR_HV;
+#endif
         goto store_next;
-    case EXCP_PERF: /* 0x0F00 */
+    case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
+        /* FIT on 4xx */
+#if defined (DEBUG_EXCEPTIONS)
+        if (loglevel != 0)
+            fprintf(logfile, "FIT exception\n");
+#endif
+        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
+        goto store_next;
+    case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
+#if defined (DEBUG_EXCEPTIONS)
+        if (loglevel != 0)
+            fprintf(logfile, "WDT exception\n");
+#endif
+        switch (excp_model) {
+        case POWERPC_EXCP_BOOKE:
+            srr0 = SPR_BOOKE_CSRR0;
+            srr1 = SPR_BOOKE_CSRR1;
+            break;
+        default:
+            break;
+        }
+        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
+        goto store_next;
+    case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
+        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
+        goto store_next;
+    case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
+        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
+        goto store_next;
+    case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
+        switch (excp_model) {
+        case POWERPC_EXCP_BOOKE:
+            srr0 = SPR_BOOKE_DSRR0;
+            srr1 = SPR_BOOKE_DSRR1;
+            asrr0 = SPR_BOOKE_CSRR0;
+            asrr1 = SPR_BOOKE_CSRR1;
+            break;
+        default:
+            break;
+        }
         /* XXX: TODO */
-        cpu_abort(env,
-                  "Performance counter exception is not implemented yet !\n");
+        cpu_abort(env, "Debug exception is not implemented yet !\n");
         goto store_next;
-    /* 32 bits PowerPC specific exceptions */
-    case EXCP_FP_ASSIST: /* 0x0E00 */
+#if defined(TARGET_PPCEMB)
+    case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
+        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
+        goto store_current;
+    case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
         /* XXX: TODO */
-        cpu_abort(env, "Floating point assist exception "
+        cpu_abort(env, "Embedded floating point data exception "
                   "is not implemented yet !\n");
         goto store_next;
-    /* 64 bits PowerPC exceptions */
-    case EXCP_DSEG: /* 0x0380 */
+    case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
         /* XXX: TODO */
-        cpu_abort(env, "Data segment exception is not implemented yet !\n");
+        cpu_abort(env, "Embedded floating point round exception "
+                  "is not implemented yet !\n");
         goto store_next;
-    case EXCP_ISEG: /* 0x0480 */
+    case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
+        new_msr &= ~((target_ulong)1 << MSR_RI);
         /* XXX: TODO */
         cpu_abort(env,
-                  "Instruction segment exception is not implemented yet !\n");
+                  "Performance counter exception is not implemented yet !\n");
         goto store_next;
-    case EXCP_HDECR: /* 0x0980 */
+    case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
         /* XXX: TODO */
-        cpu_abort(env, "Hypervisor decrementer exception is not implemented "
-                  "yet !\n");
+        cpu_abort(env,
+                  "Embedded doorbell interrupt is not implemented yet !\n");
         goto store_next;
-    /* Implementation specific exceptions */
-    case 0x0A00:
-        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");
-            goto store_next;
-        } else {
-            cpu_abort(env, "Invalid exception 0x0A00 !\n");
-        }
-        return;
-    case 0x0F20:
-        idx = 9;
-        switch (PPC_EXCP(env)) {
-        case PPC_FLAGS_EXCP_40x:
-            /* APU unavailable on 405 */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "APU unavailable exception is not implemented yet !\n");
-            goto store_next;
-        case PPC_FLAGS_EXCP_74xx:
-            /* Altivec unavailable */
-            /* XXX: TODO */
-            cpu_abort(env, "Altivec unavailable exception "
-                      "is not implemented yet !\n");
-            goto store_next;
+    case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
+        switch (excp_model) {
+        case POWERPC_EXCP_BOOKE:
+            srr0 = SPR_BOOKE_CSRR0;
+            srr1 = SPR_BOOKE_CSRR1;
+            break;
         default:
-            cpu_abort(env, "Invalid exception 0x0F20 !\n");
             break;
         }
-        return;
-    case 0x1000:
-        idx = 10;
-        switch (PPC_EXCP(env)) {
-        case PPC_FLAGS_EXCP_40x:
-            /* PIT on 4xx */
-            msr &= ~0xFFFF0000;
+        /* XXX: TODO */
+        cpu_abort(env, "Embedded doorbell critical interrupt "
+                  "is not implemented yet !\n");
+        goto store_next;
+#endif /* defined(TARGET_PPCEMB) */
+    case POWERPC_EXCP_RESET:     /* System reset exception                   */
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+        new_msr |= (target_ulong)1 << MSR_HV;
+#endif
+        goto store_next;
+#if defined(TARGET_PPC64)
+    case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            new_msr |= (target_ulong)1 << MSR_HV;
+#endif
+        goto store_next;
+    case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            new_msr |= (target_ulong)1 << MSR_HV;
+#endif
+        goto store_next;
+#endif /* defined(TARGET_PPC64) */
+#if defined(TARGET_PPC64H)
+    case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
+        srr0 = SPR_HSRR0;
+        srr1 = SPR_HSRR1;
+        new_msr |= (target_ulong)1 << MSR_HV;
+        goto store_next;
+#endif
+    case POWERPC_EXCP_TRACE:     /* Trace exception                          */
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            new_msr |= (target_ulong)1 << MSR_HV;
+#endif
+        goto store_next;
+#if defined(TARGET_PPC64H)
+    case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
+        srr0 = SPR_HSRR0;
+        srr1 = SPR_HSRR1;
+        new_msr |= (target_ulong)1 << MSR_HV;
+        goto store_next;
+    case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
+        srr0 = SPR_HSRR0;
+        srr1 = SPR_HSRR1;
+        new_msr |= (target_ulong)1 << MSR_HV;
+        goto store_next;
+    case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
+        srr0 = SPR_HSRR0;
+        srr1 = SPR_HSRR1;
+        new_msr |= (target_ulong)1 << MSR_HV;
+        goto store_next;
+    case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
+        srr0 = SPR_HSRR0;
+        srr1 = SPR_HSRR1;
+        new_msr |= (target_ulong)1 << MSR_HV;
+        goto store_next;
+#endif /* defined(TARGET_PPC64H) */
+    case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            new_msr |= (target_ulong)1 << MSR_HV;
+#endif
+        goto store_current;
+    case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
 #if defined (DEBUG_EXCEPTIONS)
-            if (loglevel != 0)
-                fprintf(logfile, "PIT exception\n");
+        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 */
-            goto store_gprs;
-        case PPC_FLAGS_EXCP_7x5:
-            /* ITLBMISS on 745/755 */
+        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
+        goto store_next;
+    case POWERPC_EXCP_IO:        /* IO error exception                       */
+        /* XXX: TODO */
+        cpu_abort(env, "601 IO error exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
+        /* XXX: TODO */
+        cpu_abort(env, "601 run mode exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
+        /* XXX: TODO */
+        cpu_abort(env, "602 emulation trap exception "
+                  "is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
+        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
+#if defined(TARGET_PPC64H) /* XXX: check this */
+        if (lpes1 == 0)
+            new_msr |= (target_ulong)1 << MSR_HV;
+#endif
+        switch (excp_model) {
+        case POWERPC_EXCP_602:
+        case POWERPC_EXCP_603:
+        case POWERPC_EXCP_603E:
+        case POWERPC_EXCP_G2:
+            goto tlb_miss_tgpr;
+        case POWERPC_EXCP_7x5:
             goto tlb_miss;
+        case POWERPC_EXCP_74xx:
+            goto tlb_miss_74xx;
         default:
-            cpu_abort(env, "Invalid exception 0x1000 !\n");
+            cpu_abort(env, "Invalid instruction TLB miss exception\n");
             break;
         }
-        return;
-    case 0x1010:
-        idx = 11;
-        switch (PPC_EXCP(env)) {
-        case PPC_FLAGS_EXCP_40x:
-            /* FIT on 4xx */
-            msr &= ~0xFFFF0000;
-#if defined (DEBUG_EXCEPTIONS)
-            if (loglevel != 0)
-                fprintf(logfile, "FIT exception\n");
+        break;
+    case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
+        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
+#if defined(TARGET_PPC64H) /* XXX: check this */
+        if (lpes1 == 0)
+            new_msr |= (target_ulong)1 << MSR_HV;
 #endif
-            goto store_next;
+        switch (excp_model) {
+        case POWERPC_EXCP_602:
+        case POWERPC_EXCP_603:
+        case POWERPC_EXCP_603E:
+        case POWERPC_EXCP_G2:
+            goto tlb_miss_tgpr;
+        case POWERPC_EXCP_7x5:
+            goto tlb_miss;
+        case POWERPC_EXCP_74xx:
+            goto tlb_miss_74xx;
         default:
-            cpu_abort(env, "Invalid exception 0x1010 !\n");
+            cpu_abort(env, "Invalid data load TLB miss exception\n");
             break;
         }
-        return;
-    case 0x1020:
-        idx = 12;
-        switch (PPC_EXCP(env)) {
-        case PPC_FLAGS_EXCP_40x:
-            /* Watchdog on 4xx */
-            msr &= ~0xFFFF0000;
-#if defined (DEBUG_EXCEPTIONS)
-            if (loglevel != 0)
-                fprintf(logfile, "WDT exception\n");
+        break;
+    case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
+        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
+#if defined(TARGET_PPC64H) /* XXX: check this */
+        if (lpes1 == 0)
+            new_msr |= (target_ulong)1 << MSR_HV;
 #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 */
-            msr &= ~0xFFFF0000;
-            goto store_next;
-        case PPC_FLAGS_EXCP_602:
-        case PPC_FLAGS_EXCP_603:
-            /* DLTLBMISS on 602/603 */
-            goto store_gprs;
-        case PPC_FLAGS_EXCP_7x5:
-            /* DLTLBMISS on 745/755 */
+        switch (excp_model) {
+        case POWERPC_EXCP_602:
+        case POWERPC_EXCP_603:
+        case POWERPC_EXCP_603E:
+        case POWERPC_EXCP_G2:
+        tlb_miss_tgpr:
+            /* Swap temporary saved registers with GPRs */
+            if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
+                new_msr |= (target_ulong)1 << MSR_TGPR;
+                hreg_swap_gpr_tgpr(env);
+            }
             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 */
-            msr &= ~0xFFFF0000;
-            goto store_next;
-        case PPC_FLAGS_EXCP_602:
-        case PPC_FLAGS_EXCP_603:
-            /* DSTLBMISS on 602/603 */
-        store_gprs:
-            /* Swap temporary saved registers with GPRs */
-            swap_gpr_tgpr(env);
-            msr_tgpr = 1;
+        case POWERPC_EXCP_7x5:
+        tlb_miss:
 #if defined (DEBUG_SOFTWARE_TLB)
             if (loglevel != 0) {
                 const unsigned char *es;
                 target_ulong *miss, *cmp;
                 int en;
-                if (excp == 0x1000) {
+                if (excp == POWERPC_EXCP_IFTLB) {
                     es = "I";
                     en = 'I';
                     miss = &env->spr[SPR_IMISS];
                     cmp = &env->spr[SPR_ICMP];
                 } else {
-                    if (excp == 0x1100)
+                    if (excp == POWERPC_EXCP_DLTLB)
                         es = "DL";
                     else
                         es = "DS";
@@ -2161,304 +2482,301 @@
                         env->error_code);
             }
 #endif
-            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) & (env->nb_ways - 1)) << 17;
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1200 !\n");
             break;
-        }
-        return;
-    case 0x1300:
-        switch (PPC_EXCP(env)) {
-        case PPC_FLAGS_EXCP_601:
-        case PPC_FLAGS_EXCP_602:
-        case PPC_FLAGS_EXCP_603:
-        case PPC_FLAGS_EXCP_604:
-        case PPC_FLAGS_EXCP_7x0:
-        case PPC_FLAGS_EXCP_7x5:
-            /* IABR on 6xx/7xx */
-            /* XXX: TODO */
-            cpu_abort(env, "IABR exception is not implemented yet !\n");
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1300 !\n");
+        case POWERPC_EXCP_74xx:
+        tlb_miss_74xx:
+#if defined (DEBUG_SOFTWARE_TLB)
+            if (loglevel != 0) {
+                const unsigned char *es;
+                target_ulong *miss, *cmp;
+                int en;
+                if (excp == POWERPC_EXCP_IFTLB) {
+                    es = "I";
+                    en = 'I';
+                    miss = &env->spr[SPR_TLBMISS];
+                    cmp = &env->spr[SPR_PTEHI];
+                } else {
+                    if (excp == POWERPC_EXCP_DLTLB)
+                        es = "DL";
+                    else
+                        es = "DS";
+                    en = 'D';
+                    miss = &env->spr[SPR_TLBMISS];
+                    cmp = &env->spr[SPR_PTEHI];
+                }
+                fprintf(logfile, "74xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
+                        " %08x\n",
+                        es, en, *miss, en, *cmp, env->error_code);
+            }
+#endif
+            msr |= env->error_code; /* key bit */
             break;
-        }
-        return;
-    case 0x1400:
-        switch (PPC_EXCP(env)) {
-        case PPC_FLAGS_EXCP_601:
-        case PPC_FLAGS_EXCP_602:
-        case PPC_FLAGS_EXCP_603:
-        case PPC_FLAGS_EXCP_604:
-        case PPC_FLAGS_EXCP_7x0:
-        case PPC_FLAGS_EXCP_7x5:
-            /* SMI on 6xx/7xx */
-            /* XXX: TODO */
-            cpu_abort(env, "SMI exception is not implemented yet !\n");
-            goto store_next;
         default:
-            cpu_abort(env, "Invalid exception 0x1400 !\n");
+            cpu_abort(env, "Invalid data store TLB miss exception\n");
             break;
         }
-        return;
-    case 0x1500:
-        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;
-        case PPC_FLAGS_EXCP_970:
-            /* Soft patch exception on 970 */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "970 soft-patch exception is not implemented yet !\n");
-            goto store_next;
-        case PPC_FLAGS_EXCP_74xx:
-            /* VPU assist on 74xx */
-            /* XXX: TODO */
-            cpu_abort(env, "VPU assist exception is not implemented yet !\n");
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1500 !\n");
-            break;
-        }
-        return;
-    case 0x1600:
-        switch (PPC_EXCP(env)) {
-        case PPC_FLAGS_EXCP_602:
-            /* Emulation trap on 602 */
-            /* XXX: TODO */
-            cpu_abort(env, "602 emulation trap exception "
-                      "is not implemented yet !\n");
-            goto store_next;
-        case PPC_FLAGS_EXCP_970:
-            /* Maintenance exception on 970 */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "970 maintenance exception is not implemented yet !\n");
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1600 !\n");
-            break;
-        }
-        return;
-    case 0x1700:
-        switch (PPC_EXCP(env)) {
-        case PPC_FLAGS_EXCP_7x0:
-        case PPC_FLAGS_EXCP_7x5:
-            /* Thermal management interrupt on G3 */
-            /* XXX: TODO */
-            cpu_abort(env, "G3 thermal management exception "
-                      "is not implemented yet !\n");
-            goto store_next;
-        case PPC_FLAGS_EXCP_970:
-            /* VPU assist on 970 */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "970 VPU assist exception is not implemented yet !\n");
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1700 !\n");
-            break;
-        }
-        return;
-    case 0x1800:
-        switch (PPC_EXCP(env)) {
-        case PPC_FLAGS_EXCP_970:
-            /* Thermal exception on 970 */
-            /* XXX: TODO */
-            cpu_abort(env, "970 thermal management exception "
-                      "is not implemented yet !\n");
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1800 !\n");
-            break;
-        }
-        return;
-    case 0x2000:
-        switch (PPC_EXCP(env)) {
-        case PPC_FLAGS_EXCP_40x:
-            /* DEBUG on 4xx */
-            /* XXX: TODO */
-            cpu_abort(env, "40x debug exception is not implemented yet !\n");
-            goto store_next;
-        case PPC_FLAGS_EXCP_601:
-            /* Run mode exception on 601 */
-            /* XXX: TODO */
-            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;
-        }
-        return;
-    /* Other exceptions */
-    /* Qemu internal exceptions:
-     * we should never come here with those values: abort execution
-     */
+        goto store_next;
+    case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
+        /* XXX: TODO */
+        cpu_abort(env, "Floating point assist exception "
+                  "is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
+        /* XXX: TODO */
+        cpu_abort(env, "IABR exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_SMI:       /* System management interrupt              */
+        /* XXX: TODO */
+        cpu_abort(env, "SMI exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
+        /* XXX: TODO */
+        cpu_abort(env, "Thermal management exception "
+                  "is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
+        new_msr &= ~((target_ulong)1 << MSR_RI);
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            new_msr |= (target_ulong)1 << MSR_HV;
+#endif
+        /* XXX: TODO */
+        cpu_abort(env,
+                  "Performance counter exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
+        /* XXX: TODO */
+        cpu_abort(env, "VPU assist exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
+        /* XXX: TODO */
+        cpu_abort(env,
+                  "970 soft-patch exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
+        /* XXX: TODO */
+        cpu_abort(env,
+                  "970 maintenance exception is not implemented yet !\n");
+        goto store_next;
     default:
-        cpu_abort(env, "Invalid exception: code %d (%04x)\n", excp, excp);
-        return;
+    excp_invalid:
+        cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
+        break;
     store_current:
         /* save current instruction location */
-        *srr_0 = env->nip - 4;
+        env->spr[srr0] = env->nip - 4;
         break;
     store_next:
         /* save next instruction location */
-        *srr_0 = env->nip;
+        env->spr[srr0] = env->nip;
         break;
     }
-    /* Save msr */
-    *srr_1 = msr;
-    if (asrr_0 != NULL)
-        *asrr_0 = *srr_0;
-    if (asrr_1 != NULL)
-        *asrr_1 = *srr_1;
+    /* Save MSR */
+    env->spr[srr1] = msr;
+    /* If any alternate SRR register are defined, duplicate saved values */
+    if (asrr0 != -1)
+        env->spr[asrr0] = env->spr[srr0];
+    if (asrr1 != -1)
+        env->spr[asrr1] = env->spr[srr1];
     /* If we disactivated any translation, flush TLBs */
-    if (msr_ir || msr_dr) {
+    if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
         tlb_flush(env, 1);
+    /* reload MSR with correct bits */
+    new_msr &= ~((target_ulong)1 << MSR_EE);
+    new_msr &= ~((target_ulong)1 << MSR_PR);
+    new_msr &= ~((target_ulong)1 << MSR_FP);
+    new_msr &= ~((target_ulong)1 << MSR_FE0);
+    new_msr &= ~((target_ulong)1 << MSR_SE);
+    new_msr &= ~((target_ulong)1 << MSR_BE);
+    new_msr &= ~((target_ulong)1 << MSR_FE1);
+    new_msr &= ~((target_ulong)1 << MSR_IR);
+    new_msr &= ~((target_ulong)1 << MSR_DR);
+#if 0 /* Fix this: not on all targets */
+    new_msr &= ~((target_ulong)1 << MSR_PMM);
+#endif
+    new_msr &= ~((target_ulong)1 << MSR_LE);
+    if (msr_ile)
+        new_msr |= (target_ulong)1 << MSR_LE;
+    else
+        new_msr &= ~((target_ulong)1 << MSR_LE);
+    /* Jump to handler */
+    vector = env->excp_vectors[excp];
+    if (vector == (target_ulong)-1) {
+        cpu_abort(env, "Raised an exception without defined vector %d\n",
+                  excp);
     }
-    /* reload MSR with correct bits */
-    msr_ee = 0;
-    msr_pr = 0;
-    msr_fp = 0;
-    msr_fe0 = 0;
-    msr_se = 0;
-    msr_be = 0;
-    msr_fe1 = 0;
-    msr_ir = 0;
-    msr_dr = 0;
-    msr_ri = 0;
-    msr_le = msr_ile;
-    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);
+    vector |= env->excp_prefix;
+#if defined(TARGET_PPC64)
+    if (excp_model == POWERPC_EXCP_BOOKE) {
+        if (!msr_icm) {
+            new_msr &= ~((target_ulong)1 << MSR_CM);
+            vector = (uint32_t)vector;
+        } else {
+            new_msr |= (target_ulong)1 << MSR_CM;
         }
-#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;
+        if (!msr_isf) {
+            new_msr &= ~((target_ulong)1 << MSR_SF);
+            vector = (uint32_t)vector;
+        } else {
+            new_msr |= (target_ulong)1 << MSR_SF;
+        }
     }
-    do_compute_hflags(env);
-    /* Jump to handler */
-    env->exception_index = EXCP_NONE;
+#endif
+    /* XXX: we don't use hreg_store_msr here as already have treated
+     *      any special case that could occur. Just store MSR and update hflags
+     */
+    env->msr = new_msr;
+    hreg_compute_hflags(env);
+    env->nip = vector;
+    /* Reset exception state */
+    env->exception_index = POWERPC_EXCP_NONE;
+    env->error_code = 0;
 }
 
+void do_interrupt (CPUState *env)
+{
+    powerpc_excp(env, env->excp_model, env->exception_index);
+}
+
 void ppc_hw_interrupt (CPUPPCState *env)
 {
-    int raised = 0;
+#if defined(TARGET_PPC64H)
+    int hdice;
+#endif
 
-#if 1
+#if 0
     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);
+                env->interrupt_request, (int)msr_me, (int)msr_ee);
     }
 #endif
-    /* Raise it */
+    /* External reset */
     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;
+        powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
+        return;
     }
-    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;
-        }
+    /* Machine check exception */
+    if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
+        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
+        powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
+        return;
     }
-    if (raised == 0 && msr_ee != 0) {
-#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+#if 0 /* TODO */
+    /* External debug exception */
+    if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
+        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
+        powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
+        return;
+    }
+#endif
+#if defined(TARGET_PPC64H)
+    hdice = env->spr[SPR_LPCR] & 1;
+    if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
         /* 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
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
+            return;
+        }
+    }
 #endif
+    if (msr_ce != 0) {
+        /* External critical interrupt */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
+            /* Taking a critical external interrupt does not clear the external
+             * critical interrupt status
+             */
+#if 0
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
+#endif
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
+            return;
+        }
+    }
+    if (msr_ee != 0) {
+        /* Watchdog timer on embedded PowerPC */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
+            return;
+        }
+#if defined(TARGET_PPCEMB)
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
+            return;
+        }
+#endif
+#if defined(TARGET_PPCEMB)
+        /* External interrupt */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
+            /* Taking an external interrupt does not clear the external
+             * interrupt status
+             */
+#if 0
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
+#endif
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
+            return;
+        }
+#endif
+        /* Fixed interval timer on embedded PowerPC */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
+            return;
+        }
+        /* Programmable interval timer on embedded PowerPC */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
+            return;
+        }
         /* 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;
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
+            return;
+        }
+#if !defined(TARGET_PPCEMB)
         /* External interrupt */
-        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
-            env->exception_index = EXCP_EXTERNAL;
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
             /* 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
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
+            return;
+        }
+#endif
+#if defined(TARGET_PPCEMB)
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
+            return;
+        }
+#endif
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
+            return;
+        }
         /* Thermal interrupt */
-        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
-            env->exception_index = EXCP_970_THRM;
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
-            raised = 1;
-#endif
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
+            return;
         }
-#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 */
 
@@ -2492,37 +2810,36 @@
 void cpu_ppc_reset (void *opaque)
 {
     CPUPPCState *env;
-    int i;
+    target_ulong msr;
 
     env = opaque;
-    /* XXX: some of those flags initialisation values could depend
-     *      on the actual PowerPC implementation
-     */
-    for (i = 0; i < 63; i++)
-        env->msr[i] = 0;
+    msr = (target_ulong)0;
 #if defined(TARGET_PPC64)
-    msr_hv = 0; /* Should be 1... */
+    msr |= (target_ulong)0 << MSR_HV; /* Should be 1... */
 #endif
-    msr_ap = 0; /* TO BE CHECKED */
-    msr_sa = 0; /* TO BE CHECKED */
-    msr_ip = 0; /* TO BE CHECKED */
+    msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
+    msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
+    msr |= (target_ulong)1 << MSR_EP;
 #if defined (DO_SINGLE_STEP) && 0
     /* Single step trace mode */
-    msr_se = 1;
-    msr_be = 1;
+    msr |= (target_ulong)1 << MSR_SE;
+    msr |= (target_ulong)1 << MSR_BE;
 #endif
 #if defined(CONFIG_USER_ONLY)
-    msr_fp = 1; /* Allow floating point exceptions */
-    msr_pr = 1;
+    msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
+    msr |= (target_ulong)1 << MSR_PR;
 #else
-    env->nip = 0xFFFFFFFC;
-    ppc_tlb_invalidate_all(env);
+    env->nip = env->hreset_vector | env->excp_prefix;
+    if (env->mmu_model != POWERPC_MMU_REAL_4xx)
+        ppc_tlb_invalidate_all(env);
 #endif
-    do_compute_hflags(env);
+    env->msr = msr;
+    hreg_compute_hflags(env);
     env->reserve = -1;
     /* Be sure no exception or interrupt is pending */
     env->pending_interrupts = 0;
-    env->exception_index = EXCP_NONE;
+    env->exception_index = POWERPC_EXCP_NONE;
+    env->error_code = 0;
     /* Flush all TLBs */
     tlb_flush(env, 1);
 }
@@ -2535,7 +2852,6 @@
     if (!env)
         return NULL;
     cpu_exec_init(env);
-    cpu_ppc_reset(env);
 
     return env;
 }

Added: trunk/src/host/qemu-neo1973/target-ppc/helper_regs.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/helper_regs.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-ppc/helper_regs.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -0,0 +1,121 @@
+/*
+ *  PowerPC emulation special registers manipulation 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
+ */
+
+#if !defined(__HELPER_REGS_H__)
+#define __HELPER_REGS_H__
+
+static always_inline target_ulong hreg_load_xer (CPUPPCState *env)
+{
+    return (xer_so << XER_SO) |
+        (xer_ov << XER_OV) |
+        (xer_ca << XER_CA) |
+        (xer_bc << XER_BC) |
+        (xer_cmp << XER_CMP);
+}
+
+static always_inline void hreg_store_xer (CPUPPCState *env, target_ulong 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) & 0x7F;
+}
+
+/* Swap temporary saved registers with GPRs */
+static always_inline void hreg_swap_gpr_tgpr (CPUPPCState *env)
+{
+    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;
+}
+
+static always_inline void hreg_compute_hflags (CPUPPCState *env)
+{
+    target_ulong hflags_mask;
+
+    /* We 'forget' FE0 & FE1: we'll never generate imprecise exceptions */
+    hflags_mask = (1 << MSR_VR) | (1 << MSR_AP) | (1 << MSR_SA) |
+        (1 << MSR_PR) | (1 << MSR_FP) | (1 << MSR_SE) | (1 << MSR_BE) |
+        (1 << MSR_LE);
+#if defined (TARGET_PPC64)
+    hflags_mask |= (1ULL << MSR_CM) | (1ULL << MSR_SF);
+#if defined (TARGET_PPC64H)
+    hflags_mask |= 1ULL << MSR_HV;
+    /* Precompute MMU index */
+    if (msr_pr == 0 && msr_hv != 0)
+        env->mmu_idx = 2;
+    else
+#endif
+#endif
+        env->mmu_idx = 1 - msr_pr;
+    env->hflags = env->msr & hflags_mask;
+}
+
+static always_inline int hreg_store_msr (CPUPPCState *env, target_ulong value)
+{
+    int excp;
+
+    excp = 0;
+    value &= env->msr_mask;
+#if !defined (CONFIG_USER_ONLY)
+    if (((value >> MSR_IR) & 1) != msr_ir ||
+        ((value >> MSR_DR) & 1) != msr_dr) {
+        /* Flush all tlb when changing translation mode */
+        tlb_flush(env, 1);
+        excp = POWERPC_EXCP_NONE;
+        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+    }
+    if (unlikely((env->flags & POWERPC_FLAG_TGPR) &&
+                 ((value ^ env->msr) & (1 << MSR_TGPR)))) {
+        /* Swap temporary saved registers with GPRs */
+        hreg_swap_gpr_tgpr(env);
+    }
+    if (unlikely((value >> MSR_EP) & 1) != msr_ep) {
+        /* Change the exception prefix on PowerPC 601 */
+        env->excp_prefix = ((value >> MSR_EP) & 1) * 0xFFF00000;
+    }
+#endif
+    env->msr = value;
+    hreg_compute_hflags(env);
+#if !defined (CONFIG_USER_ONLY)
+    if (unlikely(msr_pow == 1)) {
+        if ((*env->check_pow)(env)) {
+            env->halted = 1;
+            excp = EXCP_HALTED;
+        }
+    }
+#endif
+
+    return excp;
+}
+
+#endif /* !defined(__HELPER_REGS_H__) */

Modified: trunk/src/host/qemu-neo1973/target-ppc/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-ppc/op.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -22,6 +22,8 @@
 
 #include "config.h"
 #include "exec.h"
+#include "host-utils.h"
+#include "helper_regs.h"
 #include "op_helper.h"
 
 #define REG 0
@@ -120,7 +122,6 @@
 #define REG 31
 #include "op_template.h"
 
-
 void OPPROTO op_print_mem_EA (void)
 {
     do_print_mem_EA(T0);
@@ -135,13 +136,6 @@
     RETURN();
 }
 
-/* Set Rc1 (for floating point arithmetic) */
-void OPPROTO op_set_Rc1 (void)
-{
-    env->crf[1] = env->fpscr[7];
-    RETURN();
-}
-
 /* Constants load */
 void OPPROTO op_reset_T0 (void)
 {
@@ -180,7 +174,7 @@
 #if 0 // unused
 void OPPROTO op_set_T2 (void)
 {
-    T2 = PARAM1;
+    T2 = (uint32_t)PARAM1;
     RETURN();
 }
 #endif
@@ -285,16 +279,24 @@
 
 void OPPROTO op_load_xer (void)
 {
-    do_load_xer();
+    T0 = hreg_load_xer(env);
     RETURN();
 }
 
 void OPPROTO op_store_xer (void)
 {
-    do_store_xer();
+    hreg_store_xer(env, T0);
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_store_pri (void)
+{
+    do_store_pri(PARAM1);
+    RETURN();
+}
+#endif
+
 #if !defined(CONFIG_USER_ONLY)
 /* Segment registers load and store */
 void OPPROTO op_load_sr (void)
@@ -309,6 +311,20 @@
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_load_slb (void)
+{
+    T0 = ppc_load_slb(env, T1);
+    RETURN();
+}
+
+void OPPROTO op_store_slb (void)
+{
+    ppc_store_slb(env, T1, T0);
+    RETURN();
+}
+#endif /* defined(TARGET_PPC64) */
+
 void OPPROTO op_load_sdr1 (void)
 {
     T0 = env->sdr1;
@@ -337,23 +353,35 @@
 
 void OPPROTO op_load_msr (void)
 {
-    T0 = do_load_msr(env);
+    T0 = env->msr;
     RETURN();
 }
 
 void OPPROTO op_store_msr (void)
 {
-    do_store_msr(env, T0);
+    do_store_msr();
     RETURN();
 }
 
 #if defined (TARGET_PPC64)
 void OPPROTO op_store_msr_32 (void)
 {
-    ppc_store_msr_32(env, T0);
+    T0 = (env->msr & ~0xFFFFFFFFULL) | (T0 & 0xFFFFFFFF);
+    do_store_msr();
     RETURN();
 }
 #endif
+
+void OPPROTO op_update_riee (void)
+{
+    /* We don't call do_store_msr here as we won't trigger
+     * any special case nor change hflags
+     */
+    T0 &= (1 << MSR_RI) | (1 << MSR_EE);
+    env->msr &= ~(1 << MSR_RI) | (1 << MSR_EE);
+    env->msr |= T0;
+    RETURN();
+}
 #endif
 
 /* SPR */
@@ -423,6 +451,18 @@
     RETURN();
 }
 
+void OPPROTO op_load_atbl (void)
+{
+    T0 = cpu_ppc_load_atbl(env);
+    RETURN();
+}
+
+void OPPROTO op_load_atbu (void)
+{
+    T0 = cpu_ppc_load_atbu(env);
+    RETURN();
+}
+
 #if !defined(CONFIG_USER_ONLY)
 void OPPROTO op_store_tbl (void)
 {
@@ -436,6 +476,18 @@
     RETURN();
 }
 
+void OPPROTO op_store_atbl (void)
+{
+    cpu_ppc_store_atbl(env, T0);
+    RETURN();
+}
+
+void OPPROTO op_store_atbu (void)
+{
+    cpu_ppc_store_atbu(env, T0);
+    RETURN();
+}
+
 void OPPROTO op_load_decr (void)
 {
     T0 = cpu_ppc_load_decr(env);
@@ -494,24 +546,111 @@
 #endif /* !defined(CONFIG_USER_ONLY) */
 
 /* FPSCR */
-void OPPROTO op_load_fpscr (void)
+#ifdef CONFIG_SOFTFLOAT
+void OPPROTO op_reset_fpstatus (void)
 {
-    do_load_fpscr();
+    env->fp_status.float_exception_flags = 0;
     RETURN();
 }
+#endif
 
-void OPPROTO op_store_fpscr (void)
+void OPPROTO op_compute_fprf (void)
 {
-    do_store_fpscr(PARAM1);
+    do_compute_fprf(PARAM1);
     RETURN();
 }
 
-void OPPROTO op_reset_scrfx (void)
+#ifdef CONFIG_SOFTFLOAT
+void OPPROTO op_float_check_status (void)
 {
-    env->fpscr[7] &= ~0x8;
+    do_float_check_status();
     RETURN();
 }
+#else
+void OPPROTO op_float_check_status (void)
+{
+    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
+        (env->error_code & POWERPC_EXCP_FP)) {
+        /* Differred floating-point exception after target FPR update */
+        if (msr_fe0 != 0 || msr_fe1 != 0)
+            do_raise_exception_err(env->exception_index, env->error_code);
+    }
+    RETURN();
+}
+#endif
 
+#if defined(WORDS_BIGENDIAN)
+#define WORD0 0
+#define WORD1 1
+#else
+#define WORD0 1
+#define WORD1 0
+#endif
+void OPPROTO op_load_fpscr_FT0 (void)
+{
+    /* The 32 MSB of the target fpr are undefined.
+     * They'll be zero...
+     */
+    union {
+        float64 d;
+        struct {
+            uint32_t u[2];
+        } s;
+    } u;
+
+    u.s.u[WORD0] = 0;
+    u.s.u[WORD1] = env->fpscr;
+    FT0 = u.d;
+    RETURN();
+}
+
+void OPPROTO op_set_FT0 (void)
+{
+    union {
+        float64 d;
+        struct {
+            uint32_t u[2];
+        } s;
+    } u;
+
+    u.s.u[WORD0] = 0;
+    u.s.u[WORD1] = PARAM1;
+    FT0 = u.d;
+    RETURN();
+}
+#undef WORD0
+#undef WORD1
+
+void OPPROTO op_load_fpscr_T0 (void)
+{
+    T0 = (env->fpscr >> PARAM1) & 0xF;
+    RETURN();
+}
+
+void OPPROTO op_load_fpcc (void)
+{
+    T0 = fpscr_fpcc;
+    RETURN();
+}
+
+void OPPROTO op_fpscr_resetbit (void)
+{
+    env->fpscr &= PARAM1;
+    RETURN();
+}
+
+void OPPROTO op_fpscr_setbit (void)
+{
+    do_fpscr_setbit(PARAM1);
+    RETURN();
+}
+
+void OPPROTO op_store_fpscr (void)
+{
+    do_store_fpscr(PARAM1);
+    RETURN();
+}
+
 /* crf operations */
 void OPPROTO op_getbit_T0 (void)
 {
@@ -527,7 +666,7 @@
 
 void OPPROTO op_setcrfbit (void)
 {
-    T1 = (T1 & PARAM1) | (T0 << PARAM2);
+    T1 = (T1 & (uint32_t)PARAM1) | (T0 << PARAM2);
     RETURN();
 }
 
@@ -922,7 +1061,7 @@
 {
     uint64_t tl, th;
 
-    do_imul64(&tl, &th);
+    muls64(&tl, &th, T0, T1);
     T0 = th;
     RETURN();
 }
@@ -940,7 +1079,7 @@
 {
     uint64_t tl, th;
 
-    do_mul64(&tl, &th);
+    mulu64(&tl, &th, T0, T1);
     T0 = th;
     RETURN();
 }
@@ -1101,7 +1240,7 @@
 #if defined(TARGET_PPC64)
 void OPPROTO op_subfic_64 (void)
 {
-    T0 = PARAM1 + ~T0 + 1;
+    T0 = (int64_t)PARAM1 + ~T0 + 1;
     if ((uint64_t)T0 <= (uint64_t)PARAM1) {
         xer_ca = 1;
     } else {
@@ -1343,27 +1482,41 @@
 /* andi. */
 void OPPROTO op_andi_T0 (void)
 {
-    T0 &= PARAM1;
+    T0 &= (uint32_t)PARAM1;
     RETURN();
 }
 
 void OPPROTO op_andi_T1 (void)
 {
-    T1 &= PARAM1;
+    T1 &= (uint32_t)PARAM1;
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_andi_T0_64 (void)
+{
+    T0 &= ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
+    RETURN();
+}
+
+void OPPROTO op_andi_T1_64 (void)
+{
+    T1 &= ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
+    RETURN();
+}
+#endif
+
 /* count leading zero */
 void OPPROTO op_cntlzw (void)
 {
-    T0 = _do_cntlzw(T0);
+    do_cntlzw();
     RETURN();
 }
 
 #if defined(TARGET_PPC64)
 void OPPROTO op_cntlzd (void)
 {
-    T0 = _do_cntlzd(T0);
+    do_cntlzd();
     RETURN();
 }
 #endif
@@ -1436,7 +1589,7 @@
 /* ori */
 void OPPROTO op_ori (void)
 {
-    T0 |= PARAM1;
+    T0 |= (uint32_t)PARAM1;
     RETURN();
 }
 
@@ -1450,7 +1603,7 @@
 /* xori */
 void OPPROTO op_xori (void)
 {
-    T0 ^= PARAM1;
+    T0 ^= (uint32_t)PARAM1;
     RETURN();
 }
 
@@ -1630,28 +1783,44 @@
 /* fadd - fadd. */
 void OPPROTO op_fadd (void)
 {
+#if USE_PRECISE_EMULATION
+    do_fadd();
+#else
     FT0 = float64_add(FT0, FT1, &env->fp_status);
+#endif
     RETURN();
 }
 
 /* fsub - fsub. */
 void OPPROTO op_fsub (void)
 {
+#if USE_PRECISE_EMULATION
+    do_fsub();
+#else
     FT0 = float64_sub(FT0, FT1, &env->fp_status);
+#endif
     RETURN();
 }
 
 /* fmul - fmul. */
 void OPPROTO op_fmul (void)
 {
+#if USE_PRECISE_EMULATION
+    do_fmul();
+#else
     FT0 = float64_mul(FT0, FT1, &env->fp_status);
+#endif
     RETURN();
 }
 
 /* fdiv - fdiv. */
 void OPPROTO op_fdiv (void)
 {
+#if USE_PRECISE_EMULATION
+    do_fdiv();
+#else
     FT0 = float64_div(FT0, FT1, &env->fp_status);
+#endif
     RETURN();
 }
 
@@ -1662,6 +1831,13 @@
     RETURN();
 }
 
+/* fre - fre. */
+void OPPROTO op_fre (void)
+{
+    do_fre();
+    RETURN();
+}
+
 /* fres - fres. */
 void OPPROTO op_fres (void)
 {
@@ -1726,7 +1902,11 @@
 /* frsp - frsp. */
 void OPPROTO op_frsp (void)
 {
+#if USE_PRECISE_EMULATION
+    do_frsp();
+#else
     FT0 = float64_to_float32(FT0, &env->fp_status);
+#endif
     RETURN();
 }
 
@@ -1767,6 +1947,30 @@
 }
 #endif
 
+void OPPROTO op_frin (void)
+{
+    do_frin();
+    RETURN();
+}
+
+void OPPROTO op_friz (void)
+{
+    do_friz();
+    RETURN();
+}
+
+void OPPROTO op_frip (void)
+{
+    do_frip();
+    RETURN();
+}
+
+void OPPROTO op_frim (void)
+{
+    do_frim();
+    RETURN();
+}
+
 /***                         Floating-Point compare                        ***/
 /* fcmpu */
 void OPPROTO op_fcmpu (void)
@@ -1816,7 +2020,12 @@
 #define MEMSUFFIX _kernel
 #include "op_helper.h"
 #include "op_mem.h"
+#if defined(TARGET_PPC64H)
+#define MEMSUFFIX _hypv
+#include "op_helper.h"
+#include "op_mem.h"
 #endif
+#endif
 
 /* Special op to check and maybe clear reservation */
 void OPPROTO op_check_reservation (void)
@@ -1835,6 +2044,12 @@
 }
 #endif
 
+void OPPROTO op_wait (void)
+{
+    env->halted = 1;
+    RETURN();
+}
+
 /* Return from interrupt */
 #if !defined(CONFIG_USER_ONLY)
 void OPPROTO op_rfi (void)
@@ -1850,8 +2065,31 @@
     RETURN();
 }
 #endif
+
+#if defined(TARGET_PPC64H)
+void OPPROTO op_hrfid (void)
+{
+    do_hrfid();
+    RETURN();
+}
 #endif
 
+/* Exception vectors */
+void OPPROTO op_store_excp_prefix (void)
+{
+    T0 &= env->ivpr_mask;
+    env->excp_prefix = T0;
+    RETURN();
+}
+
+void OPPROTO op_store_excp_vector (void)
+{
+    T0 &= env->ivor_mask;
+    env->excp_vectors[PARAM1] = T0;
+    RETURN();
+}
+#endif
+
 /* Trap word */
 void OPPROTO op_tw (void)
 {
@@ -1871,21 +2109,21 @@
 /* tlbia */
 void OPPROTO op_tlbia (void)
 {
-    do_tlbia();
+    ppc_tlb_invalidate_all(env);
     RETURN();
 }
 
 /* tlbie */
 void OPPROTO op_tlbie (void)
 {
-    do_tlbie();
+    ppc_tlb_invalidate_one(env, (uint32_t)T0);
     RETURN();
 }
 
 #if defined(TARGET_PPC64)
 void OPPROTO op_tlbie_64 (void)
 {
-    do_tlbie_64();
+    ppc_tlb_invalidate_one(env, T0);
     RETURN();
 }
 #endif
@@ -1893,20 +2131,26 @@
 #if defined(TARGET_PPC64)
 void OPPROTO op_slbia (void)
 {
-    do_slbia();
+    ppc_slb_invalidate_all(env);
     RETURN();
 }
 
 void OPPROTO op_slbie (void)
 {
-    do_slbie();
+    ppc_slb_invalidate_one(env, (uint32_t)T0);
     RETURN();
 }
+
+void OPPROTO op_slbie_64 (void)
+{
+    ppc_slb_invalidate_one(env, T0);
+    RETURN();
+}
 #endif
 #endif
 
+#if !defined(CONFIG_USER_ONLY)
 /* PowerPC 602/603/755 software TLB load instructions */
-#if !defined(CONFIG_USER_ONLY)
 void OPPROTO op_6xx_tlbld (void)
 {
     do_load_6xx_tlb(0);
@@ -1918,6 +2162,19 @@
     do_load_6xx_tlb(1);
     RETURN();
 }
+
+/* PowerPC 74xx software TLB load instructions */
+void OPPROTO op_74xx_tlbld (void)
+{
+    do_load_74xx_tlb(0);
+    RETURN();
+}
+
+void OPPROTO op_74xx_tlbli (void)
+{
+    do_load_74xx_tlb(1);
+    RETURN();
+}
 #endif
 
 /* 601 specific */
@@ -2090,7 +2347,7 @@
 void OPPROTO op_POWER_rlmi (void)
 {
     T0 = rotl32(T0, T2) & PARAM1;
-    T0 |= T1 & PARAM2;
+    T0 |= T1 & (uint32_t)PARAM2;
     RETURN();
 }
 
@@ -2319,7 +2576,6 @@
     RETURN();
 }
 
-#if !defined(CONFIG_USER_ONLY)
 void OPPROTO op_load_dcr (void)
 {
     do_load_dcr();
@@ -2332,6 +2588,7 @@
     RETURN();
 }
 
+#if !defined(CONFIG_USER_ONLY)
 /* Return from critical interrupt :
  * same as rfi, except nip & MSR are loaded from SRR2/3 instead of SRR0/1
  */
@@ -2361,58 +2618,44 @@
 
 void OPPROTO op_wrte (void)
 {
-    msr_ee = T0 >> 16;
+    /* We don't call do_store_msr here as we won't trigger
+     * any special case nor change hflags
+     */
+    T0 &= 1 << MSR_EE;
+    env->msr &= ~(1 << MSR_EE);
+    env->msr |= T0;
     RETURN();
 }
 
-void OPPROTO op_booke_tlbre0 (void)
+void OPPROTO op_440_tlbre (void)
 {
-    do_booke_tlbre0();
+    do_440_tlbre(PARAM1);
     RETURN();
 }
 
-void OPPROTO op_booke_tlbre1 (void)
+void OPPROTO op_440_tlbsx (void)
 {
-    do_booke_tlbre1();
+    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
     RETURN();
 }
 
-void OPPROTO op_booke_tlbre2 (void)
+void OPPROTO op_4xx_tlbsx_check (void)
 {
-    do_booke_tlbre2();
-    RETURN();
-}
+    int tmp;
 
-void OPPROTO op_booke_tlbsx (void)
-{
-    do_booke_tlbsx();
+    tmp = xer_so;
+    if (T0 != -1)
+        tmp |= 0x02;
+    env->crf[0] = tmp;
     RETURN();
 }
 
-void OPPROTO op_booke_tlbsx_ (void)
+void OPPROTO op_440_tlbwe (void)
 {
-    do_booke_tlbsx_();
+    do_440_tlbwe(PARAM1);
     RETURN();
 }
 
-void OPPROTO op_booke_tlbwe0 (void)
-{
-    do_booke_tlbwe0();
-    RETURN();
-}
-
-void OPPROTO op_booke_tlbwe1 (void)
-{
-    do_booke_tlbwe1();
-    RETURN();
-}
-
-void OPPROTO op_booke_tlbwe2 (void)
-{
-    do_booke_tlbwe2();
-    RETURN();
-}
-
 void OPPROTO op_4xx_tlbre_lo (void)
 {
     do_4xx_tlbre_lo();
@@ -2427,16 +2670,10 @@
 
 void OPPROTO op_4xx_tlbsx (void)
 {
-    do_4xx_tlbsx();
+    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]);
     RETURN();
 }
 
-void OPPROTO op_4xx_tlbsx_ (void)
-{
-    do_4xx_tlbsx_();
-    RETURN();
-}
-
 void OPPROTO op_4xx_tlbwe_lo (void)
 {
     do_4xx_tlbwe_lo();
@@ -2503,6 +2740,7 @@
 void OPPROTO op_store_40x_dbcr0 (void)
 {
     store_40x_dbcr0(env, T0);
+    RETURN();
 }
 
 void OPPROTO op_store_40x_sler (void)
@@ -2522,7 +2760,6 @@
     store_booke_tsr(env, T0);
     RETURN();
 }
-
 #endif /* !defined(CONFIG_USER_ONLY) */
 
 #if 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-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -18,7 +18,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include "exec.h"
+#include "host-utils.h"
 
+#include "helper_regs.h"
 #include "op_helper.h"
 
 #define MEMSUFFIX _raw
@@ -31,12 +33,16 @@
 #define MEMSUFFIX _kernel
 #include "op_helper.h"
 #include "op_helper_mem.h"
+#if defined(TARGET_PPC64H)
+#define MEMSUFFIX _hypv
+#include "op_helper.h"
+#include "op_helper_mem.h"
 #endif
+#endif
 
 //#define DEBUG_OP
 //#define DEBUG_EXCEPTIONS
 //#define DEBUG_SOFTWARE_TLB
-//#define FLUSH_ALL_TLBS
 
 /*****************************************************************************/
 /* Exceptions processing helpers */
@@ -46,14 +52,6 @@
 #if 0
     printf("Raise exception %3x code : %d\n", exception, error_code);
 #endif
-    switch (exception) {
-    case EXCP_PROGRAM:
-        if (error_code == EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0)
-            return;
-        break;
-    default:
-        break;
-    }
     env->exception_index = exception;
     env->error_code = error_code;
     cpu_loop_exit();
@@ -94,95 +92,14 @@
     }
 }
 
-void do_load_xer (void)
+#if defined(TARGET_PPC64)
+void do_store_pri (int prio)
 {
-    T0 = (xer_so << XER_SO) |
-        (xer_ov << XER_OV) |
-        (xer_ca << XER_CA) |
-        (xer_bc << XER_BC) |
-        (xer_cmp << XER_CMP);
+    env->spr[SPR_PPR] &= ~0x001C000000000000ULL;
+    env->spr[SPR_PPR] |= ((uint64_t)prio & 0x7) << 50;
 }
-
-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;
-    }
-    /* 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) {
@@ -204,79 +121,6 @@
 
 /*****************************************************************************/
 /* 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;
@@ -408,8 +252,9 @@
     int64_t th;
     uint64_t tl;
 
-    do_imul64(&tl, &th);
-    if (likely(th == 0)) {
+    muls64(&tl, &th, T0, T1);
+    /* If th != 0 && th != -1, then we had an overflow */
+    if (likely((th + 1) <= 1)) {
         xer_ov = 0;
     } else {
         xer_ov = 1;
@@ -537,6 +382,18 @@
 }
 #endif
 
+void do_cntlzw (void)
+{
+    T0 = clz32(T0);
+}
+
+#if defined(TARGET_PPC64)
+void do_cntlzd (void)
+{
+    T0 = clz64(T0);
+}
+#endif
+
 /* shift right arithmetic helper */
 void do_sraw (void)
 {
@@ -594,16 +451,6 @@
 }
 #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;
@@ -611,7 +458,7 @@
 
     ret = 0;
     for (i = 0; i < 32; i += 8)
-        ret |= popcnt((T0 >> i) & 0xFF) << i;
+        ret |= ctpop8((T0 >> i) & 0xFF) << i;
     T0 = ret;
 }
 
@@ -623,13 +470,544 @@
 
     ret = 0;
     for (i = 0; i < 64; i += 8)
-        ret |= popcnt((T0 >> i) & 0xFF) << i;
+        ret |= ctpop8((T0 >> i) & 0xFF) << i;
     T0 = ret;
 }
 #endif
 
 /*****************************************************************************/
 /* Floating point operations helpers */
+static always_inline int fpisneg (float64 f)
+{
+    union {
+        float64 f;
+        uint64_t u;
+    } u;
+
+    u.f = f;
+
+    return u.u >> 63 != 0;
+}
+
+static always_inline int isden (float f)
+{
+    union {
+        float64 f;
+        uint64_t u;
+    } u;
+
+    u.f = f;
+
+    return ((u.u >> 52) & 0x7FF) == 0;
+}
+
+static always_inline int iszero (float64 f)
+{
+    union {
+        float64 f;
+        uint64_t u;
+    } u;
+
+    u.f = f;
+
+    return (u.u & ~0x8000000000000000ULL) == 0;
+}
+
+static always_inline int isinfinity (float64 f)
+{
+    union {
+        float64 f;
+        uint64_t u;
+    } u;
+
+    u.f = f;
+
+    return ((u.u >> 52) & 0x3FF) == 0x3FF &&
+        (u.u & 0x000FFFFFFFFFFFFFULL) == 0;
+}
+
+void do_compute_fprf (int set_fprf)
+{
+    int isneg;
+
+    isneg = fpisneg(FT0);
+    if (unlikely(float64_is_nan(FT0))) {
+        if (float64_is_signaling_nan(FT0)) {
+            /* Signaling NaN: flags are undefined */
+            T0 = 0x00;
+        } else {
+            /* Quiet NaN */
+            T0 = 0x11;
+        }
+    } else if (unlikely(isinfinity(FT0))) {
+        /* +/- infinity */
+        if (isneg)
+            T0 = 0x09;
+        else
+            T0 = 0x05;
+    } else {
+        if (iszero(FT0)) {
+            /* +/- zero */
+            if (isneg)
+                T0 = 0x12;
+            else
+                T0 = 0x02;
+        } else {
+            if (isden(FT0)) {
+                /* Denormalized numbers */
+                T0 = 0x10;
+            } else {
+                /* Normalized numbers */
+                T0 = 0x00;
+            }
+            if (isneg) {
+                T0 |= 0x08;
+            } else {
+                T0 |= 0x04;
+            }
+        }
+    }
+    if (set_fprf) {
+        /* We update FPSCR_FPRF */
+        env->fpscr &= ~(0x1F << FPSCR_FPRF);
+        env->fpscr |= T0 << FPSCR_FPRF;
+    }
+    /* We just need fpcc to update Rc1 */
+    T0 &= 0xF;
+}
+
+/* Floating-point invalid operations exception */
+static always_inline void fload_invalid_op_excp (int op)
+{
+    int ve;
+
+    ve = fpscr_ve;
+    if (op & POWERPC_EXCP_FP_VXSNAN) {
+        /* Operation on signaling NaN */
+        env->fpscr |= 1 << FPSCR_VXSNAN;
+    }
+    if (op & POWERPC_EXCP_FP_VXSOFT) {
+        /* Software-defined condition */
+        env->fpscr |= 1 << FPSCR_VXSOFT;
+    }
+    switch (op & ~(POWERPC_EXCP_FP_VXSOFT | POWERPC_EXCP_FP_VXSNAN)) {
+    case POWERPC_EXCP_FP_VXISI:
+        /* Magnitude subtraction of infinities */
+        env->fpscr |= 1 << FPSCR_VXISI;
+        goto update_arith;
+    case POWERPC_EXCP_FP_VXIDI:
+        /* Division of infinity by infinity */
+        env->fpscr |= 1 << FPSCR_VXIDI;
+        goto update_arith;
+    case POWERPC_EXCP_FP_VXZDZ:
+        /* Division of zero by zero */
+        env->fpscr |= 1 << FPSCR_VXZDZ;
+        goto update_arith;
+    case POWERPC_EXCP_FP_VXIMZ:
+        /* Multiplication of zero by infinity */
+        env->fpscr |= 1 << FPSCR_VXIMZ;
+        goto update_arith;
+    case POWERPC_EXCP_FP_VXVC:
+        /* Ordered comparison of NaN */
+        env->fpscr |= 1 << FPSCR_VXVC;
+        env->fpscr &= ~(0xF << FPSCR_FPCC);
+        env->fpscr |= 0x11 << FPSCR_FPCC;
+        /* We must update the target FPR before raising the exception */
+        if (ve != 0) {
+            env->exception_index = POWERPC_EXCP_PROGRAM;
+            env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
+            /* Update the floating-point enabled exception summary */
+            env->fpscr |= 1 << FPSCR_FEX;
+            /* Exception is differed */
+            ve = 0;
+        }
+        break;
+    case POWERPC_EXCP_FP_VXSQRT:
+        /* Square root of a negative number */
+        env->fpscr |= 1 << FPSCR_VXSQRT;
+    update_arith:
+        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
+        if (ve == 0) {
+            /* Set the result to quiet NaN */
+            FT0 = (uint64_t)-1;
+            env->fpscr &= ~(0xF << FPSCR_FPCC);
+            env->fpscr |= 0x11 << FPSCR_FPCC;
+        }
+        break;
+    case POWERPC_EXCP_FP_VXCVI:
+        /* Invalid conversion */
+        env->fpscr |= 1 << FPSCR_VXCVI;
+        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
+        if (ve == 0) {
+            /* Set the result to quiet NaN */
+            FT0 = (uint64_t)-1;
+            env->fpscr &= ~(0xF << FPSCR_FPCC);
+            env->fpscr |= 0x11 << FPSCR_FPCC;
+        }
+        break;
+    }
+    /* Update the floating-point invalid operation summary */
+    env->fpscr |= 1 << FPSCR_VX;
+    /* Update the floating-point exception summary */
+    env->fpscr |= 1 << FPSCR_FX;
+    if (ve != 0) {
+        /* Update the floating-point enabled exception summary */
+        env->fpscr |= 1 << FPSCR_FEX;
+        if (msr_fe0 != 0 || msr_fe1 != 0)
+            do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op);
+    }
+}
+
+static always_inline void float_zero_divide_excp (void)
+{
+    union {
+        float64 f;
+        uint64_t u;
+    } u0, u1;
+
+    env->fpscr |= 1 << FPSCR_ZX;
+    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
+    /* Update the floating-point exception summary */
+    env->fpscr |= 1 << FPSCR_FX;
+    if (fpscr_ze != 0) {
+        /* Update the floating-point enabled exception summary */
+        env->fpscr |= 1 << FPSCR_FEX;
+        if (msr_fe0 != 0 || msr_fe1 != 0) {
+            do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
+        }
+    } else {
+        /* Set the result to infinity */
+        u0.f = FT0;
+        u1.f = FT1;
+        u0.u = ((u0.u ^ u1.u) & 0x8000000000000000ULL);
+        u0.u |= 0x3FFULL << 52;
+        FT0 = u0.f;
+    }
+}
+
+static always_inline void float_overflow_excp (void)
+{
+    env->fpscr |= 1 << FPSCR_OX;
+    /* Update the floating-point exception summary */
+    env->fpscr |= 1 << FPSCR_FX;
+    if (fpscr_oe != 0) {
+        /* XXX: should adjust the result */
+        /* Update the floating-point enabled exception summary */
+        env->fpscr |= 1 << FPSCR_FEX;
+        /* We must update the target FPR before raising the exception */
+        env->exception_index = POWERPC_EXCP_PROGRAM;
+        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
+    } else {
+        env->fpscr |= 1 << FPSCR_XX;
+        env->fpscr |= 1 << FPSCR_FI;
+    }
+}
+
+static always_inline void float_underflow_excp (void)
+{
+    env->fpscr |= 1 << FPSCR_UX;
+    /* Update the floating-point exception summary */
+    env->fpscr |= 1 << FPSCR_FX;
+    if (fpscr_ue != 0) {
+        /* XXX: should adjust the result */
+        /* Update the floating-point enabled exception summary */
+        env->fpscr |= 1 << FPSCR_FEX;
+        /* We must update the target FPR before raising the exception */
+        env->exception_index = POWERPC_EXCP_PROGRAM;
+        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
+    }
+}
+
+static always_inline void float_inexact_excp (void)
+{
+    env->fpscr |= 1 << FPSCR_XX;
+    /* Update the floating-point exception summary */
+    env->fpscr |= 1 << FPSCR_FX;
+    if (fpscr_xe != 0) {
+        /* Update the floating-point enabled exception summary */
+        env->fpscr |= 1 << FPSCR_FEX;
+        /* We must update the target FPR before raising the exception */
+        env->exception_index = POWERPC_EXCP_PROGRAM;
+        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
+    }
+}
+
+static always_inline void fpscr_set_rounding_mode (void)
+{
+    int rnd_type;
+
+    /* Set rounding mode */
+    switch (fpscr_rn) {
+    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);
+}
+
+void do_fpscr_setbit (int bit)
+{
+    int prev;
+
+    prev = (env->fpscr >> bit) & 1;
+    env->fpscr |= 1 << bit;
+    if (prev == 0) {
+        switch (bit) {
+        case FPSCR_VX:
+            env->fpscr |= 1 << FPSCR_FX;
+            if (fpscr_ve)
+                goto raise_ve;
+        case FPSCR_OX:
+            env->fpscr |= 1 << FPSCR_FX;
+            if (fpscr_oe)
+                goto raise_oe;
+            break;
+        case FPSCR_UX:
+            env->fpscr |= 1 << FPSCR_FX;
+            if (fpscr_ue)
+                goto raise_ue;
+            break;
+        case FPSCR_ZX:
+            env->fpscr |= 1 << FPSCR_FX;
+            if (fpscr_ze)
+                goto raise_ze;
+            break;
+        case FPSCR_XX:
+            env->fpscr |= 1 << FPSCR_FX;
+            if (fpscr_xe)
+                goto raise_xe;
+            break;
+        case FPSCR_VXSNAN:
+        case FPSCR_VXISI:
+        case FPSCR_VXIDI:
+        case FPSCR_VXZDZ:
+        case FPSCR_VXIMZ:
+        case FPSCR_VXVC:
+        case FPSCR_VXSOFT:
+        case FPSCR_VXSQRT:
+        case FPSCR_VXCVI:
+            env->fpscr |= 1 << FPSCR_VX;
+            env->fpscr |= 1 << FPSCR_FX;
+            if (fpscr_ve != 0)
+                goto raise_ve;
+            break;
+        case FPSCR_VE:
+            if (fpscr_vx != 0) {
+            raise_ve:
+                env->error_code = POWERPC_EXCP_FP;
+                if (fpscr_vxsnan)
+                    env->error_code |= POWERPC_EXCP_FP_VXSNAN;
+                if (fpscr_vxisi)
+                    env->error_code |= POWERPC_EXCP_FP_VXISI;
+                if (fpscr_vxidi)
+                    env->error_code |= POWERPC_EXCP_FP_VXIDI;
+                if (fpscr_vxzdz)
+                    env->error_code |= POWERPC_EXCP_FP_VXZDZ;
+                if (fpscr_vximz)
+                    env->error_code |= POWERPC_EXCP_FP_VXIMZ;
+                if (fpscr_vxvc)
+                    env->error_code |= POWERPC_EXCP_FP_VXVC;
+                if (fpscr_vxsoft)
+                    env->error_code |= POWERPC_EXCP_FP_VXSOFT;
+                if (fpscr_vxsqrt)
+                    env->error_code |= POWERPC_EXCP_FP_VXSQRT;
+                if (fpscr_vxcvi)
+                    env->error_code |= POWERPC_EXCP_FP_VXCVI;
+                goto raise_excp;
+            }
+            break;
+        case FPSCR_OE:
+            if (fpscr_ox != 0) {
+            raise_oe:
+                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
+                goto raise_excp;
+            }
+            break;
+        case FPSCR_UE:
+            if (fpscr_ux != 0) {
+            raise_ue:
+                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
+                goto raise_excp;
+            }
+            break;
+        case FPSCR_ZE:
+            if (fpscr_zx != 0) {
+            raise_ze:
+                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX;
+                goto raise_excp;
+            }
+            break;
+        case FPSCR_XE:
+            if (fpscr_xx != 0) {
+            raise_xe:
+                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
+                goto raise_excp;
+            }
+            break;
+        case FPSCR_RN1:
+        case FPSCR_RN:
+            fpscr_set_rounding_mode();
+            break;
+        default:
+            break;
+        raise_excp:
+            /* Update the floating-point enabled exception summary */
+            env->fpscr |= 1 << FPSCR_FEX;
+                /* We have to update Rc1 before raising the exception */
+            env->exception_index = POWERPC_EXCP_PROGRAM;
+            break;
+        }
+    }
+}
+
+#if defined(WORDS_BIGENDIAN)
+#define WORD0 0
+#define WORD1 1
+#else
+#define WORD0 1
+#define WORD1 0
+#endif
+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;
+    uint32_t prev, new;
+    int i;
+
+    u.d = FT0;
+    prev = env->fpscr;
+    new = u.s.u[WORD1];
+    new &= ~0x90000000;
+    new |= prev & 0x90000000;
+    for (i = 0; i < 7; i++) {
+        if (mask & (1 << i)) {
+            env->fpscr &= ~(0xF << (4 * i));
+            env->fpscr |= new & (0xF << (4 * i));
+        }
+    }
+    /* Update VX and FEX */
+    if (fpscr_ix != 0)
+        env->fpscr |= 1 << FPSCR_VX;
+    if ((fpscr_ex & fpscr_eex) != 0) {
+        env->fpscr |= 1 << FPSCR_FEX;
+        env->exception_index = POWERPC_EXCP_PROGRAM;
+        /* XXX: we should compute it properly */
+        env->error_code = POWERPC_EXCP_FP;
+    }
+    fpscr_set_rounding_mode();
+}
+#undef WORD0
+#undef WORD1
+
+#ifdef CONFIG_SOFTFLOAT
+void do_float_check_status (void)
+{
+    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
+        (env->error_code & POWERPC_EXCP_FP)) {
+        /* Differred floating-point exception after target FPR update */
+        if (msr_fe0 != 0 || msr_fe1 != 0)
+            do_raise_exception_err(env->exception_index, env->error_code);
+    } else if (env->fp_status.float_exception_flags & float_flag_overflow) {
+        float_overflow_excp();
+    } else if (env->fp_status.float_exception_flags & float_flag_underflow) {
+        float_underflow_excp();
+    } else if (env->fp_status.float_exception_flags & float_flag_inexact) {
+        float_inexact_excp();
+    }
+}
+#endif
+
+#if USE_PRECISE_EMULATION
+void do_fadd (void)
+{
+    if (unlikely(float64_is_signaling_nan(FT0) ||
+                 float64_is_signaling_nan(FT1))) {
+        /* sNaN addition */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else if (likely(isfinite(FT0) || isfinite(FT1) ||
+                      fpisneg(FT0) == fpisneg(FT1))) {
+        FT0 = float64_add(FT0, FT1, &env->fp_status);
+    } else {
+        /* Magnitude subtraction of infinities */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
+    }
+}
+
+void do_fsub (void)
+{
+    if (unlikely(float64_is_signaling_nan(FT0) ||
+                 float64_is_signaling_nan(FT1))) {
+        /* sNaN subtraction */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else if (likely(isfinite(FT0) || isfinite(FT1) ||
+                      fpisneg(FT0) != fpisneg(FT1))) {
+        FT0 = float64_sub(FT0, FT1, &env->fp_status);
+    } else {
+        /* Magnitude subtraction of infinities */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
+    }
+}
+
+void do_fmul (void)
+{
+    if (unlikely(float64_is_signaling_nan(FT0) ||
+                 float64_is_signaling_nan(FT1))) {
+        /* sNaN multiplication */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else if (unlikely((isinfinity(FT0) && iszero(FT1)) ||
+                        (iszero(FT0) && isinfinity(FT1)))) {
+        /* Multiplication of zero by infinity */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
+    } else {
+        FT0 = float64_mul(FT0, FT1, &env->fp_status);
+    }
+}
+
+void do_fdiv (void)
+{
+    if (unlikely(float64_is_signaling_nan(FT0) ||
+                 float64_is_signaling_nan(FT1))) {
+        /* sNaN division */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else if (unlikely(isinfinity(FT0) && isinfinity(FT1))) {
+        /* Division of infinity by infinity */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
+    } else if (unlikely(iszero(FT1))) {
+        if (iszero(FT0)) {
+            /* Division of zero by zero */
+            fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
+        } else {
+            /* Division by zero */
+            float_zero_divide_excp();
+        }
+    } else {
+        FT0 = float64_div(FT0, FT1, &env->fp_status);
+    }
+}
+#endif /* USE_PRECISE_EMULATION */
+
 void do_fctiw (void)
 {
     union {
@@ -637,14 +1015,22 @@
         uint64_t i;
     } p;
 
-    p.i = float64_to_int32(FT0, &env->fp_status);
+    if (unlikely(float64_is_signaling_nan(FT0))) {
+        /* sNaN conversion */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
+    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
+        /* qNan / infinity conversion */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
+    } else {
+        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)
-     */
-    p.i |= 0xFFF80000ULL << 32;
+        /* XXX: higher bits are not supposed to be significant.
+         *     to make tests easier, return the same as a real PowerPC 750
+         */
+        p.i |= 0xFFF80000ULL << 32;
 #endif
-    FT0 = p.d;
+        FT0 = p.d;
+    }
 }
 
 void do_fctiwz (void)
@@ -654,14 +1040,22 @@
         uint64_t i;
     } p;
 
-    p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);
+    if (unlikely(float64_is_signaling_nan(FT0))) {
+        /* sNaN conversion */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
+    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
+        /* qNan / infinity conversion */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
+    } else {
+        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)
-     */
-    p.i |= 0xFFF80000ULL << 32;
+        /* XXX: higher bits are not supposed to be significant.
+         *     to make tests easier, return the same as a real PowerPC 750
+         */
+        p.i |= 0xFFF80000ULL << 32;
 #endif
-    FT0 = p.d;
+        FT0 = p.d;
+    }
 }
 
 #if defined(TARGET_PPC64)
@@ -683,8 +1077,16 @@
         uint64_t i;
     } p;
 
-    p.i = float64_to_int64(FT0, &env->fp_status);
-    FT0 = p.d;
+    if (unlikely(float64_is_signaling_nan(FT0))) {
+        /* sNaN conversion */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
+    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
+        /* qNan / infinity conversion */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
+    } else {
+        p.i = float64_to_int64(FT0, &env->fp_status);
+        FT0 = p.d;
+    }
 }
 
 void do_fctidz (void)
@@ -694,101 +1096,229 @@
         uint64_t i;
     } p;
 
-    p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status);
-    FT0 = p.d;
+    if (unlikely(float64_is_signaling_nan(FT0))) {
+        /* sNaN conversion */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
+    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
+        /* qNan / infinity conversion */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
+    } else {
+        p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status);
+        FT0 = p.d;
+    }
 }
 
 #endif
 
+static always_inline void do_fri (int rounding_mode)
+{
+    if (unlikely(float64_is_signaling_nan(FT0))) {
+        /* sNaN round */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
+    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
+        /* qNan / infinity round */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
+    } else {
+        set_float_rounding_mode(rounding_mode, &env->fp_status);
+        FT0 = float64_round_to_int(FT0, &env->fp_status);
+        /* Restore rounding mode from FPSCR */
+        fpscr_set_rounding_mode();
+    }
+}
+
+void do_frin (void)
+{
+    do_fri(float_round_nearest_even);
+}
+
+void do_friz (void)
+{
+    do_fri(float_round_to_zero);
+}
+
+void do_frip (void)
+{
+    do_fri(float_round_up);
+}
+
+void do_frim (void)
+{
+    do_fri(float_round_down);
+}
+
 #if USE_PRECISE_EMULATION
 void do_fmadd (void)
 {
+    if (unlikely(float64_is_signaling_nan(FT0) ||
+                 float64_is_signaling_nan(FT1) ||
+                 float64_is_signaling_nan(FT2))) {
+        /* sNaN operation */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else {
 #ifdef FLOAT128
-    float128 ft0_128, ft1_128;
+        /* This is the way the PowerPC specification defines it */
+        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);
+        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;
+        /* This is OK on x86 hosts */
+        FT0 = (FT0 * FT1) + FT2;
 #endif
+    }
 }
 
 void do_fmsub (void)
 {
+    if (unlikely(float64_is_signaling_nan(FT0) ||
+                 float64_is_signaling_nan(FT1) ||
+                 float64_is_signaling_nan(FT2))) {
+        /* sNaN operation */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else {
 #ifdef FLOAT128
-    float128 ft0_128, ft1_128;
+        /* This is the way the PowerPC specification defines it */
+        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);
+        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;
+        /* This is OK on x86 hosts */
+        FT0 = (FT0 * FT1) - FT2;
 #endif
+    }
 }
 #endif /* USE_PRECISE_EMULATION */
 
 void do_fnmadd (void)
 {
+    if (unlikely(float64_is_signaling_nan(FT0) ||
+                 float64_is_signaling_nan(FT1) ||
+                 float64_is_signaling_nan(FT2))) {
+        /* sNaN operation */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else {
 #if USE_PRECISE_EMULATION
 #ifdef FLOAT128
-    float128 ft0_128, ft1_128;
+        /* This is the way the PowerPC specification defines it */
+        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);
+        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;
+        /* 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);
+        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);
+        if (likely(!isnan(FT0)))
+            FT0 = float64_chs(FT0);
+    }
 }
 
 void do_fnmsub (void)
 {
+    if (unlikely(float64_is_signaling_nan(FT0) ||
+                 float64_is_signaling_nan(FT1) ||
+                 float64_is_signaling_nan(FT2))) {
+        /* sNaN operation */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else {
 #if USE_PRECISE_EMULATION
 #ifdef FLOAT128
-    float128 ft0_128, ft1_128;
+        /* This is the way the PowerPC specification defines it */
+        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);
+        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;
+        /* 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);
+        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);
+        if (likely(!isnan(FT0)))
+            FT0 = float64_chs(FT0);
+    }
 }
 
+#if USE_PRECISE_EMULATION
+void do_frsp (void)
+{
+    if (unlikely(float64_is_signaling_nan(FT0))) {
+        /* sNaN square root */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else {
+        FT0 = float64_to_float32(FT0, &env->fp_status);
+    }
+}
+#endif /* USE_PRECISE_EMULATION */
+
 void do_fsqrt (void)
 {
-    FT0 = float64_sqrt(FT0, &env->fp_status);
+    if (unlikely(float64_is_signaling_nan(FT0))) {
+        /* sNaN square root */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
+        /* Square root of a negative nonzero number */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
+    } else {
+        FT0 = float64_sqrt(FT0, &env->fp_status);
+    }
 }
 
+void do_fre (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    if (unlikely(float64_is_signaling_nan(FT0))) {
+        /* sNaN reciprocal */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else if (unlikely(iszero(FT0))) {
+        /* Zero reciprocal */
+        float_zero_divide_excp();
+    } else if (likely(isnormal(FT0))) {
+        FT0 = float64_div(1.0, FT0, &env->fp_status);
+    } else {
+        p.d = FT0;
+        if (p.i == 0x8000000000000000ULL) {
+            p.i = 0xFFF0000000000000ULL;
+        } else if (p.i == 0x0000000000000000ULL) {
+            p.i = 0x7FF0000000000000ULL;
+        } else if (isnan(FT0)) {
+            p.i = 0x7FF8000000000000ULL;
+        } else if (fpisneg(FT0)) {
+            p.i = 0x8000000000000000ULL;
+        } else {
+            p.i = 0x0000000000000000ULL;
+        }
+        FT0 = p.d;
+    }
+}
+
 void do_fres (void)
 {
     union {
@@ -796,7 +1326,13 @@
         uint64_t i;
     } p;
 
-    if (likely(isnormal(FT0))) {
+    if (unlikely(float64_is_signaling_nan(FT0))) {
+        /* sNaN reciprocal */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else if (unlikely(iszero(FT0))) {
+        /* Zero reciprocal */
+        float_zero_divide_excp();
+    } else if (likely(isnormal(FT0))) {
 #if USE_PRECISE_EMULATION
         FT0 = float64_div(1.0, FT0, &env->fp_status);
         FT0 = float64_to_float32(FT0, &env->fp_status);
@@ -811,7 +1347,7 @@
             p.i = 0x7FF0000000000000ULL;
         } else if (isnan(FT0)) {
             p.i = 0x7FF8000000000000ULL;
-        } else if (FT0 < 0.0) {
+        } else if (fpisneg(FT0)) {
             p.i = 0x8000000000000000ULL;
         } else {
             p.i = 0x0000000000000000ULL;
@@ -827,7 +1363,13 @@
         uint64_t i;
     } p;
 
-    if (likely(isnormal(FT0) && FT0 > 0.0)) {
+    if (unlikely(float64_is_signaling_nan(FT0))) {
+        /* sNaN reciprocal square root */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
+        /* Reciprocal square root of a negative nonzero number */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
+    } else if (likely(isnormal(FT0))) {
         FT0 = float64_sqrt(FT0, &env->fp_status);
         FT0 = float32_div(1.0, FT0, &env->fp_status);
     } else {
@@ -837,9 +1379,8 @@
         } else if (p.i == 0x0000000000000000ULL) {
             p.i = 0x7FF0000000000000ULL;
         } else if (isnan(FT0)) {
-            if (!(p.i & 0x0008000000000000ULL))
-                p.i |= 0x000FFFFFFFFFFFFFULL;
-        } else if (FT0 < 0) {
+            p.i |= 0x000FFFFFFFFFFFFFULL;
+        } else if (fpisneg(FT0)) {
             p.i = 0x7FF8000000000000ULL;
         } else {
             p.i = 0x0000000000000000ULL;
@@ -850,7 +1391,7 @@
 
 void do_fsel (void)
 {
-    if (FT0 >= 0)
+    if (!fpisneg(FT0) || iszero(FT0))
         FT0 = FT1;
     else
         FT0 = FT2;
@@ -858,7 +1399,11 @@
 
 void do_fcmpu (void)
 {
-    if (likely(!isnan(FT0) && !isnan(FT1))) {
+    if (unlikely(float64_is_signaling_nan(FT0) ||
+                 float64_is_signaling_nan(FT1))) {
+        /* sNaN comparison */
+        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+    } else {
         if (float64_lt(FT0, FT1, &env->fp_status)) {
             T0 = 0x08UL;
         } else if (!float64_le(FT0, FT1, &env->fp_status)) {
@@ -866,18 +1411,25 @@
         } else {
             T0 = 0x02UL;
         }
-    } else {
-        T0 = 0x01UL;
-        env->fpscr[4] |= 0x1;
-        env->fpscr[6] |= 0x1;
     }
-    env->fpscr[3] = T0;
+    env->fpscr &= ~(0x0F << FPSCR_FPRF);
+    env->fpscr |= T0 << FPSCR_FPRF;
 }
 
 void do_fcmpo (void)
 {
-    env->fpscr[4] &= ~0x1;
-    if (likely(!isnan(FT0) && !isnan(FT1))) {
+    if (unlikely(float64_is_nan(FT0) ||
+                 float64_is_nan(FT1))) {
+        if (float64_is_signaling_nan(FT0) ||
+            float64_is_signaling_nan(FT1)) {
+            /* sNaN comparison */
+            fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
+                                  POWERPC_EXCP_FP_VXVC);
+        } else {
+            /* qNaN comparison */
+            fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
+        }
+    } else {
         if (float64_lt(FT0, FT1, &env->fp_status)) {
             T0 = 0x08UL;
         } else if (!float64_le(FT0, FT1, &env->fp_status)) {
@@ -885,57 +1437,70 @@
         } else {
             T0 = 0x02UL;
         }
-    } else {
-        T0 = 0x01UL;
-        env->fpscr[4] |= 0x1;
-        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;
-        } else {
-            env->fpscr[4] |= 0x8;
-        }
     }
-    env->fpscr[3] = T0;
+    env->fpscr &= ~(0x0F << FPSCR_FPRF);
+    env->fpscr |= T0 << FPSCR_FPRF;
 }
 
 #if !defined (CONFIG_USER_ONLY)
 void cpu_dump_rfi (target_ulong RA, target_ulong msr);
-void do_rfi (void)
+
+void do_store_msr (void)
 {
+    T0 = hreg_store_msr(env, T0);
+    if (T0 != 0) {
+        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+        do_raise_exception(T0);
+    }
+}
+
+static always_inline void __do_rfi (target_ulong nip, target_ulong msr,
+                                    target_ulong msrm, int keep_msrh)
+{
 #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));
+    if (msr & (1ULL << MSR_SF)) {
+        nip = (uint64_t)nip;
+        msr &= (uint64_t)msrm;
     } else {
-        env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
-        ppc_store_msr_32(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+        nip = (uint32_t)nip;
+        msr = (uint32_t)(msr & msrm);
+        if (keep_msrh)
+            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
     }
 #else
-    env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
-    do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+    nip = (uint32_t)nip;
+    msr &= (uint32_t)msrm;
 #endif
+    /* XXX: beware: this is false if VLE is supported */
+    env->nip = nip & ~((target_ulong)0x00000003);
+    hreg_store_msr(env, msr);
 #if defined (DEBUG_OP)
-    cpu_dump_rfi(env->nip, do_load_msr(env));
+    cpu_dump_rfi(env->nip, env->msr);
 #endif
+    /* No need to raise an exception here,
+     * as rfi is always the last insn of a TB
+     */
     env->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
+void do_rfi (void)
+{
+    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
+             ~((target_ulong)0xFFFF0000), 1);
+}
+
 #if defined(TARGET_PPC64)
 void do_rfid (void)
 {
-    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));
+    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
+             ~((target_ulong)0xFFFF0000), 0);
+}
 #endif
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+#if defined(TARGET_PPC64H)
+void do_hrfid (void)
+{
+    __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
+             ~((target_ulong)0xFFFF0000), 0);
 }
 #endif
 #endif
@@ -947,7 +1512,7 @@
                   ((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);
+        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
     }
 }
 
@@ -959,7 +1524,7 @@
                   ((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);
+        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
 }
 #endif
 
@@ -982,21 +1547,21 @@
     switch (T0) {
     case 0x0CUL:
         /* Instruction cache line size */
-        T0 = ICACHE_LINE_SIZE;
+        T0 = env->icache_line_size;
         break;
     case 0x0DUL:
         /* Data cache line size */
-        T0 = DCACHE_LINE_SIZE;
+        T0 = env->dcache_line_size;
         break;
     case 0x0EUL:
         /* Minimum cache line size */
-        T0 = ICACHE_LINE_SIZE < DCACHE_LINE_SIZE ?
-            ICACHE_LINE_SIZE : DCACHE_LINE_SIZE;
+        T0 = env->icache_line_size < env->dcache_line_size ?
+            env->icache_line_size : env->dcache_line_size;
         break;
     case 0x0FUL:
         /* Maximum cache line size */
-        T0 = ICACHE_LINE_SIZE > DCACHE_LINE_SIZE ?
-            ICACHE_LINE_SIZE : DCACHE_LINE_SIZE;
+        T0 = env->icache_line_size > env->dcache_line_size ?
+            env->icache_line_size : env->dcache_line_size;
         break;
     default:
         /* Undefined */
@@ -1130,13 +1695,7 @@
 
 void do_POWER_rfsvc (void)
 {
-    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;
+    __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
 }
 
 /* PowerPC 601 BAT management helper */
@@ -1206,68 +1765,7 @@
     }
 }
 
-#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;
-}
-
+/* XXX: to be improved to check access rights when in user-mode */
 void do_load_dcr (void)
 {
     target_ulong val;
@@ -1276,12 +1774,14 @@
         if (loglevel != 0) {
             fprintf(logfile, "No DCR environment\n");
         }
-        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
+        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                               POWERPC_EXCP_INVAL | POWERPC_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);
+        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
     } else {
         T0 = val;
     }
@@ -1293,15 +1793,42 @@
         if (loglevel != 0) {
             fprintf(logfile, "No DCR environment\n");
         }
-        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
+        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                               POWERPC_EXCP_INVAL | POWERPC_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);
+        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
     }
 }
 
+#if !defined(CONFIG_USER_ONLY)
+void do_40x_rfci (void)
+{
+    __do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
+             ~((target_ulong)0xFFFF0000), 0);
+}
+
+void do_rfci (void)
+{
+    __do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
+             ~((target_ulong)0x3FFF0000), 0);
+}
+
+void do_rfdi (void)
+{
+    __do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
+             ~((target_ulong)0x3FFF0000), 0);
+}
+
+void do_rfmci (void)
+{
+    __do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
+             ~((target_ulong)0x3FFF0000), 0);
+}
+
 void do_load_403_pb (int num)
 {
     T0 = env->pb[num];
@@ -1346,12 +1873,12 @@
     0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
 };
 
-static inline uint8_t byte_reverse (uint8_t val)
+static always_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)
+static always_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);
@@ -1384,7 +1911,7 @@
 }
 
 /* Fixed-point vector arithmetic */
-static inline uint32_t _do_eabs (uint32_t val)
+static always_inline uint32_t _do_eabs (uint32_t val)
 {
     if (val != 0x80000000)
         val &= ~0x80000000;
@@ -1392,25 +1919,25 @@
     return val;
 }
 
-static inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
+static always_inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
 {
     return op1 + op2;
 }
 
-static inline int _do_ecntlsw (uint32_t val)
+static always_inline int _do_ecntlsw (uint32_t val)
 {
     if (val & 0x80000000)
-        return _do_cntlzw(~val);
+        return clz32(~val);
     else
-        return _do_cntlzw(val);
+        return clz32(val);
 }
 
-static inline int _do_ecntlzw (uint32_t val)
+static always_inline int _do_ecntlzw (uint32_t val)
 {
-    return _do_cntlzw(val);
+    return clz32(val);
 }
 
-static inline uint32_t _do_eneg (uint32_t val)
+static always_inline uint32_t _do_eneg (uint32_t val)
 {
     if (val != 0x80000000)
         val ^= 0x80000000;
@@ -1418,35 +1945,35 @@
     return val;
 }
 
-static inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
+static always_inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
 {
     return rotl32(op1, op2);
 }
 
-static inline uint32_t _do_erndw (uint32_t val)
+static always_inline uint32_t _do_erndw (uint32_t val)
 {
     return (val + 0x000080000000) & 0xFFFF0000;
 }
 
-static inline uint32_t _do_eslw (uint32_t op1, uint32_t op2)
+static always_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)
+static always_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)
+static always_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)
+static always_inline uint32_t _do_esubfw (uint32_t op1, uint32_t op2)
 {
     return op2 - op1;
 }
@@ -1475,7 +2002,7 @@
 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)
+static always_inline uint32_t _do_esel (uint32_t op1, uint32_t op2, int n)
 {
     if (n)
         return op1;
@@ -1498,31 +2025,31 @@
                          _do_e##name(T0_64, T1_64));                          \
 }
 
-static inline uint32_t _do_evcmp_merge (int t0, int t1)
+static always_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)
+static always_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)
+static always_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)
+static always_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)
+static always_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)
+static always_inline int _do_ecmpltu (uint32_t op1, uint32_t op2)
 {
     return op1 < op2 ? 1 : 0;
 }
@@ -1539,7 +2066,7 @@
 DO_SPE_CMP(cmpltu);
 
 /* Single precision floating-point conversions from/to integer */
-static inline uint32_t _do_efscfsi (int32_t val)
+static always_inline uint32_t _do_efscfsi (int32_t val)
 {
     union {
         uint32_t u;
@@ -1551,7 +2078,7 @@
     return u.u;
 }
 
-static inline uint32_t _do_efscfui (uint32_t val)
+static always_inline uint32_t _do_efscfui (uint32_t val)
 {
     union {
         uint32_t u;
@@ -1563,7 +2090,7 @@
     return u.u;
 }
 
-static inline int32_t _do_efsctsi (uint32_t val)
+static always_inline int32_t _do_efsctsi (uint32_t val)
 {
     union {
         int32_t u;
@@ -1578,7 +2105,7 @@
     return float32_to_int32(u.f, &env->spe_status);
 }
 
-static inline uint32_t _do_efsctui (uint32_t val)
+static always_inline uint32_t _do_efsctui (uint32_t val)
 {
     union {
         int32_t u;
@@ -1593,7 +2120,7 @@
     return float32_to_uint32(u.f, &env->spe_status);
 }
 
-static inline int32_t _do_efsctsiz (uint32_t val)
+static always_inline int32_t _do_efsctsiz (uint32_t val)
 {
     union {
         int32_t u;
@@ -1608,7 +2135,7 @@
     return float32_to_int32_round_to_zero(u.f, &env->spe_status);
 }
 
-static inline uint32_t _do_efsctuiz (uint32_t val)
+static always_inline uint32_t _do_efsctuiz (uint32_t val)
 {
     union {
         int32_t u;
@@ -1654,7 +2181,7 @@
 }
 
 /* Single precision floating-point conversion to/from fractional */
-static inline uint32_t _do_efscfsf (uint32_t val)
+static always_inline uint32_t _do_efscfsf (uint32_t val)
 {
     union {
         uint32_t u;
@@ -1669,7 +2196,7 @@
     return u.u;
 }
 
-static inline uint32_t _do_efscfuf (uint32_t val)
+static always_inline uint32_t _do_efscfuf (uint32_t val)
 {
     union {
         uint32_t u;
@@ -1684,7 +2211,7 @@
     return u.u;
 }
 
-static inline int32_t _do_efsctsf (uint32_t val)
+static always_inline int32_t _do_efsctsf (uint32_t val)
 {
     union {
         int32_t u;
@@ -1702,7 +2229,7 @@
     return float32_to_int32(u.f, &env->spe_status);
 }
 
-static inline uint32_t _do_efsctuf (uint32_t val)
+static always_inline uint32_t _do_efsctuf (uint32_t val)
 {
     union {
         int32_t u;
@@ -1720,7 +2247,7 @@
     return float32_to_uint32(u.f, &env->spe_status);
 }
 
-static inline int32_t _do_efsctsfz (uint32_t val)
+static always_inline int32_t _do_efsctsfz (uint32_t val)
 {
     union {
         int32_t u;
@@ -1738,7 +2265,7 @@
     return float32_to_int32_round_to_zero(u.f, &env->spe_status);
 }
 
-static inline uint32_t _do_efsctufz (uint32_t val)
+static always_inline uint32_t _do_efsctufz (uint32_t val)
 {
     union {
         int32_t u;
@@ -1787,19 +2314,19 @@
 }
 
 /* Double precision floating point helpers */
-static inline int _do_efdcmplt (uint64_t op1, uint64_t op2)
+static always_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)
+static always_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)
+static always_inline int _do_efdcmpeq (uint64_t op1, uint64_t op2)
 {
     /* XXX: TODO: test special values (NaN, infinites, ...) */
     return _do_efdtsteq(op1, op2);
@@ -1821,7 +2348,7 @@
 }
 
 /* Double precision floating-point conversion to/from integer */
-static inline uint64_t _do_efdcfsi (int64_t val)
+static always_inline uint64_t _do_efdcfsi (int64_t val)
 {
     union {
         uint64_t u;
@@ -1833,7 +2360,7 @@
     return u.u;
 }
 
-static inline uint64_t _do_efdcfui (uint64_t val)
+static always_inline uint64_t _do_efdcfui (uint64_t val)
 {
     union {
         uint64_t u;
@@ -1845,7 +2372,7 @@
     return u.u;
 }
 
-static inline int64_t _do_efdctsi (uint64_t val)
+static always_inline int64_t _do_efdctsi (uint64_t val)
 {
     union {
         int64_t u;
@@ -1860,7 +2387,7 @@
     return float64_to_int64(u.f, &env->spe_status);
 }
 
-static inline uint64_t _do_efdctui (uint64_t val)
+static always_inline uint64_t _do_efdctui (uint64_t val)
 {
     union {
         int64_t u;
@@ -1875,7 +2402,7 @@
     return float64_to_uint64(u.f, &env->spe_status);
 }
 
-static inline int64_t _do_efdctsiz (uint64_t val)
+static always_inline int64_t _do_efdctsiz (uint64_t val)
 {
     union {
         int64_t u;
@@ -1890,7 +2417,7 @@
     return float64_to_int64_round_to_zero(u.f, &env->spe_status);
 }
 
-static inline uint64_t _do_efdctuiz (uint64_t val)
+static always_inline uint64_t _do_efdctuiz (uint64_t val)
 {
     union {
         int64_t u;
@@ -1936,7 +2463,7 @@
 }
 
 /* Double precision floating-point conversion to/from fractional */
-static inline uint64_t _do_efdcfsf (int64_t val)
+static always_inline uint64_t _do_efdcfsf (int64_t val)
 {
     union {
         uint64_t u;
@@ -1951,7 +2478,7 @@
     return u.u;
 }
 
-static inline uint64_t _do_efdcfuf (uint64_t val)
+static always_inline uint64_t _do_efdcfuf (uint64_t val)
 {
     union {
         uint64_t u;
@@ -1966,7 +2493,7 @@
     return u.u;
 }
 
-static inline int64_t _do_efdctsf (uint64_t val)
+static always_inline int64_t _do_efdctsf (uint64_t val)
 {
     union {
         int64_t u;
@@ -1984,7 +2511,7 @@
     return float64_to_int32(u.f, &env->spe_status);
 }
 
-static inline uint64_t _do_efdctuf (uint64_t val)
+static always_inline uint64_t _do_efdctuf (uint64_t val)
 {
     union {
         int64_t u;
@@ -2002,7 +2529,7 @@
     return float64_to_uint32(u.f, &env->spe_status);
 }
 
-static inline int64_t _do_efdctsfz (uint64_t val)
+static always_inline int64_t _do_efdctsfz (uint64_t val)
 {
     union {
         int64_t u;
@@ -2020,7 +2547,7 @@
     return float64_to_int32_round_to_zero(u.f, &env->spe_status);
 }
 
-static inline uint64_t _do_efdctufz (uint64_t val)
+static always_inline uint64_t _do_efdctufz (uint64_t val)
 {
     union {
         int64_t u;
@@ -2069,7 +2596,7 @@
 }
 
 /* Floating point conversion between single and double precision */
-static inline uint32_t _do_efscfd (uint64_t val)
+static always_inline uint32_t _do_efscfd (uint64_t val)
 {
     union {
         uint64_t u;
@@ -2086,7 +2613,7 @@
     return u2.u;
 }
 
-static inline uint64_t _do_efdcfs (uint32_t val)
+static always_inline uint64_t _do_efdcfs (uint32_t val)
 {
     union {
         uint64_t u;
@@ -2130,19 +2657,19 @@
 DO_SPE_OP2(fsdiv);
 
 /* Single-precision floating-point comparisons */
-static inline int _do_efscmplt (uint32_t op1, uint32_t op2)
+static always_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)
+static always_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)
+static always_inline int _do_efscmpeq (uint32_t op1, uint32_t op2)
 {
     /* XXX: TODO: test special values (NaN, infinites, ...) */
     return _do_efststeq(op1, op2);
@@ -2205,7 +2732,11 @@
 #if !defined (CONFIG_USER_ONLY)
 
 #define MMUSUFFIX _mmu
-#define GETPC() (__builtin_return_address(0))
+#ifdef __s390__
+# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
+#else
+# define GETPC() (__builtin_return_address(0))
+#endif
 
 #define SHIFT 0
 #include "softmmu_template.h"
@@ -2223,7 +2754,7 @@
    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)
+void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 {
     TranslationBlock *tb;
     CPUState *saved_env;
@@ -2234,11 +2765,11 @@
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, is_user, 1);
+    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
     if (unlikely(ret != 0)) {
         if (likely(retaddr)) {
             /* now we have a real cpu fault */
-            pc = (target_phys_addr_t)retaddr;
+            pc = (target_phys_addr_t)(unsigned long)retaddr;
             tb = tb_find_pc(pc);
             if (likely(tb)) {
                 /* the PC is inside the translated code. It means that we have
@@ -2251,120 +2782,6 @@
     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)
@@ -2393,12 +2810,33 @@
                      way, is_code, CMP, RPN);
 }
 
-static target_ulong booke_tlb_to_page_size (int size)
+void do_load_74xx_tlb (int is_code)
 {
+    target_ulong RPN, CMP, EPN;
+    int way;
+
+    RPN = env->spr[SPR_PTELO];
+    CMP = env->spr[SPR_PTEHI];
+    EPN = env->spr[SPR_TLBMISS] & ~0x3;
+    way = env->spr[SPR_TLBMISS] & 0x3;
+#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 always_inline target_ulong booke_tlb_to_page_size (int size)
+{
     return 1024 << (2 * size);
 }
 
-static int booke_page_size_to_tlb (target_ulong page_size)
+static always_inline int booke_page_size_to_tlb (target_ulong page_size)
 {
     int size;
 
@@ -2492,21 +2930,6 @@
         T0 |= 0x100;
 }
 
-void do_4xx_tlbsx (void)
-{
-    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]);
-}
-
-void do_4xx_tlbsx_ (void)
-{
-    int tmp = xer_so;
-
-    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]);
-    if (T0 != -1)
-        tmp |= 0x02;
-    env->crf[0] = tmp;
-}
-
 void do_4xx_tlbwe_hi (void)
 {
     ppcemb_tlb_t *tlb;
@@ -2541,7 +2964,7 @@
                   "are not supported (%d)\n",
                   tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
     }
-    tlb->EPN = (T1 & 0xFFFFFC00) & ~(tlb->size - 1);
+    tlb->EPN = T1 & ~(tlb->size - 1);
     if (T1 & 0x40)
         tlb->prot |= PAGE_VALID;
     else
@@ -2607,150 +3030,114 @@
 #endif
 }
 
-/* BookE TLB management */
-void do_booke_tlbwe0 (void)
+/* PowerPC 440 TLB management */
+void do_440_tlbwe (int word)
 {
     ppcemb_tlb_t *tlb;
-    target_ulong EPN, size;
+    target_ulong EPN, RPN, size;
     int do_flush_tlbs;
 
 #if defined (DEBUG_SOFTWARE_TLB)
     if (loglevel != 0) {
-        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
+        fprintf(logfile, "%s word %d T0 " REGX " T1 " REGX "\n",
+                __func__, word, T0, T1);
     }
 #endif
     do_flush_tlbs = 0;
     T0 &= 0x3F;
     tlb = &env->tlb[T0].tlbe;
-    EPN = T1 & 0xFFFFFC00;
-    if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
-        do_flush_tlbs = 1;
-    tlb->EPN = EPN;
-    size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
-    if ((tlb->prot & PAGE_VALID) && tlb->size < size)
-        do_flush_tlbs = 1;
-    tlb->size = size;
-    tlb->attr &= ~0x1;
-    tlb->attr |= (T1 >> 8) & 1;
-    if (T1 & 0x200) {
-        tlb->prot |= PAGE_VALID;
-    } else {
-        if (tlb->prot & PAGE_VALID) {
-            tlb->prot &= ~PAGE_VALID;
+    switch (word) {
+    default:
+        /* Just here to please gcc */
+    case 0:
+        EPN = T1 & 0xFFFFFC00;
+        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
             do_flush_tlbs = 1;
+        tlb->EPN = EPN;
+        size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
+        if ((tlb->prot & PAGE_VALID) && tlb->size < size)
+            do_flush_tlbs = 1;
+        tlb->size = size;
+        tlb->attr &= ~0x1;
+        tlb->attr |= (T1 >> 8) & 1;
+        if (T1 & 0x200) {
+            tlb->prot |= PAGE_VALID;
+        } else {
+            if (tlb->prot & PAGE_VALID) {
+                tlb->prot &= ~PAGE_VALID;
+                do_flush_tlbs = 1;
+            }
         }
+        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
+        if (do_flush_tlbs)
+            tlb_flush(env, 1);
+        break;
+    case 1:
+        RPN = T1 & 0xFFFFFC0F;
+        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
+            tlb_flush(env, 1);
+        tlb->RPN = RPN;
+        break;
+    case 2:
+        tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
+        tlb->prot = tlb->prot & PAGE_VALID;
+        if (T1 & 0x1)
+            tlb->prot |= PAGE_READ << 4;
+        if (T1 & 0x2)
+            tlb->prot |= PAGE_WRITE << 4;
+        if (T1 & 0x4)
+            tlb->prot |= PAGE_EXEC << 4;
+        if (T1 & 0x8)
+            tlb->prot |= PAGE_READ;
+        if (T1 & 0x10)
+            tlb->prot |= PAGE_WRITE;
+        if (T1 & 0x20)
+            tlb->prot |= PAGE_EXEC;
+        break;
     }
-    tlb->PID = env->spr[SPR_BOOKE_PID];
-    if (do_flush_tlbs)
-        tlb_flush(env, 1);
 }
 
-void do_booke_tlbwe1 (void)
+void do_440_tlbre (int word)
 {
     ppcemb_tlb_t *tlb;
-    target_phys_addr_t RPN;
+    int size;
 
-#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;
-    RPN = T1 & 0xFFFFFC0F;
-    if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
-        tlb_flush(env, 1);
-    tlb->RPN = RPN;
-}
-
-void do_booke_tlbwe2 (void)
-{
-    ppcemb_tlb_t *tlb;
-
-#if defined (DEBUG_SOFTWARE_TLB)
-    if (loglevel != 0) {
-        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
+    switch (word) {
+    default:
+        /* Just here to please gcc */
+    case 0:
+        T0 = tlb->EPN;
+        size = booke_page_size_to_tlb(tlb->size);
+        if (size < 0 || size > 0xF)
+            size = 1;
+        T0 |= size << 4;
+        if (tlb->attr & 0x1)
+            T0 |= 0x100;
+        if (tlb->prot & PAGE_VALID)
+            T0 |= 0x200;
+        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
+        env->spr[SPR_440_MMUCR] |= tlb->PID;
+        break;
+    case 1:
+        T0 = tlb->RPN;
+        break;
+    case 2:
+        T0 = tlb->attr & ~0x1;
+        if (tlb->prot & (PAGE_READ << 4))
+            T0 |= 0x1;
+        if (tlb->prot & (PAGE_WRITE << 4))
+            T0 |= 0x2;
+        if (tlb->prot & (PAGE_EXEC << 4))
+            T0 |= 0x4;
+        if (tlb->prot & PAGE_READ)
+            T0 |= 0x8;
+        if (tlb->prot & PAGE_WRITE)
+            T0 |= 0x10;
+        if (tlb->prot & PAGE_EXEC)
+            T0 |= 0x20;
+        break;
     }
-#endif
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
-    tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
-    tlb->prot = tlb->prot & PAGE_VALID;
-    if (T1 & 0x1)
-        tlb->prot |= PAGE_READ << 4;
-    if (T1 & 0x2)
-        tlb->prot |= PAGE_WRITE << 4;
-    if (T1 & 0x4)
-        tlb->prot |= PAGE_EXEC << 4;
-    if (T1 & 0x8)
-        tlb->prot |= PAGE_READ;
-    if (T1 & 0x10)
-        tlb->prot |= PAGE_WRITE;
-    if (T1 & 0x20)
-        tlb->prot |= PAGE_EXEC;
 }
-
-void do_booke_tlbsx (void)
-{
-    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR]);
-}
-
-void do_booke_tlbsx_ (void)
-{
-    int tmp = xer_so;
-
-    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR]);
-    if (T0 != -1)
-        tmp |= 0x02;
-    env->crf[0] = tmp;
-}
-
-void do_booke_tlbre0 (void)
-{
-    ppcemb_tlb_t *tlb;
-    int size;
-
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
-    T0 = tlb->EPN;
-    size = booke_page_size_to_tlb(tlb->size);
-    if (size < 0 || size > 0xF)
-        size = 1;
-    T0 |= size << 4;
-    if (tlb->attr & 0x1)
-        T0 |= 0x100;
-    if (tlb->prot & PAGE_VALID)
-        T0 |= 0x200;
-    env->spr[SPR_BOOKE_PID] = tlb->PID;
-}
-
-void do_booke_tlbre1 (void)
-{
-    ppcemb_tlb_t *tlb;
-
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
-    T0 = tlb->RPN;
-}
-
-void do_booke_tlbre2 (void)
-{
-    ppcemb_tlb_t *tlb;
-
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
-    T0 = tlb->attr & ~0x1;
-    if (tlb->prot & (PAGE_READ << 4))
-        T0 |= 0x1;
-    if (tlb->prot & (PAGE_WRITE << 4))
-        T0 |= 0x2;
-    if (tlb->prot & (PAGE_EXEC << 4))
-        T0 |= 0x4;
-    if (tlb->prot & PAGE_READ)
-        T0 |= 0x8;
-    if (tlb->prot & PAGE_WRITE)
-        T0 |= 0x10;
-    if (tlb->prot & PAGE_EXEC)
-        T0 |= 0x20;
-}
 #endif /* !CONFIG_USER_ONLY */

Modified: trunk/src/host/qemu-neo1973/target-ppc/op_helper.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_helper.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_helper.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -30,6 +30,7 @@
 void glue(do_stmw, MEMSUFFIX) (int src);
 void glue(do_stmw_le, MEMSUFFIX) (int src);
 void glue(do_icbi, MEMSUFFIX) (void);
+void glue(do_dcbz, 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);
@@ -46,6 +47,7 @@
 void glue(do_stmw_64, MEMSUFFIX) (int src);
 void glue(do_stmw_le_64, MEMSUFFIX) (int src);
 void glue(do_icbi_64, MEMSUFFIX) (void);
+void glue(do_dcbz_64, MEMSUFFIX) (void);
 #endif
 
 #else
@@ -55,9 +57,10 @@
 /* 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);
+#if defined(TARGET_PPC64)
+void do_store_pri (int prio);
+#endif
+void do_fpscr_setbit (int bit);
 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);
@@ -72,12 +75,14 @@
 void do_subfe (void);
 void do_subfmeo (void);
 void do_subfzeo (void);
+void do_cntlzw (void);
+#if defined(TARGET_PPC64)
+void do_cntlzd (void);
+#endif
 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);
@@ -93,7 +98,18 @@
 #endif
 
 /* Floating-point arithmetic helpers */
+void do_compute_fprf (int set_class);
+#ifdef CONFIG_SOFTFLOAT
+void do_float_check_status (void);
+#endif
+#if USE_PRECISE_EMULATION
+void do_fadd (void);
+void do_fsub (void);
+void do_fmul (void);
+void do_fdiv (void);
+#endif
 void do_fsqrt (void);
+void do_fre (void);
 void do_fres (void);
 void do_frsqrte (void);
 void do_fsel (void);
@@ -103,6 +119,9 @@
 #endif
 void do_fnmadd (void);
 void do_fnmsub (void);
+#if USE_PRECISE_EMULATION
+void do_frsp (void);
+#endif
 void do_fctiw (void);
 void do_fctiwz (void);
 #if defined(TARGET_PPC64)
@@ -110,6 +129,10 @@
 void do_fctid (void);
 void do_fctidz (void);
 #endif
+void do_frin (void);
+void do_friz (void);
+void do_frip (void);
+void do_frim (void);
 void do_fcmpu (void);
 void do_fcmpo (void);
 
@@ -119,21 +142,17 @@
 void do_td (int flags);
 #endif
 #if !defined(CONFIG_USER_ONLY)
+void do_store_msr (void);
 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);
+#if defined(TARGET_PPC64H)
+void do_hrfid (void);
 #endif
 void do_load_6xx_tlb (int is_code);
-#if defined(TARGET_PPC64)
-void do_slbia (void);
-void do_slbie (void);
+void do_load_74xx_tlb (int is_code);
 #endif
-#endif
 
 /* POWER / PowerPC 601 specific helpers */
 void do_store_601_batu (int nr);
@@ -156,32 +175,24 @@
 void do_op_602_mfrom (void);
 #endif
 
-/* PowerPC BookE specific helpers */
+/* PowerPC 440 specific helpers */
 #if !defined(CONFIG_USER_ONLY)
-void do_booke_tlbre0 (void);
-void do_booke_tlbre1 (void);
-void do_booke_tlbre2 (void);
-void do_booke_tlbsx (void);
-void do_booke_tlbsx_ (void);
-void do_booke_tlbwe0 (void);
-void do_booke_tlbwe1 (void);
-void do_booke_tlbwe2 (void);
+void do_440_tlbre (int word);
+void do_440_tlbwe (int word);
 #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);
+#if !defined(CONFIG_USER_ONLY)
 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
@@ -278,94 +289,22 @@
 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)
+static always_inline uint32_t _do_efsabs (uint32_t val)
 {
     return val & ~0x80000000;
 }
-static inline uint32_t _do_efsnabs (uint32_t val)
+static always_inline uint32_t _do_efsnabs (uint32_t val)
 {
     return val | 0x80000000;
 }
-static inline uint32_t _do_efsneg (uint32_t val)
+static always_inline uint32_t _do_efsneg (uint32_t val)
 {
     return val ^ 0x80000000;
 }
-static inline uint32_t _do_efsadd (uint32_t op1, uint32_t op2)
+static always_inline uint32_t _do_efsadd (uint32_t op1, uint32_t op2)
 {
     union {
         uint32_t u;
@@ -376,7 +315,7 @@
     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)
+static always_inline uint32_t _do_efssub (uint32_t op1, uint32_t op2)
 {
     union {
         uint32_t u;
@@ -387,7 +326,7 @@
     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)
+static always_inline uint32_t _do_efsmul (uint32_t op1, uint32_t op2)
 {
     union {
         uint32_t u;
@@ -398,7 +337,7 @@
     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)
+static always_inline uint32_t _do_efsdiv (uint32_t op1, uint32_t op2)
 {
     union {
         uint32_t u;
@@ -410,7 +349,7 @@
     return u1.u;
 }
 
-static inline int _do_efststlt (uint32_t op1, uint32_t op2)
+static always_inline int _do_efststlt (uint32_t op1, uint32_t op2)
 {
     union {
         uint32_t u;
@@ -420,7 +359,7 @@
     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)
+static always_inline int _do_efststgt (uint32_t op1, uint32_t op2)
 {
     union {
         uint32_t u;
@@ -430,7 +369,7 @@
     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)
+static always_inline int _do_efststeq (uint32_t op1, uint32_t op2)
 {
     union {
         uint32_t u;
@@ -441,7 +380,7 @@
     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)
+static always_inline int _do_efdtstlt (uint64_t op1, uint64_t op2)
 {
     union {
         uint64_t u;
@@ -451,7 +390,7 @@
     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)
+static always_inline int _do_efdtstgt (uint64_t op1, uint64_t op2)
 {
     union {
         uint64_t u;
@@ -461,7 +400,7 @@
     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)
+static always_inline int _do_efdtsteq (uint64_t op1, uint64_t op2)
 {
     union {
         uint64_t u;

Modified: trunk/src/host/qemu-neo1973/target-ppc/op_helper_mem.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_helper_mem.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_helper_mem.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -19,14 +19,15 @@
  */
 
 /* Multiple word / string load and store */
-static inline target_ulong glue(ld32r, MEMSUFFIX) (target_ulong EA)
+static always_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)
+static always_inline void glue(st32r, MEMSUFFIX) (target_ulong EA,
+                                                  target_ulong data)
 {
     uint32_t tmp =
         ((data & 0xFF000000UL) >> 24) | ((data & 0x00FF0000UL) >> 8) |
@@ -251,9 +252,10 @@
      * (not a fetch) by the MMU. To be sure it will be so,
      * do the load "by hand".
      */
+    T0 &= ~(env->icache_line_size - 1);
     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));
+    tb_invalidate_page_range((uint32_t)T0,
+                             (uint32_t)(T0 + env->icache_line_size));
 }
 
 #if defined(TARGET_PPC64)
@@ -265,12 +267,105 @@
      * (not a fetch) by the MMU. To be sure it will be so,
      * do the load "by hand".
      */
+    T0 &= ~(env->icache_line_size - 1);
     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));
+    tb_invalidate_page_range((uint64_t)T0,
+                             (uint64_t)(T0 + env->icache_line_size));
 }
 #endif
 
+void glue(do_dcbz, MEMSUFFIX) (void)
+{
+    int dcache_line_size = env->dcache_line_size;
+
+    /* XXX: should be 970 specific (?) */
+    if (((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1)
+        dcache_line_size = 32;
+    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) {
+        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);
+        if (dcache_line_size >= 128) {
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x40UL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x44UL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x48UL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x4CUL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x50UL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x54UL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x58UL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x5CUL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x60UL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x64UL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x68UL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x6CUL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x70UL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x74UL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x78UL), 0);
+            glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x7CUL), 0);
+        }
+    }
+}
+
+#if defined(TARGET_PPC64)
+void glue(do_dcbz_64, MEMSUFFIX) (void)
+{
+    int dcache_line_size = env->dcache_line_size;
+
+    /* XXX: should be 970 specific (?) */
+    if (((env->spr[SPR_970_HID5] >> 6) & 0x3) == 0x2)
+        dcache_line_size = 32;
+    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) {
+        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);
+        if (dcache_line_size >= 128) {
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x40UL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x44UL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x48UL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x4CUL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x50UL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x54UL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x58UL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x5CUL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x60UL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x64UL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x68UL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x6CUL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x70UL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x74UL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x78UL), 0);
+            glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x7CUL), 0);
+        }
+    }
+}
+#endif
+
 /* PowerPC 601 specific instructions (POWER bridge) */
 // XXX: to be tested
 void glue(do_POWER_lscbx, MEMSUFFIX) (int dest, int ra, int rb)
@@ -305,7 +400,7 @@
     FT1 = glue(ldfq, MEMSUFFIX)((uint32_t)(T0 + 4));
 }
 
-static inline double glue(ldfqr, MEMSUFFIX) (target_ulong EA)
+static always_inline double glue(ldfqr, MEMSUFFIX) (target_ulong EA)
 {
     union {
         double d;
@@ -337,7 +432,7 @@
     glue(stfq, MEMSUFFIX)((uint32_t)(T0 + 4), FT1);
 }
 
-static inline void glue(stfqr, MEMSUFFIX) (target_ulong EA, double d)
+static always_inline void glue(stfqr, MEMSUFFIX) (target_ulong EA, double d)
 {
     union {
         double d;

Modified: trunk/src/host/qemu-neo1973/target-ppc/op_mem.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_mem.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_mem.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -18,19 +18,19 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-static inline uint16_t glue(ld16r, MEMSUFFIX) (target_ulong EA)
+static always_inline uint16_t glue(ld16r, MEMSUFFIX) (target_ulong EA)
 {
     uint16_t tmp = glue(lduw, MEMSUFFIX)(EA);
     return ((tmp & 0xFF00) >> 8) | ((tmp & 0x00FF) << 8);
 }
 
-static inline int32_t glue(ld16rs, MEMSUFFIX) (target_ulong EA)
+static always_inline int32_t glue(ld16rs, MEMSUFFIX) (target_ulong EA)
 {
     int16_t tmp = glue(lduw, MEMSUFFIX)(EA);
     return (int16_t)((tmp & 0xFF00) >> 8) | ((tmp & 0x00FF) << 8);
 }
 
-static inline uint32_t glue(ld32r, MEMSUFFIX) (target_ulong EA)
+static always_inline uint32_t glue(ld32r, MEMSUFFIX) (target_ulong EA)
 {
     uint32_t tmp = glue(ldl, MEMSUFFIX)(EA);
     return ((tmp & 0xFF000000) >> 24) | ((tmp & 0x00FF0000) >> 8) |
@@ -38,7 +38,7 @@
 }
 
 #if defined(TARGET_PPC64) || defined(TARGET_PPCEMB)
-static inline uint64_t glue(ld64r, MEMSUFFIX) (target_ulong EA)
+static always_inline uint64_t glue(ld64r, MEMSUFFIX) (target_ulong EA)
 {
     uint64_t tmp = glue(ldq, MEMSUFFIX)(EA);
     return ((tmp & 0xFF00000000000000ULL) >> 56) |
@@ -53,12 +53,12 @@
 #endif
 
 #if defined(TARGET_PPC64)
-static inline int64_t glue(ldsl, MEMSUFFIX) (target_ulong EA)
+static always_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)
+static always_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) |
@@ -66,13 +66,15 @@
 }
 #endif
 
-static inline void glue(st16r, MEMSUFFIX) (target_ulong EA, uint16_t data)
+static always_inline void glue(st16r, MEMSUFFIX) (target_ulong EA,
+                                                  uint16_t data)
 {
     uint16_t tmp = ((data & 0xFF00) >> 8) | ((data & 0x00FF) << 8);
     glue(stw, MEMSUFFIX)(EA, tmp);
 }
 
-static inline void glue(st32r, MEMSUFFIX) (target_ulong EA, uint32_t data)
+static always_inline void glue(st32r, MEMSUFFIX) (target_ulong EA,
+                                                  uint32_t data)
 {
     uint32_t tmp = ((data & 0xFF000000) >> 24) | ((data & 0x00FF0000) >> 8) |
         ((data & 0x0000FF00) << 8) | ((data & 0x000000FF) << 24);
@@ -80,7 +82,8 @@
 }
 
 #if defined(TARGET_PPC64) || defined(TARGET_PPCEMB)
-static inline void glue(st64r, MEMSUFFIX) (target_ulong EA, uint64_t data)
+static always_inline void glue(st64r, MEMSUFFIX) (target_ulong EA,
+                                                  uint64_t data)
 {
     uint64_t tmp = ((data & 0xFF00000000000000ULL) >> 56) |
         ((data & 0x00FF000000000000ULL) >> 40) |
@@ -296,7 +299,9 @@
     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);
+            do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL |
+                                   POWERPC_EXCP_INVAL_LSWX);
         } else {
             glue(do_lsw, MEMSUFFIX)(PARAM1);
         }
@@ -311,7 +316,9 @@
     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);
+            do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL |
+                                   POWERPC_EXCP_INVAL_LSWX);
         } else {
             glue(do_lsw_64, MEMSUFFIX)(PARAM1);
         }
@@ -326,7 +333,9 @@
     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);
+            do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL |
+                                   POWERPC_EXCP_INVAL_LSWX);
         } else {
             glue(do_lsw_le, MEMSUFFIX)(PARAM1);
         }
@@ -341,7 +350,9 @@
     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);
+            do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL |
+                                   POWERPC_EXCP_INVAL_LSWX);
         } else {
             glue(do_lsw_le_64, MEMSUFFIX)(PARAM1);
         }
@@ -395,14 +406,42 @@
 }
 #endif
 
+static always_inline void glue(stfs, MEMSUFFIX) (target_ulong EA, double d)
+{
+    glue(stfl, MEMSUFFIX)(EA, float64_to_float32(d, &env->fp_status));
+}
+
+#if defined(WORDS_BIGENDIAN)
+#define WORD0 0
+#define WORD1 1
+#else
+#define WORD0 1
+#define WORD1 0
+#endif
+static always_inline void glue(stfiwx, MEMSUFFIX) (target_ulong EA, double d)
+{
+    union {
+        double d;
+        uint32_t u[2];
+    } u;
+
+    /* Store the low order 32 bits without any conversion */
+    u.d = d;
+    glue(stl, MEMSUFFIX)(EA, u.u[WORD0]);
+}
+#undef WORD0
+#undef WORD1
+
 PPC_STF_OP(fd, stfq);
-PPC_STF_OP(fs, stfl);
+PPC_STF_OP(fs, stfs);
+PPC_STF_OP(fiwx, stfiwx);
 #if defined(TARGET_PPC64)
 PPC_STF_OP_64(fd, stfq);
-PPC_STF_OP_64(fs, stfl);
+PPC_STF_OP_64(fs, stfs);
+PPC_STF_OP_64(fiwx, stfiwx);
 #endif
 
-static inline void glue(stfqr, MEMSUFFIX) (target_ulong EA, double d)
+static always_inline void glue(stfqr, MEMSUFFIX) (target_ulong EA, double d)
 {
     union {
         double d;
@@ -421,14 +460,14 @@
     glue(stfq, MEMSUFFIX)(EA, u.d);
 }
 
-static inline void glue(stflr, MEMSUFFIX) (target_ulong EA, float f)
+static always_inline void glue(stfsr, MEMSUFFIX) (target_ulong EA, double d)
 {
     union {
         float f;
         uint32_t u;
     } u;
 
-    u.f = f;
+    u.f = float64_to_float32(d, &env->fp_status);
     u.u = ((u.u & 0xFF000000UL) >> 24) |
         ((u.u & 0x00FF0000ULL) >> 8) |
         ((u.u & 0x0000FF00UL) << 8) |
@@ -436,11 +475,29 @@
     glue(stfl, MEMSUFFIX)(EA, u.f);
 }
 
+static always_inline void glue(stfiwxr, MEMSUFFIX) (target_ulong EA, double d)
+{
+    union {
+        double d;
+        uint64_t u;
+    } u;
+
+    /* Store the low order 32 bits without any conversion */
+    u.d = d;
+    u.u = ((u.u & 0xFF000000UL) >> 24) |
+        ((u.u & 0x00FF0000ULL) >> 8) |
+        ((u.u & 0x0000FF00UL) << 8) |
+        ((u.u & 0x000000FFULL) << 24);
+    glue(stl, MEMSUFFIX)(EA, u.u);
+}
+
 PPC_STF_OP(fd_le, stfqr);
-PPC_STF_OP(fs_le, stflr);
+PPC_STF_OP(fs_le, stfsr);
+PPC_STF_OP(fiwx_le, stfiwxr);
 #if defined(TARGET_PPC64)
 PPC_STF_OP_64(fd_le, stfqr);
-PPC_STF_OP_64(fs_le, stflr);
+PPC_STF_OP_64(fs_le, stfsr);
+PPC_STF_OP_64(fiwx_le, stfiwxr);
 #endif
 
 /***                         Floating-point load                           ***/
@@ -460,14 +517,19 @@
 }
 #endif
 
+static always_inline double glue(ldfs, MEMSUFFIX) (target_ulong EA)
+{
+    return float32_to_float64(glue(ldfl, MEMSUFFIX)(EA), &env->fp_status);
+}
+
 PPC_LDF_OP(fd, ldfq);
-PPC_LDF_OP(fs, ldfl);
+PPC_LDF_OP(fs, ldfs);
 #if defined(TARGET_PPC64)
 PPC_LDF_OP_64(fd, ldfq);
-PPC_LDF_OP_64(fs, ldfl);
+PPC_LDF_OP_64(fs, ldfs);
 #endif
 
-static inline double glue(ldfqr, MEMSUFFIX) (target_ulong EA)
+static always_inline double glue(ldfqr, MEMSUFFIX) (target_ulong EA)
 {
     union {
         double d;
@@ -487,7 +549,7 @@
     return u.d;
 }
 
-static inline float glue(ldflr, MEMSUFFIX) (target_ulong EA)
+static always_inline double glue(ldfsr, MEMSUFFIX) (target_ulong EA)
 {
     union {
         float f;
@@ -500,21 +562,21 @@
         ((u.u & 0x0000FF00UL) << 8) |
         ((u.u & 0x000000FFULL) << 24);
 
-    return u.f;
+    return float32_to_float64(u.f, &env->fp_status);
 }
 
 PPC_LDF_OP(fd_le, ldfqr);
-PPC_LDF_OP(fs_le, ldflr);
+PPC_LDF_OP(fs_le, ldfsr);
 #if defined(TARGET_PPC64)
 PPC_LDF_OP_64(fd_le, ldfqr);
-PPC_LDF_OP_64(fs_le, ldflr);
+PPC_LDF_OP_64(fs_le, ldfsr);
 #endif
 
 /* Load and set reservation */
 void OPPROTO glue(op_lwarx, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ldl, MEMSUFFIX)((uint32_t)T0);
         env->reserve = (uint32_t)T0;
@@ -526,7 +588,7 @@
 void OPPROTO glue(op_lwarx_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ldl, MEMSUFFIX)((uint64_t)T0);
         env->reserve = (uint64_t)T0;
@@ -537,7 +599,7 @@
 void OPPROTO glue(op_ldarx, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ldq, MEMSUFFIX)((uint32_t)T0);
         env->reserve = (uint32_t)T0;
@@ -548,7 +610,7 @@
 void OPPROTO glue(op_ldarx_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ldq, MEMSUFFIX)((uint64_t)T0);
         env->reserve = (uint64_t)T0;
@@ -560,7 +622,7 @@
 void OPPROTO glue(op_lwarx_le, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ld32r, MEMSUFFIX)((uint32_t)T0);
         env->reserve = (uint32_t)T0;
@@ -572,7 +634,7 @@
 void OPPROTO glue(op_lwarx_le_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ld32r, MEMSUFFIX)((uint64_t)T0);
         env->reserve = (uint64_t)T0;
@@ -583,7 +645,7 @@
 void OPPROTO glue(op_ldarx_le, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ld64r, MEMSUFFIX)((uint32_t)T0);
         env->reserve = (uint32_t)T0;
@@ -594,7 +656,7 @@
 void OPPROTO glue(op_ldarx_le_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ld64r, MEMSUFFIX)((uint64_t)T0);
         env->reserve = (uint64_t)T0;
@@ -607,7 +669,7 @@
 void OPPROTO glue(op_stwcx, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint32_t)T0)) {
             env->crf[0] = xer_so;
@@ -624,7 +686,7 @@
 void OPPROTO glue(op_stwcx_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint64_t)T0)) {
             env->crf[0] = xer_so;
@@ -640,7 +702,7 @@
 void OPPROTO glue(op_stdcx, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint32_t)T0)) {
             env->crf[0] = xer_so;
@@ -656,7 +718,7 @@
 void OPPROTO glue(op_stdcx_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint64_t)T0)) {
             env->crf[0] = xer_so;
@@ -673,7 +735,7 @@
 void OPPROTO glue(op_stwcx_le, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint32_t)T0)) {
             env->crf[0] = xer_so;
@@ -690,7 +752,7 @@
 void OPPROTO glue(op_stwcx_le_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint64_t)T0)) {
             env->crf[0] = xer_so;
@@ -706,7 +768,7 @@
 void OPPROTO glue(op_stdcx_le, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint32_t)T0)) {
             env->crf[0] = xer_so;
@@ -722,7 +784,7 @@
 void OPPROTO glue(op_stdcx_le_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint64_t)T0)) {
             env->crf[0] = xer_so;
@@ -736,7 +798,7 @@
 }
 #endif
 
-void OPPROTO glue(op_dcbz, MEMSUFFIX) (void)
+void OPPROTO glue(op_dcbz_l32, MEMSUFFIX) (void)
 {
     glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x00), 0);
     glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x04), 0);
@@ -746,8 +808,19 @@
     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 */
+    RETURN();
+}
+
+void OPPROTO glue(op_dcbz_l64, 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);
     glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x20UL), 0);
     glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x24UL), 0);
     glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x28UL), 0);
@@ -756,12 +829,54 @@
     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();
 }
 
+void OPPROTO glue(op_dcbz_l128, 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);
+    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);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x40UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x44UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x48UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x4CUL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x50UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x54UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x58UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x5CUL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x60UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x64UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x68UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x6CUL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x70UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x74UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x78UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x7CUL), 0);
+    RETURN();
+}
+
+void OPPROTO glue(op_dcbz, MEMSUFFIX) (void)
+{
+    glue(do_dcbz, MEMSUFFIX)();
+    RETURN();
+}
+
 #if defined(TARGET_PPC64)
-void OPPROTO glue(op_dcbz_64, MEMSUFFIX) (void)
+void OPPROTO glue(op_dcbz_l32_64, MEMSUFFIX) (void)
 {
     glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x00), 0);
     glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x04), 0);
@@ -771,8 +886,19 @@
     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 */
+    RETURN();
+}
+
+void OPPROTO glue(op_dcbz_l64_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);
     glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x20UL), 0);
     glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x24UL), 0);
     glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x28UL), 0);
@@ -781,9 +907,51 @@
     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();
 }
+
+void OPPROTO glue(op_dcbz_l128_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);
+    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);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x40UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x44UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x48UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x4CUL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x50UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x54UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x58UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x5CUL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x60UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x64UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x68UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x6CUL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x70UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x74UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x78UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x7CUL), 0);
+    RETURN();
+}
+
+void OPPROTO glue(op_dcbz_64, MEMSUFFIX) (void)
+{
+    glue(do_dcbz_64, MEMSUFFIX)();
+    RETURN();
+}
 #endif
 
 /* Instruction cache block invalidate */
@@ -895,6 +1063,66 @@
     RETURN();
 }
 
+/* Altivec vector extension */
+#if defined(WORDS_BIGENDIAN)
+#define VR_DWORD0 0
+#define VR_DWORD1 1
+#else
+#define VR_DWORD0 1
+#define VR_DWORD1 0
+#endif
+void OPPROTO glue(op_vr_lvx, MEMSUFFIX) (void)
+{
+    AVR0.u64[VR_DWORD0] = glue(ldq, MEMSUFFIX)((uint32_t)T0);
+    AVR0.u64[VR_DWORD1] = glue(ldq, MEMSUFFIX)((uint32_t)T0 + 8);
+}
+
+void OPPROTO glue(op_vr_lvx_le, MEMSUFFIX) (void)
+{
+    AVR0.u64[VR_DWORD1] = glue(ldq, MEMSUFFIX)((uint32_t)T0);
+    AVR0.u64[VR_DWORD0] = glue(ldq, MEMSUFFIX)((uint32_t)T0 + 8);
+}
+
+void OPPROTO glue(op_vr_stvx, MEMSUFFIX) (void)
+{
+    glue(stq, MEMSUFFIX)((uint32_t)T0, AVR0.u64[VR_DWORD0]);
+    glue(stq, MEMSUFFIX)((uint32_t)T0 + 8, AVR0.u64[VR_DWORD1]);
+}
+
+void OPPROTO glue(op_vr_stvx_le, MEMSUFFIX) (void)
+{
+    glue(stq, MEMSUFFIX)((uint32_t)T0, AVR0.u64[VR_DWORD1]);
+    glue(stq, MEMSUFFIX)((uint32_t)T0 + 8, AVR0.u64[VR_DWORD0]);
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_vr_lvx_64, MEMSUFFIX) (void)
+{
+    AVR0.u64[VR_DWORD0] = glue(ldq, MEMSUFFIX)((uint64_t)T0);
+    AVR0.u64[VR_DWORD1] = glue(ldq, MEMSUFFIX)((uint64_t)T0 + 8);
+}
+
+void OPPROTO glue(op_vr_lvx_le_64, MEMSUFFIX) (void)
+{
+    AVR0.u64[VR_DWORD1] = glue(ldq, MEMSUFFIX)((uint64_t)T0);
+    AVR0.u64[VR_DWORD0] = glue(ldq, MEMSUFFIX)((uint64_t)T0 + 8);
+}
+
+void OPPROTO glue(op_vr_stvx_64, MEMSUFFIX) (void)
+{
+    glue(stq, MEMSUFFIX)((uint64_t)T0, AVR0.u64[VR_DWORD0]);
+    glue(stq, MEMSUFFIX)((uint64_t)T0 + 8, AVR0.u64[VR_DWORD1]);
+}
+
+void OPPROTO glue(op_vr_stvx_le_64, MEMSUFFIX) (void)
+{
+    glue(stq, MEMSUFFIX)((uint64_t)T0, AVR0.u64[VR_DWORD1]);
+    glue(stq, MEMSUFFIX)((uint64_t)T0 + 8, AVR0.u64[VR_DWORD0]);
+}
+#endif
+#undef VR_DWORD0
+#undef VR_DWORD1
+
 #if defined(TARGET_PPCEMB)
 /* SPE extension */
 #define _PPC_SPE_LD_OP(name, op)                                              \
@@ -919,7 +1147,6 @@
 _PPC_SPE_LD_OP(name, op)
 #endif
 
-
 #define _PPC_SPE_ST_OP(name, op)                                              \
 void OPPROTO glue(glue(op_spe_st, name), MEMSUFFIX) (void)                    \
 {                                                                             \
@@ -948,7 +1175,7 @@
 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)
+static always_inline uint64_t glue(spe_ldw, MEMSUFFIX) (target_ulong EA)
 {
     uint64_t ret;
     ret = (uint64_t)glue(ldl, MEMSUFFIX)(EA) << 32;
@@ -956,13 +1183,14 @@
     return ret;
 }
 PPC_SPE_LD_OP(dw, spe_ldw);
-static inline void glue(spe_stdw, MEMSUFFIX) (target_ulong EA, uint64_t data)
+static always_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)
+static always_inline uint64_t glue(spe_ldw_le, MEMSUFFIX) (target_ulong EA)
 {
     uint64_t ret;
     ret = (uint64_t)glue(ld32r, MEMSUFFIX)(EA) << 32;
@@ -970,14 +1198,14 @@
     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)
+static always_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)
+static always_inline uint64_t glue(spe_ldh, MEMSUFFIX) (target_ulong EA)
 {
     uint64_t ret;
     ret = (uint64_t)glue(lduw, MEMSUFFIX)(EA) << 48;
@@ -987,7 +1215,8 @@
     return ret;
 }
 PPC_SPE_LD_OP(dh, spe_ldh);
-static inline void glue(spe_stdh, MEMSUFFIX) (target_ulong EA, uint64_t data)
+static always_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);
@@ -995,7 +1224,7 @@
     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)
+static always_inline uint64_t glue(spe_ldh_le, MEMSUFFIX) (target_ulong EA)
 {
     uint64_t ret;
     ret = (uint64_t)glue(ld16r, MEMSUFFIX)(EA) << 48;
@@ -1005,8 +1234,8 @@
     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)
+static always_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);
@@ -1014,7 +1243,7 @@
     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)
+static always_inline uint64_t glue(spe_lwhe, MEMSUFFIX) (target_ulong EA)
 {
     uint64_t ret;
     ret = (uint64_t)glue(lduw, MEMSUFFIX)(EA) << 48;
@@ -1022,13 +1251,14 @@
     return ret;
 }
 PPC_SPE_LD_OP(whe, spe_lwhe);
-static inline void glue(spe_stwhe, MEMSUFFIX) (target_ulong EA, uint64_t data)
+static always_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)
+static always_inline uint64_t glue(spe_lwhe_le, MEMSUFFIX) (target_ulong EA)
 {
     uint64_t ret;
     ret = (uint64_t)glue(ld16r, MEMSUFFIX)(EA) << 48;
@@ -1036,14 +1266,14 @@
     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)
+static always_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)
+static always_inline uint64_t glue(spe_lwhou, MEMSUFFIX) (target_ulong EA)
 {
     uint64_t ret;
     ret = (uint64_t)glue(lduw, MEMSUFFIX)(EA) << 32;
@@ -1051,7 +1281,7 @@
     return ret;
 }
 PPC_SPE_LD_OP(whou, spe_lwhou);
-static inline uint64_t glue(spe_lwhos, MEMSUFFIX) (target_ulong EA)
+static always_inline uint64_t glue(spe_lwhos, MEMSUFFIX) (target_ulong EA)
 {
     uint64_t ret;
     ret = ((uint64_t)((int32_t)glue(ldsw, MEMSUFFIX)(EA))) << 32;
@@ -1059,13 +1289,14 @@
     return ret;
 }
 PPC_SPE_LD_OP(whos, spe_lwhos);
-static inline void glue(spe_stwho, MEMSUFFIX) (target_ulong EA, uint64_t data)
+static always_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)
+static always_inline uint64_t glue(spe_lwhou_le, MEMSUFFIX) (target_ulong EA)
 {
     uint64_t ret;
     ret = (uint64_t)glue(ld16r, MEMSUFFIX)(EA) << 32;
@@ -1073,7 +1304,7 @@
     return ret;
 }
 PPC_SPE_LD_OP(whou_le, spe_lwhou_le);
-static inline uint64_t glue(spe_lwhos_le, MEMSUFFIX) (target_ulong EA)
+static always_inline uint64_t glue(spe_lwhos_le, MEMSUFFIX) (target_ulong EA)
 {
     uint64_t ret;
     ret = ((uint64_t)((int32_t)glue(ld16rs, MEMSUFFIX)(EA))) << 32;
@@ -1081,55 +1312,57 @@
     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)
+static always_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)
+static always_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)
+static always_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)
+static always_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)
+static always_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)
+static always_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)
+static always_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)
+static always_inline uint64_t glue(spe_lwhsplat, MEMSUFFIX) (target_ulong EA)
 {
     uint64_t ret;
     uint16_t tmp;
@@ -1140,7 +1373,8 @@
     return ret;
 }
 PPC_SPE_LD_OP(whsplat, spe_lwhsplat);
-static inline uint64_t glue(spe_lwhsplat_le, MEMSUFFIX) (target_ulong EA)
+static always_inline
+uint64_t glue(spe_lwhsplat_le, MEMSUFFIX) (target_ulong EA)
 {
     uint64_t ret;
     uint16_t tmp;

Modified: trunk/src/host/qemu-neo1973/target-ppc/op_template.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_template.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_template.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -57,6 +57,7 @@
 }
 #endif
 
+/* General purpose registers containing vector operands moves */
 #if defined(TARGET_PPCEMB)
 void OPPROTO glue(op_load_gpr64_T0_gpr, REG) (void)
 {
@@ -99,65 +100,71 @@
 #endif
 #endif /* defined(TARGET_PPCEMB) */
 
-#if REG <= 7
-/* Condition register moves */
-void OPPROTO glue(op_load_crf_T0_crf, REG) (void)
+/* Altivec registers moves */
+void OPPROTO glue(op_load_avr_A0_avr, REG) (void)
 {
-    T0 = env->crf[REG];
+    AVR0 = env->avr[REG];
     RETURN();
 }
 
-void OPPROTO glue(op_load_crf_T1_crf, REG) (void)
+void OPPROTO glue(op_load_avr_A1_avr, REG) (void)
 {
-    T1 = env->crf[REG];
+    AVR1 = env->avr[REG];
     RETURN();
 }
 
-void OPPROTO glue(op_store_T0_crf_crf, REG) (void)
+void OPPROTO glue(op_load_avr_A2_avr, REG) (void)
 {
-    env->crf[REG] = T0;
+    AVR2 = env->avr[REG];
     RETURN();
 }
 
-void OPPROTO glue(op_store_T1_crf_crf, REG) (void)
+void OPPROTO glue(op_store_A0_avr_avr, REG) (void)
 {
-    env->crf[REG] = T1;
+    env->avr[REG] = AVR0;
     RETURN();
 }
 
-/* Floating point condition and status register moves */
-void OPPROTO glue(op_load_fpscr_T0_fpscr, REG) (void)
+void OPPROTO glue(op_store_A1_avr_avr, REG) (void)
 {
-    T0 = env->fpscr[REG];
+    env->avr[REG] = AVR1;
     RETURN();
 }
 
-#if REG == 0
-void OPPROTO glue(op_store_T0_fpscr_fpscr, REG) (void)
+#if 0 // unused
+void OPPROTO glue(op_store_A2_avr_avr, REG) (void)
 {
-    env->fpscr[REG] = (env->fpscr[REG] & 0x9) | (T0 & ~0x9);
+    env->avr[REG] = AVR2;
     RETURN();
 }
+#endif
 
-void OPPROTO glue(op_clear_fpscr_fpscr, REG) (void)
+#if REG <= 7
+/* Condition register moves */
+void OPPROTO glue(op_load_crf_T0_crf, REG) (void)
 {
-    env->fpscr[REG] = (env->fpscr[REG] & 0x9);
+    T0 = env->crf[REG];
     RETURN();
 }
-#else
-void OPPROTO glue(op_store_T0_fpscr_fpscr, REG) (void)
+
+void OPPROTO glue(op_load_crf_T1_crf, REG) (void)
 {
-    env->fpscr[REG] = T0;
+    T1 = env->crf[REG];
     RETURN();
 }
 
-void OPPROTO glue(op_clear_fpscr_fpscr, REG) (void)
+void OPPROTO glue(op_store_T0_crf_crf, REG) (void)
 {
-    env->fpscr[REG] = 0x0;
+    env->crf[REG] = T0;
     RETURN();
 }
-#endif
 
+void OPPROTO glue(op_store_T1_crf_crf, REG) (void)
+{
+    env->crf[REG] = T1;
+    RETURN();
+}
+
 #endif /* REG <= 7 */
 
 /* floating point registers moves */

Modified: trunk/src/host/qemu-neo1973/target-ppc/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/translate.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-ppc/translate.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -27,11 +27,15 @@
 #include "exec-all.h"
 #include "disas.h"
 
+/* Include definitions for instructions classes and implementations flags */
 //#define DO_SINGLE_STEP
 //#define PPC_DEBUG_DISAS
 //#define DEBUG_MEMORY_ACCESSES
 //#define DO_PPC_STATISTICS
+//#define OPTIMIZE_FPRF_UPDATE
 
+/*****************************************************************************/
+/* Code translation helpers                                                  */
 #if defined(USE_DIRECT_JUMP)
 #define TBPARAM(x)
 #else
@@ -47,10 +51,14 @@
 
 static uint16_t *gen_opc_ptr;
 static uint32_t *gen_opparam_ptr;
+#if defined(OPTIMIZE_FPRF_UPDATE)
+static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
+static uint16_t **gen_fprf_ptr;
+#endif
 
 #include "gen-op.h"
 
-static inline void gen_set_T0 (target_ulong val)
+static always_inline void gen_set_T0 (target_ulong val)
 {
 #if defined(TARGET_PPC64)
     if (val >> 32)
@@ -60,7 +68,7 @@
         gen_op_set_T0(val);
 }
 
-static inline void gen_set_T1 (target_ulong val)
+static always_inline void gen_set_T1 (target_ulong val)
 {
 #if defined(TARGET_PPC64)
     if (val >> 32)
@@ -75,7 +83,7 @@
 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
 };                                                                            \
-static inline void func(int n)                                                \
+static always_inline void func (int n)                                        \
 {                                                                             \
     NAME ## _table[n]();                                                      \
 }
@@ -87,7 +95,7 @@
 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
 };                                                                            \
-static inline void func(int n)                                                \
+static always_inline void func (int n)                                        \
 {                                                                             \
     NAME ## _table[n]();                                                      \
 }
@@ -103,7 +111,7 @@
 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
 };                                                                            \
-static inline void func(int n)                                                \
+static always_inline void func (int n)                                        \
 {                                                                             \
     NAME ## _table[n]();                                                      \
 }
@@ -114,16 +122,6 @@
 GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
 GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
 
-/* Floating point condition and status register moves */
-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 inline void gen_op_store_T0_fpscri (int n, uint8_t param)
-{
-    gen_op_set_T0(param);
-    gen_op_store_T0_fpscr(n);
-}
-
 /* 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);
@@ -161,11 +159,13 @@
     int sf_mode;
 #endif
     int fpu_enabled;
+    int altivec_enabled;
 #if defined(TARGET_PPCEMB)
     int spe_enabled;
 #endif
     ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
     int singlestep_enabled;
+    int dcache_line_size;
 } DisasContext;
 
 struct opc_handler_t {
@@ -175,13 +175,15 @@
     uint64_t type;
     /* handler */
     void (*handler)(DisasContext *ctx);
+#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
+    const unsigned char *oname;
+#endif
 #if defined(DO_PPC_STATISTICS)
-    const unsigned char *oname;
     uint64_t count;
 #endif
 };
 
-static inline void gen_set_Rc0 (DisasContext *ctx)
+static always_inline void gen_set_Rc0 (DisasContext *ctx)
 {
 #if defined(TARGET_PPC64)
     if (ctx->sf_mode)
@@ -192,8 +194,46 @@
     gen_op_set_Rc0();
 }
 
-static inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
+static always_inline void gen_reset_fpstatus (void)
 {
+#ifdef CONFIG_SOFTFLOAT
+    gen_op_reset_fpstatus();
+#endif
+}
+
+static always_inline void gen_compute_fprf (int set_fprf, int set_rc)
+{
+    if (set_fprf != 0) {
+        /* This case might be optimized later */
+#if defined(OPTIMIZE_FPRF_UPDATE)
+        *gen_fprf_ptr++ = gen_opc_ptr;
+#endif
+        gen_op_compute_fprf(1);
+        if (unlikely(set_rc))
+            gen_op_store_T0_crf(1);
+        gen_op_float_check_status();
+    } else if (unlikely(set_rc)) {
+        /* We always need to compute fpcc */
+        gen_op_compute_fprf(0);
+        gen_op_store_T0_crf(1);
+        if (set_fprf)
+            gen_op_float_check_status();
+    }
+}
+
+static always_inline void gen_optimize_fprf (void)
+{
+#if defined(OPTIMIZE_FPRF_UPDATE)
+    uint16_t **ptr;
+
+    for (ptr = gen_fprf_buf; ptr != (gen_fprf_ptr - 1); ptr++)
+        *ptr = INDEX_op_nop1;
+    gen_fprf_ptr = gen_fprf_buf;
+#endif
+}
+
+static always_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);
@@ -202,35 +242,47 @@
         gen_op_update_nip(nip);
 }
 
-#define RET_EXCP(ctx, excp, error)                                            \
+#define GEN_EXCP(ctx, excp, error)                                            \
 do {                                                                          \
-    if ((ctx)->exception == EXCP_NONE) {                                      \
+    if ((ctx)->exception == POWERPC_EXCP_NONE) {                              \
         gen_update_nip(ctx, (ctx)->nip);                                      \
     }                                                                         \
     gen_op_raise_exception_err((excp), (error));                              \
     ctx->exception = (excp);                                                  \
 } while (0)
 
-#define RET_INVAL(ctx)                                                        \
-RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL)
+#define GEN_EXCP_INVAL(ctx)                                                   \
+GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
+         POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL)
 
-#define RET_PRIVOPC(ctx)                                                      \
-RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC)
+#define GEN_EXCP_PRIVOPC(ctx)                                                 \
+GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
+         POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_OPC)
 
-#define RET_PRIVREG(ctx)                                                      \
-RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
+#define GEN_EXCP_PRIVREG(ctx)                                                 \
+GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
+         POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG)
 
+#define GEN_EXCP_NO_FP(ctx)                                                   \
+GEN_EXCP(ctx, POWERPC_EXCP_FPU, 0)
+
+#define GEN_EXCP_NO_AP(ctx)                                                   \
+GEN_EXCP(ctx, POWERPC_EXCP_APU, 0)
+
+#define GEN_EXCP_NO_VR(ctx)                                                   \
+GEN_EXCP(ctx, POWERPC_EXCP_VPU, 0)
+
 /* Stop translation */
-static inline void RET_STOP (DisasContext *ctx)
+static always_inline void GEN_STOP (DisasContext *ctx)
 {
     gen_update_nip(ctx, ctx->nip);
-    ctx->exception = EXCP_MTMSR;
+    ctx->exception = POWERPC_EXCP_STOP;
 }
 
 /* No need to update nip here, as execution flow will change */
-static inline void RET_CHG_FLOW (DisasContext *ctx)
+static always_inline void GEN_SYNC (DisasContext *ctx)
 {
-    ctx->exception = EXCP_MTMSR;
+    ctx->exception = POWERPC_EXCP_SYNC;
 }
 
 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
@@ -238,6 +290,11 @@
 GEN_OPCODE(name, opc1, opc2, opc3, inval, type);                              \
 static void gen_##name (DisasContext *ctx)
 
+#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type)               \
+static void gen_##name (DisasContext *ctx);                                   \
+GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type);                       \
+static void gen_##name (DisasContext *ctx)
+
 typedef struct opcode_t {
     unsigned char opc1, opc2, opc3;
 #if HOST_LONG_BITS == 64 /* Explicitely align to 64 bits */
@@ -249,15 +306,16 @@
     const unsigned char *oname;
 } opcode_t;
 
+/*****************************************************************************/
 /***                           Instruction decoding                        ***/
 #define EXTRACT_HELPER(name, shift, nb)                                       \
-static inline uint32_t name (uint32_t opcode)                                 \
+static always_inline uint32_t name (uint32_t opcode)                          \
 {                                                                             \
     return (opcode >> (shift)) & ((1 << (nb)) - 1);                           \
 }
 
 #define EXTRACT_SHELPER(name, shift, nb)                                      \
-static inline int32_t name (uint32_t opcode)                                  \
+static always_inline int32_t name (uint32_t opcode)                           \
 {                                                                             \
     return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1));                \
 }
@@ -288,7 +346,7 @@
 EXTRACT_HELPER(crbB, 11, 5);
 /* SPR / TBL */
 EXTRACT_HELPER(_SPR, 11, 10);
-static inline uint32_t SPR (uint32_t opcode)
+static always_inline uint32_t SPR (uint32_t opcode)
 {
     uint32_t sprn = _SPR(opcode);
 
@@ -320,12 +378,12 @@
 /* Displacement */
 EXTRACT_SHELPER(d, 0, 16);
 /* Immediate address */
-static inline target_ulong LI (uint32_t opcode)
+static always_inline target_ulong LI (uint32_t opcode)
 {
     return (opcode >> 0) & 0x03FFFFFC;
 }
 
-static inline uint32_t BD (uint32_t opcode)
+static always_inline uint32_t BD (uint32_t opcode)
 {
     return (opcode >> 0) & 0xFFFC;
 }
@@ -338,7 +396,7 @@
 EXTRACT_HELPER(LK, 0, 1);
 
 /* Create a mask between <start> and <end> bits */
-static inline target_ulong MASK (uint32_t start, uint32_t end)
+static always_inline target_ulong MASK (uint32_t start, uint32_t end)
 {
     target_ulong ret;
 
@@ -365,6 +423,118 @@
     return ret;
 }
 
+/*****************************************************************************/
+/* PowerPC Instructions types definitions                                    */
+enum {
+    PPC_NONE          = 0x0000000000000000ULL,
+    /* PowerPC base instructions set                                         */
+    PPC_INSNS_BASE    = 0x0000000000000001ULL,
+    /* integer operations instructions                                       */
+#define PPC_INTEGER PPC_INSNS_BASE
+    /* flow control instructions                                             */
+#define PPC_FLOW    PPC_INSNS_BASE
+    /* virtual memory instructions                                           */
+#define PPC_MEM     PPC_INSNS_BASE
+    /* ld/st with reservation instructions                                   */
+#define PPC_RES     PPC_INSNS_BASE
+    /* cache control instructions                                            */
+#define PPC_CACHE   PPC_INSNS_BASE
+    /* spr/msr access instructions                                           */
+#define PPC_MISC    PPC_INSNS_BASE
+    /* Optional floating point instructions                                  */
+    PPC_FLOAT         = 0x0000000000000002ULL,
+    PPC_FLOAT_FSQRT   = 0x0000000000000004ULL,
+    PPC_FLOAT_FRES    = 0x0000000000000008ULL,
+    PPC_FLOAT_FRSQRTE = 0x0000000000000010ULL,
+    PPC_FLOAT_FSEL    = 0x0000000000000020ULL,
+    PPC_FLOAT_STFIWX  = 0x0000000000000040ULL,
+    /* external control instructions                                         */
+    PPC_EXTERN        = 0x0000000000000080ULL,
+    /* segment register access instructions                                  */
+    PPC_SEGMENT       = 0x0000000000000100ULL,
+    /* Optional cache control instruction                                    */
+    PPC_CACHE_DCBA    = 0x0000000000000200ULL,
+    /* Optional memory control instructions                                  */
+    PPC_MEM_TLBIA     = 0x0000000000000400ULL,
+    PPC_MEM_TLBIE     = 0x0000000000000800ULL,
+    PPC_MEM_TLBSYNC   = 0x0000000000001000ULL,
+    /* eieio & sync                                                          */
+    PPC_MEM_SYNC      = 0x0000000000002000ULL,
+    /* PowerPC 6xx TLB management instructions                               */
+    PPC_6xx_TLB       = 0x0000000000004000ULL,
+    /* Altivec support                                                       */
+    PPC_ALTIVEC       = 0x0000000000008000ULL,
+    /* Time base mftb instruction                                            */
+    PPC_MFTB          = 0x0000000000010000ULL,
+    /* Embedded PowerPC dedicated instructions                               */
+    PPC_EMB_COMMON    = 0x0000000000020000ULL,
+    /* PowerPC 40x exception model                                           */
+    PPC_40x_EXCP      = 0x0000000000040000ULL,
+    /* PowerPC 40x TLB management instructions                               */
+    PPC_40x_TLB       = 0x0000000000080000ULL,
+    /* PowerPC 405 Mac instructions                                          */
+    PPC_405_MAC       = 0x0000000000100000ULL,
+    /* PowerPC 440 specific instructions                                     */
+    PPC_440_SPEC      = 0x0000000000200000ULL,
+    /* Power-to-PowerPC bridge (601)                                         */
+    PPC_POWER_BR      = 0x0000000000400000ULL,
+    /* PowerPC 602 specific                                                  */
+    PPC_602_SPEC      = 0x0000000000800000ULL,
+    /* Deprecated instructions                                               */
+    /* Original POWER instruction set                                        */
+    PPC_POWER         = 0x0000000001000000ULL,
+    /* POWER2 instruction set extension                                      */
+    PPC_POWER2        = 0x0000000002000000ULL,
+    /* Power RTC support                                                     */
+    PPC_POWER_RTC     = 0x0000000004000000ULL,
+    /* 64 bits PowerPC instruction set                                       */
+    PPC_64B           = 0x0000000008000000ULL,
+    /* 64 bits hypervisor extensions                                         */
+    PPC_64H           = 0x0000000010000000ULL,
+    /* segment register access instructions for PowerPC 64 "bridge"          */
+    PPC_SEGMENT_64B   = 0x0000000020000000ULL,
+    /* BookE (embedded) PowerPC specification                                */
+    PPC_BOOKE         = 0x0000000040000000ULL,
+    /* eieio                                                                 */
+    PPC_MEM_EIEIO     = 0x0000000080000000ULL,
+    /* e500 vector instructions                                              */
+    PPC_E500_VECTOR   = 0x0000000100000000ULL,
+    /* PowerPC 4xx dedicated instructions                                    */
+    PPC_4xx_COMMON    = 0x0000000200000000ULL,
+    /* PowerPC 2.03 specification extensions                                 */
+    PPC_203           = 0x0000000400000000ULL,
+    /* PowerPC 2.03 SPE extension                                            */
+    PPC_SPE           = 0x0000000800000000ULL,
+    /* PowerPC 2.03 SPE floating-point extension                             */
+    PPC_SPEFPU        = 0x0000001000000000ULL,
+    /* SLB management                                                        */
+    PPC_SLBI          = 0x0000002000000000ULL,
+    /* PowerPC 40x ibct instructions                                         */
+    PPC_40x_ICBT      = 0x0000004000000000ULL,
+    /* PowerPC 74xx TLB management instructions                              */
+    PPC_74xx_TLB      = 0x0000008000000000ULL,
+    /* More BookE (embedded) instructions...                                 */
+    PPC_BOOKE_EXT     = 0x0000010000000000ULL,
+    /* rfmci is not implemented in all BookE PowerPC                         */
+    PPC_RFMCI         = 0x0000020000000000ULL,
+    /* user-mode DCR access, implemented in PowerPC 460                      */
+    PPC_DCRUX         = 0x0000040000000000ULL,
+    /* New floating-point extensions (PowerPC 2.0x)                          */
+    PPC_FLOAT_EXT     = 0x0000080000000000ULL,
+    /* New wait instruction (PowerPC 2.0x)                                   */
+    PPC_WAIT          = 0x0000100000000000ULL,
+    /* New 64 bits extensions (PowerPC 2.0x)                                 */
+    PPC_64BX          = 0x0000200000000000ULL,
+    /* dcbz instruction with fixed cache line size                           */
+    PPC_CACHE_DCBZ    = 0x0000400000000000ULL,
+    /* dcbz instruction with tunable cache line size                         */
+    PPC_CACHE_DCBZT   = 0x0000800000000000ULL,
+    /* frsqrtes extension                                                    */
+    PPC_FLOAT_FRSQRTES = 0x0001000000000000ULL,
+};
+
+/*****************************************************************************/
+/* PowerPC instructions table                                                */
 #if HOST_LONG_BITS == 64
 #define OPC_ALIGN 8
 #else
@@ -393,6 +563,20 @@
     },                                                                        \
     .oname = stringify(name),                                                 \
 }
+#define GEN_OPCODE2(name, onam, 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 = onam,                                                        \
+    },                                                                        \
+    .oname = onam,                                                            \
+}
 #else
 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
 OPCODES_SECTION opcode_t opc_##name = {                                       \
@@ -407,6 +591,19 @@
     },                                                                        \
     .oname = stringify(name),                                                 \
 }
+#define GEN_OPCODE2(name, onam, 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 = onam,                                                            \
+}
 #endif
 
 #define GEN_OPCODE_MARK(name)                                                 \
@@ -429,7 +626,7 @@
 /* Invalid instruction */
 GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
 {
-    RET_INVAL(ctx);
+    GEN_EXCP_INVAL(ctx);
 }
 
 static opc_handler_t invalid_handler = {
@@ -568,7 +765,7 @@
 #endif
 
 /* add    add.    addo    addo.    */
-static inline void gen_op_addo (void)
+static always_inline void gen_op_addo (void)
 {
     gen_op_move_T2_T0();
     gen_op_add();
@@ -576,7 +773,7 @@
 }
 #if defined(TARGET_PPC64)
 #define gen_op_add_64 gen_op_add
-static inline void gen_op_addo_64 (void)
+static always_inline void gen_op_addo_64 (void)
 {
     gen_op_move_T2_T0();
     gen_op_add();
@@ -585,13 +782,13 @@
 #endif
 GEN_INT_ARITH2_64 (add,    0x1F, 0x0A, 0x08, PPC_INTEGER);
 /* addc   addc.   addco   addco.   */
-static inline void gen_op_addc (void)
+static always_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)
+static always_inline void gen_op_addco (void)
 {
     gen_op_move_T2_T0();
     gen_op_add();
@@ -599,13 +796,13 @@
     gen_op_check_addo();
 }
 #if defined(TARGET_PPC64)
-static inline void gen_op_addc_64 (void)
+static always_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)
+static always_inline void gen_op_addco_64 (void)
 {
     gen_op_move_T2_T0();
     gen_op_add();
@@ -615,14 +812,14 @@
 #endif
 GEN_INT_ARITH2_64 (addc,   0x1F, 0x0A, 0x00, PPC_INTEGER);
 /* adde   adde.   addeo   addeo.   */
-static inline void gen_op_addeo (void)
+static always_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)
+static always_inline void gen_op_addeo_64 (void)
 {
     gen_op_move_T2_T0();
     gen_op_adde_64();
@@ -631,13 +828,13 @@
 #endif
 GEN_INT_ARITH2_64 (adde,   0x1F, 0x0A, 0x04, PPC_INTEGER);
 /* addme  addme.  addmeo  addmeo.  */
-static inline void gen_op_addme (void)
+static always_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)
+static always_inline void gen_op_addme_64 (void)
 {
     gen_op_move_T1_T0();
     gen_op_add_me_64();
@@ -645,13 +842,13 @@
 #endif
 GEN_INT_ARITH1_64 (addme,  0x1F, 0x0A, 0x07, PPC_INTEGER);
 /* addze  addze.  addzeo  addzeo.  */
-static inline void gen_op_addze (void)
+static always_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)
+static always_inline void gen_op_addzeo (void)
 {
     gen_op_move_T2_T0();
     gen_op_add_ze();
@@ -659,13 +856,13 @@
     gen_op_check_addo();
 }
 #if defined(TARGET_PPC64)
-static inline void gen_op_addze_64 (void)
+static always_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)
+static always_inline void gen_op_addzeo_64 (void)
 {
     gen_op_move_T2_T0();
     gen_op_add_ze();
@@ -687,7 +884,7 @@
 /* neg    neg.    nego    nego.    */
 GEN_INT_ARITH1_64 (neg,    0x1F, 0x08, 0x03, PPC_INTEGER);
 /* subf   subf.   subfo   subfo.   */
-static inline void gen_op_subfo (void)
+static always_inline void gen_op_subfo (void)
 {
     gen_op_move_T2_T0();
     gen_op_subf();
@@ -695,7 +892,7 @@
 }
 #if defined(TARGET_PPC64)
 #define gen_op_subf_64 gen_op_subf
-static inline void gen_op_subfo_64 (void)
+static always_inline void gen_op_subfo_64 (void)
 {
     gen_op_move_T2_T0();
     gen_op_subf();
@@ -704,12 +901,12 @@
 #endif
 GEN_INT_ARITH2_64 (subf,   0x1F, 0x08, 0x01, PPC_INTEGER);
 /* subfc  subfc.  subfco  subfco.  */
-static inline void gen_op_subfc (void)
+static always_inline void gen_op_subfc (void)
 {
     gen_op_subf();
     gen_op_check_subfc();
 }
-static inline void gen_op_subfco (void)
+static always_inline void gen_op_subfco (void)
 {
     gen_op_move_T2_T0();
     gen_op_subf();
@@ -717,12 +914,12 @@
     gen_op_check_subfo();
 }
 #if defined(TARGET_PPC64)
-static inline void gen_op_subfc_64 (void)
+static always_inline void gen_op_subfc_64 (void)
 {
     gen_op_subf();
     gen_op_check_subfc_64();
 }
-static inline void gen_op_subfco_64 (void)
+static always_inline void gen_op_subfco_64 (void)
 {
     gen_op_move_T2_T0();
     gen_op_subf();
@@ -732,7 +929,7 @@
 #endif
 GEN_INT_ARITH2_64 (subfc,  0x1F, 0x08, 0x00, PPC_INTEGER);
 /* subfe  subfe.  subfeo  subfeo.  */
-static inline void gen_op_subfeo (void)
+static always_inline void gen_op_subfeo (void)
 {
     gen_op_move_T2_T0();
     gen_op_subfe();
@@ -740,7 +937,7 @@
 }
 #if defined(TARGET_PPC64)
 #define gen_op_subfe_64 gen_op_subfe
-static inline void gen_op_subfeo_64 (void)
+static always_inline void gen_op_subfeo_64 (void)
 {
     gen_op_move_T2_T0();
     gen_op_subfe_64();
@@ -788,7 +985,7 @@
     gen_op_store_T0_gpr(rD(ctx->opcode));
 }
 /* addic. */
-GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
+GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
     target_long simm = SIMM(ctx->opcode);
 
@@ -845,15 +1042,15 @@
 
 #if defined(TARGET_PPC64)
 /* mulhd  mulhd.                   */
-GEN_INT_ARITHN (mulhd,  0x1F, 0x09, 0x02, PPC_INTEGER);
+GEN_INT_ARITHN (mulhd,  0x1F, 0x09, 0x02, PPC_64B);
 /* mulhdu mulhdu.                  */
-GEN_INT_ARITHN (mulhdu, 0x1F, 0x09, 0x00, PPC_INTEGER);
+GEN_INT_ARITHN (mulhdu, 0x1F, 0x09, 0x00, PPC_64B);
 /* mulld  mulld.  mulldo  mulldo.  */
-GEN_INT_ARITH2 (mulld,  0x1F, 0x09, 0x07, PPC_INTEGER);
+GEN_INT_ARITH2 (mulld,  0x1F, 0x09, 0x07, PPC_64B);
 /* divd   divd.   divdo   divdo.   */
-GEN_INT_ARITH2 (divd,   0x1F, 0x09, 0x0F, PPC_INTEGER);
+GEN_INT_ARITH2 (divd,   0x1F, 0x09, 0x0F, PPC_64B);
 /* divdu  divdu.  divduo  divduo.  */
-GEN_INT_ARITH2 (divdu,  0x1F, 0x09, 0x0E, PPC_INTEGER);
+GEN_INT_ARITH2 (divdu,  0x1F, 0x09, 0x0E, PPC_64B);
 #endif
 
 /***                           Integer comparison                          ***/
@@ -863,7 +1060,7 @@
 {                                                                             \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
-    if (ctx->sf_mode)                                                         \
+    if (ctx->sf_mode && (ctx->opcode & 0x00200000))                           \
         gen_op_##name##_64();                                                 \
     else                                                                      \
         gen_op_##name();                                                      \
@@ -887,7 +1084,7 @@
 {
     gen_op_load_gpr_T0(rA(ctx->opcode));
 #if defined(TARGET_PPC64)
-    if (ctx->sf_mode)
+    if (ctx->sf_mode && (ctx->opcode & 0x00200000))
         gen_op_cmpi_64(SIMM(ctx->opcode));
     else
 #endif
@@ -901,7 +1098,7 @@
 {
     gen_op_load_gpr_T0(rA(ctx->opcode));
 #if defined(TARGET_PPC64)
-    if (ctx->sf_mode)
+    if (ctx->sf_mode && (ctx->opcode & 0x00200000))
         gen_op_cmpli_64(UIMM(ctx->opcode));
     else
 #endif
@@ -957,7 +1154,7 @@
 /* andc & andc. */
 GEN_LOGICAL2(andc, 0x01, PPC_INTEGER);
 /* andi. */
-GEN_HANDLER(andi_, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
+GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_andi_T0(UIMM(ctx->opcode));
@@ -965,7 +1162,7 @@
     gen_set_Rc0(ctx);
 }
 /* andis. */
-GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
+GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_andi_T0(UIMM(ctx->opcode) << 16);
@@ -1007,6 +1204,54 @@
     } else if (unlikely(Rc(ctx->opcode) != 0)) {
         gen_op_load_gpr_T0(rs);
         gen_set_Rc0(ctx);
+#if defined(TARGET_PPC64)
+    } else {
+        switch (rs) {
+        case 1:
+            /* Set process priority to low */
+            gen_op_store_pri(2);
+            break;
+        case 6:
+            /* Set process priority to medium-low */
+            gen_op_store_pri(3);
+            break;
+        case 2:
+            /* Set process priority to normal */
+            gen_op_store_pri(4);
+            break;
+#if !defined(CONFIG_USER_ONLY)
+        case 31:
+            if (ctx->supervisor > 0) {
+                /* Set process priority to very low */
+                gen_op_store_pri(1);
+            }
+            break;
+        case 5:
+            if (ctx->supervisor > 0) {
+                /* Set process priority to medium-hight */
+                gen_op_store_pri(5);
+            }
+            break;
+        case 3:
+            if (ctx->supervisor > 0) {
+                /* Set process priority to high */
+                gen_op_store_pri(6);
+            }
+            break;
+#if defined(TARGET_PPC64H)
+        case 7:
+            if (ctx->supervisor > 1) {
+                /* Set process priority to very high */
+                gen_op_store_pri(7);
+            }
+            break;
+#endif
+#endif
+        default:
+            /* nop */
+            break;
+        }
+#endif
     }
 }
 
@@ -1207,42 +1452,62 @@
 
 #if defined(TARGET_PPC64)
 #define GEN_PPC64_R2(name, opc1, opc2)                                        \
-GEN_HANDLER(name##0, opc1, opc2, 0xFF, 0x00000000, PPC_64B)                   \
+GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
 {                                                                             \
     gen_##name(ctx, 0);                                                       \
 }                                                                             \
-GEN_HANDLER(name##1, opc1, opc2 | 0x10, 0xFF, 0x00000000, PPC_64B)            \
+GEN_HANDLER2(name##1, stringify(name), 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_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
 {                                                                             \
     gen_##name(ctx, 0, 0);                                                    \
 }                                                                             \
-GEN_HANDLER(name##1, opc1, opc2 | 0x01, 0xFF, 0x00000000, PPC_64B)            \
+GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000,   \
+             PPC_64B)                                                         \
 {                                                                             \
     gen_##name(ctx, 0, 1);                                                    \
 }                                                                             \
-GEN_HANDLER(name##2, opc1, opc2 | 0x10, 0xFF, 0x00000000, PPC_64B)            \
+GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000,   \
+             PPC_64B)                                                         \
 {                                                                             \
     gen_##name(ctx, 1, 0);                                                    \
 }                                                                             \
-GEN_HANDLER(name##3, opc1, opc2 | 0x11, 0xFF, 0x00000000, PPC_64B)            \
+GEN_HANDLER2(name##3, stringify(name), 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)
+static always_inline void gen_andi_T0_64 (DisasContext *ctx, uint64_t mask)
 {
+    if (mask >> 32)
+        gen_op_andi_T0_64(mask >> 32, mask & 0xFFFFFFFF);
+    else
+        gen_op_andi_T0(mask);
+}
+
+static always_inline void gen_andi_T1_64 (DisasContext *ctx, uint64_t mask)
+{
+    if (mask >> 32)
+        gen_op_andi_T1_64(mask >> 32, mask & 0xFFFFFFFF);
+    else
+        gen_op_andi_T1(mask);
+}
+
+static always_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);
+            gen_op_rotli64_T0(sh);
             goto do_store;
         } else if (likely(me == (63 - sh))) {
             gen_op_sli_T0(sh);
@@ -1250,20 +1515,20 @@
         }
     } else if (likely(me == 63)) {
         if (likely(sh == (64 - mb))) {
-            gen_op_srli_T0(mb);
+            gen_op_srli_T0_64(mb);
             goto do_store;
         }
     }
     gen_op_rotli64_T0(sh);
  do_mask:
-    gen_op_andi_T0(MASK(mb, me));
+    gen_andi_T0_64(ctx, 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)
+static always_inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
 {
     uint32_t sh, mb;
 
@@ -1273,7 +1538,7 @@
 }
 GEN_PPC64_R4(rldicl, 0x1E, 0x00);
 /* rldicr - rldicr. */
-static inline void gen_rldicr (DisasContext *ctx, int men, int shn)
+static always_inline void gen_rldicr (DisasContext *ctx, int men, int shn)
 {
     uint32_t sh, me;
 
@@ -1283,7 +1548,7 @@
 }
 GEN_PPC64_R4(rldicr, 0x1E, 0x02);
 /* rldic - rldic. */
-static inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
+static always_inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
 {
     uint32_t sh, mb;
 
@@ -1293,13 +1558,14 @@
 }
 GEN_PPC64_R4(rldic, 0x1E, 0x04);
 
-static inline void gen_rldnm (DisasContext *ctx, uint32_t mb, uint32_t me)
+static always_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_andi_T0_64(ctx, MASK(mb, me));
     }
     gen_op_store_T0_gpr(rA(ctx->opcode));
     if (unlikely(Rc(ctx->opcode) != 0))
@@ -1307,7 +1573,7 @@
 }
 
 /* rldcl - rldcl. */
-static inline void gen_rldcl (DisasContext *ctx, int mbn)
+static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
 {
     uint32_t mb;
 
@@ -1316,7 +1582,7 @@
 }
 GEN_PPC64_R2(rldcl, 0x1E, 0x08);
 /* rldcr - rldcr. */
-static inline void gen_rldcr (DisasContext *ctx, int men)
+static always_inline void gen_rldcr (DisasContext *ctx, int men)
 {
     uint32_t me;
 
@@ -1325,7 +1591,7 @@
 }
 GEN_PPC64_R2(rldcr, 0x1E, 0x09);
 /* rldimi - rldimi. */
-static inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
+static always_inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
 {
     uint64_t mask;
     uint32_t sh, mb;
@@ -1346,11 +1612,11 @@
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_load_gpr_T1(rA(ctx->opcode));
-    gen_op_rotli64_T0(SH(ctx->opcode));
+    gen_op_rotli64_T0(sh);
  do_mask:
     mask = MASK(mb, 63 - sh);
-    gen_op_andi_T0(mask);
-    gen_op_andi_T1(~mask);
+    gen_andi_T0_64(ctx, mask);
+    gen_andi_T1_64(ctx, ~mask);
     gen_op_or();
  do_store:
     gen_op_store_T0_gpr(rA(ctx->opcode));
@@ -1393,7 +1659,7 @@
 /* srad & srad. */
 __GEN_LOGICAL2(srad, 0x1A, 0x18, PPC_64B);
 /* sradi & sradi. */
-static inline void gen_sradi (DisasContext *ctx, int n)
+static always_inline void gen_sradi (DisasContext *ctx, int n)
 {
     uint64_t mask;
     int sh, mb, me;
@@ -1411,11 +1677,11 @@
     if (unlikely(Rc(ctx->opcode) != 0))
         gen_set_Rc0(ctx);
 }
-GEN_HANDLER(sradi0, 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
+GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
 {
     gen_sradi(ctx, 0);
 }
-GEN_HANDLER(sradi1, 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
+GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
 {
     gen_sradi(ctx, 1);
 }
@@ -1424,254 +1690,276 @@
 #endif
 
 /***                       Floating-Point arithmetic                       ***/
-#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat)                           \
-GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT)                   \
+#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type)           \
+GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)                        \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
-    gen_op_reset_scrfx();                                                     \
     gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
     gen_op_load_fpr_FT1(rC(ctx->opcode));                                     \
     gen_op_load_fpr_FT2(rB(ctx->opcode));                                     \
+    gen_reset_fpstatus();                                                     \
     gen_op_f##op();                                                           \
     if (isfloat) {                                                            \
         gen_op_frsp();                                                        \
     }                                                                         \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
-    if (unlikely(Rc(ctx->opcode) != 0))                                       \
-        gen_op_set_Rc1();                                                     \
+    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
 }
 
-#define GEN_FLOAT_ACB(name, op2)                                              \
-_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0);                                     \
-_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1);
+#define GEN_FLOAT_ACB(name, op2, set_fprf, type)                              \
+_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type);                     \
+_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
 
-#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat)                     \
-GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
+#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
+GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
-    gen_op_reset_scrfx();                                                     \
     gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
     gen_op_load_fpr_FT1(rB(ctx->opcode));                                     \
+    gen_reset_fpstatus();                                                     \
     gen_op_f##op();                                                           \
     if (isfloat) {                                                            \
         gen_op_frsp();                                                        \
     }                                                                         \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
-    if (unlikely(Rc(ctx->opcode) != 0))                                       \
-        gen_op_set_Rc1();                                                     \
+    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
 }
-#define GEN_FLOAT_AB(name, op2, inval)                                        \
-_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0);                               \
-_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1);
+#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type)                        \
+_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
+_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
 
-#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat)                     \
-GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
+#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type)     \
+GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type)                             \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
-    gen_op_reset_scrfx();                                                     \
     gen_op_load_fpr_FT0(rA(ctx->opcode));                                     \
     gen_op_load_fpr_FT1(rC(ctx->opcode));                                     \
+    gen_reset_fpstatus();                                                     \
     gen_op_f##op();                                                           \
     if (isfloat) {                                                            \
         gen_op_frsp();                                                        \
     }                                                                         \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
-    if (unlikely(Rc(ctx->opcode) != 0))                                       \
-        gen_op_set_Rc1();                                                     \
+    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
 }
-#define GEN_FLOAT_AC(name, op2, inval)                                        \
-_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0);                               \
-_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1);
+#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type)                        \
+_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type);               \
+_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
 
-#define GEN_FLOAT_B(name, op2, op3)                                           \
-GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT)                   \
+#define GEN_FLOAT_B(name, op2, op3, set_fprf, type)                           \
+GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)                        \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
-    gen_op_reset_scrfx();                                                     \
     gen_op_load_fpr_FT0(rB(ctx->opcode));                                     \
+    gen_reset_fpstatus();                                                     \
     gen_op_f##name();                                                         \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
-    if (unlikely(Rc(ctx->opcode) != 0))                                       \
-        gen_op_set_Rc1();                                                     \
+    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
 }
 
-#define GEN_FLOAT_BS(name, op1, op2)                                          \
-GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, PPC_FLOAT)                   \
+#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type)                          \
+GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)                        \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
-    gen_op_reset_scrfx();                                                     \
     gen_op_load_fpr_FT0(rB(ctx->opcode));                                     \
+    gen_reset_fpstatus();                                                     \
     gen_op_f##name();                                                         \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
-    if (unlikely(Rc(ctx->opcode) != 0))                                       \
-        gen_op_set_Rc1();                                                     \
+    gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0);                         \
 }
 
 /* fadd - fadds */
-GEN_FLOAT_AB(add, 0x15, 0x000007C0);
+GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
 /* fdiv - fdivs */
-GEN_FLOAT_AB(div, 0x12, 0x000007C0);
+GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
 /* fmul - fmuls */
-GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
+GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
 
-/* fres */ /* XXX: not in 601 */
-GEN_FLOAT_BS(res, 0x3B, 0x18);
+/* fre */
+GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
 
-/* frsqrte */ /* XXX: not in 601 */
-GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A);
+/* fres */
+GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
 
-/* fsel */ /* XXX: not in 601 */
-_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0);
+/* frsqrte */
+GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
+
+/* frsqrtes */
+static always_inline void gen_op_frsqrtes (void)
+{
+    gen_op_frsqrte();
+    gen_op_frsp();
+}
+GEN_FLOAT_BS(rsqrtes, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTES);
+
+/* fsel */
+_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
 /* fsub - fsubs */
-GEN_FLOAT_AB(sub, 0x14, 0x000007C0);
+GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
 /* Optional: */
 /* fsqrt */
-GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
+GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
-    gen_op_reset_scrfx();
     gen_op_load_fpr_FT0(rB(ctx->opcode));
+    gen_reset_fpstatus();
     gen_op_fsqrt();
     gen_op_store_FT0_fpr(rD(ctx->opcode));
-    if (unlikely(Rc(ctx->opcode) != 0))
-        gen_op_set_Rc1();
+    gen_compute_fprf(1, Rc(ctx->opcode) != 0);
 }
 
-GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
+GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
-    gen_op_reset_scrfx();
     gen_op_load_fpr_FT0(rB(ctx->opcode));
+    gen_reset_fpstatus();
     gen_op_fsqrt();
     gen_op_frsp();
     gen_op_store_FT0_fpr(rD(ctx->opcode));
-    if (unlikely(Rc(ctx->opcode) != 0))
-        gen_op_set_Rc1();
+    gen_compute_fprf(1, Rc(ctx->opcode) != 0);
 }
 
 /***                     Floating-Point multiply-and-add                   ***/
 /* fmadd - fmadds */
-GEN_FLOAT_ACB(madd, 0x1D);
+GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
 /* fmsub - fmsubs */
-GEN_FLOAT_ACB(msub, 0x1C);
+GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
 /* fnmadd - fnmadds */
-GEN_FLOAT_ACB(nmadd, 0x1F);
+GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
 /* fnmsub - fnmsubs */
-GEN_FLOAT_ACB(nmsub, 0x1E);
+GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
 
 /***                     Floating-Point round & convert                    ***/
 /* fctiw */
-GEN_FLOAT_B(ctiw, 0x0E, 0x00);
+GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
 /* fctiwz */
-GEN_FLOAT_B(ctiwz, 0x0F, 0x00);
+GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
 /* frsp */
-GEN_FLOAT_B(rsp, 0x0C, 0x00);
+GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
 #if defined(TARGET_PPC64)
 /* fcfid */
-GEN_FLOAT_B(cfid, 0x0E, 0x1A);
+GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
 /* fctid */
-GEN_FLOAT_B(ctid, 0x0E, 0x19);
+GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
 /* fctidz */
-GEN_FLOAT_B(ctidz, 0x0F, 0x19);
+GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
 #endif
 
+/* frin */
+GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
+/* friz */
+GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
+/* frip */
+GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
+/* frim */
+GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
+
 /***                         Floating-Point compare                        ***/
 /* fcmpo */
 GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
-    gen_op_reset_scrfx();
     gen_op_load_fpr_FT0(rA(ctx->opcode));
     gen_op_load_fpr_FT1(rB(ctx->opcode));
+    gen_reset_fpstatus();
     gen_op_fcmpo();
     gen_op_store_T0_crf(crfD(ctx->opcode));
+    gen_op_float_check_status();
 }
 
 /* fcmpu */
 GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
-    gen_op_reset_scrfx();
     gen_op_load_fpr_FT0(rA(ctx->opcode));
     gen_op_load_fpr_FT1(rB(ctx->opcode));
+    gen_reset_fpstatus();
     gen_op_fcmpu();
     gen_op_store_T0_crf(crfD(ctx->opcode));
+    gen_op_float_check_status();
 }
 
 /***                         Floating-point move                           ***/
 /* fabs */
-GEN_FLOAT_B(abs, 0x08, 0x08);
+/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
+GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
 
 /* fmr  - fmr. */
+/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
 GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
-    gen_op_reset_scrfx();
     gen_op_load_fpr_FT0(rB(ctx->opcode));
     gen_op_store_FT0_fpr(rD(ctx->opcode));
-    if (unlikely(Rc(ctx->opcode) != 0))
-        gen_op_set_Rc1();
+    gen_compute_fprf(0, Rc(ctx->opcode) != 0);
 }
 
 /* fnabs */
-GEN_FLOAT_B(nabs, 0x08, 0x04);
+/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
+GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
 /* fneg */
-GEN_FLOAT_B(neg, 0x08, 0x01);
+/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
+GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
 
 /***                  Floating-Point status & ctrl register                ***/
 /* mcrfs */
 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
 {
+    int bfa;
+
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
-    gen_op_load_fpscr_T0(crfS(ctx->opcode));
+    gen_optimize_fprf();
+    bfa = 4 * (7 - crfS(ctx->opcode));
+    gen_op_load_fpscr_T0(bfa);
     gen_op_store_T0_crf(crfD(ctx->opcode));
-    gen_op_clear_fpscr(crfS(ctx->opcode));
+    gen_op_fpscr_resetbit(~(0xF << bfa));
 }
 
 /* mffs */
 GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
-    gen_op_load_fpscr();
+    gen_optimize_fprf();
+    gen_reset_fpstatus();
+    gen_op_load_fpscr_FT0();
     gen_op_store_FT0_fpr(rD(ctx->opcode));
-    if (unlikely(Rc(ctx->opcode) != 0))
-        gen_op_set_Rc1();
+    gen_compute_fprf(0, Rc(ctx->opcode) != 0);
 }
 
 /* mtfsb0 */
@@ -1680,15 +1968,18 @@
     uint8_t crb;
 
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
-    crb = crbD(ctx->opcode) >> 2;
-    gen_op_load_fpscr_T0(crb);
-    gen_op_andi_T0(~(1 << (crbD(ctx->opcode) & 0x03)));
-    gen_op_store_T0_fpscr(crb);
-    if (unlikely(Rc(ctx->opcode) != 0))
-        gen_op_set_Rc1();
+    crb = 32 - (crbD(ctx->opcode) >> 2);
+    gen_optimize_fprf();
+    gen_reset_fpstatus();
+    if (likely(crb != 30 && crb != 29))
+        gen_op_fpscr_resetbit(~(1 << crb));
+    if (unlikely(Rc(ctx->opcode) != 0)) {
+        gen_op_load_fpcc();
+        gen_op_set_Rc0();
+    }
 }
 
 /* mtfsb1 */
@@ -1697,50 +1988,73 @@
     uint8_t crb;
 
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
-    crb = crbD(ctx->opcode) >> 2;
-    gen_op_load_fpscr_T0(crb);
-    gen_op_ori(1 << (crbD(ctx->opcode) & 0x03));
-    gen_op_store_T0_fpscr(crb);
-    if (unlikely(Rc(ctx->opcode) != 0))
-        gen_op_set_Rc1();
+    crb = 32 - (crbD(ctx->opcode) >> 2);
+    gen_optimize_fprf();
+    gen_reset_fpstatus();
+    /* XXX: we pretend we can only do IEEE floating-point computations */
+    if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI))
+        gen_op_fpscr_setbit(crb);
+    if (unlikely(Rc(ctx->opcode) != 0)) {
+        gen_op_load_fpcc();
+        gen_op_set_Rc0();
+    }
+    /* We can raise a differed exception */
+    gen_op_float_check_status();
 }
 
 /* mtfsf */
 GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
+    gen_optimize_fprf();
     gen_op_load_fpr_FT0(rB(ctx->opcode));
+    gen_reset_fpstatus();
     gen_op_store_fpscr(FM(ctx->opcode));
-    if (unlikely(Rc(ctx->opcode) != 0))
-        gen_op_set_Rc1();
+    if (unlikely(Rc(ctx->opcode) != 0)) {
+        gen_op_load_fpcc();
+        gen_op_set_Rc0();
+    }
+    /* We can raise a differed exception */
+    gen_op_float_check_status();
 }
 
 /* mtfsfi */
 GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
 {
+    int bf, sh;
+
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
-    gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode));
-    if (unlikely(Rc(ctx->opcode) != 0))
-        gen_op_set_Rc1();
+    bf = crbD(ctx->opcode) >> 2;
+    sh = 7 - bf;
+    gen_optimize_fprf();
+    gen_op_set_FT0(FPIMM(ctx->opcode) << (4 * sh));
+    gen_reset_fpstatus();
+    gen_op_store_fpscr(1 << sh);
+    if (unlikely(Rc(ctx->opcode) != 0)) {
+        gen_op_load_fpcc();
+        gen_op_set_Rc0();
+    }
+    /* We can raise a differed exception */
+    gen_op_float_check_status();
 }
 
 /***                           Addressing modes                            ***/
 /* Register indirect with immediate index : EA = (rA|0) + SIMM */
-static inline void gen_addr_imm_index (DisasContext *ctx, int maskl)
+static always_inline void gen_addr_imm_index (DisasContext *ctx,
+                                              target_long maskl)
 {
     target_long simm = SIMM(ctx->opcode);
 
-    if (maskl)
-        simm &= ~0x03;
+    simm &= ~maskl;
     if (rA(ctx->opcode) == 0) {
         gen_set_T0(simm);
     } else {
@@ -1753,7 +2067,7 @@
 #endif
 }
 
-static inline void gen_addr_reg_index (DisasContext *ctx)
+static always_inline void gen_addr_reg_index (DisasContext *ctx)
 {
     if (rA(ctx->opcode) == 0) {
         gen_op_load_gpr_T0(rB(ctx->opcode));
@@ -1767,7 +2081,7 @@
 #endif
 }
 
-static inline void gen_addr_register (DisasContext *ctx)
+static always_inline void gen_addr_register (DisasContext *ctx)
 {
     if (rA(ctx->opcode) == 0) {
         gen_op_reset_T0();
@@ -1783,6 +2097,7 @@
 #define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
 #if defined(CONFIG_USER_ONLY)
 #if defined(TARGET_PPC64)
+/* User mode only - 64 bits */
 #define OP_LD_TABLE(width)                                                    \
 static GenOpFunc *gen_op_l##width[] = {                                       \
     &gen_op_l##width##_raw,                                                   \
@@ -1801,6 +2116,7 @@
 #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
+/* User mode only - 32 bits */
 #define OP_LD_TABLE(width)                                                    \
 static GenOpFunc *gen_op_l##width[] = {                                       \
     &gen_op_l##width##_raw,                                                   \
@@ -1817,14 +2133,53 @@
 #define gen_op_lbz_le_raw gen_op_lbz_raw
 #else
 #if defined(TARGET_PPC64)
+#if defined(TARGET_PPC64H)
+/* Full system - 64 bits with hypervisor mode */
 #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##_64_user,                                               \
+    &gen_op_l##width##_le_64_user,                                            \
     &gen_op_l##width##_kernel,                                                \
     &gen_op_l##width##_le_kernel,                                             \
+    &gen_op_l##width##_64_kernel,                                             \
+    &gen_op_l##width##_le_64_kernel,                                          \
+    &gen_op_l##width##_hypv,                                                  \
+    &gen_op_l##width##_le_hypv,                                               \
+    &gen_op_l##width##_64_hypv,                                               \
+    &gen_op_l##width##_le_64_hypv,                                            \
+};
+#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##_64_user,                                              \
+    &gen_op_st##width##_le_64_user,                                           \
+    &gen_op_st##width##_kernel,                                               \
+    &gen_op_st##width##_le_kernel,                                            \
+    &gen_op_st##width##_64_kernel,                                            \
+    &gen_op_st##width##_le_64_kernel,                                         \
+    &gen_op_st##width##_hypv,                                                 \
+    &gen_op_st##width##_le_hypv,                                              \
+    &gen_op_st##width##_64_hypv,                                              \
+    &gen_op_st##width##_le_64_hypv,                                           \
+};
+/* Byte access routine are endian safe */
+#define gen_op_stb_le_hypv      gen_op_stb_64_hypv
+#define gen_op_lbz_le_hypv      gen_op_lbz_64_hypv
+#define gen_op_stb_le_64_hypv   gen_op_stb_64_hypv
+#define gen_op_lbz_le_64_hypv   gen_op_lbz_64_hypv
+#else
+/* Full system - 64 bits */
+#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##_64_user,                                               \
     &gen_op_l##width##_le_64_user,                                            \
+    &gen_op_l##width##_kernel,                                                \
+    &gen_op_l##width##_le_kernel,                                             \
     &gen_op_l##width##_64_kernel,                                             \
     &gen_op_l##width##_le_64_kernel,                                          \
 };
@@ -1832,19 +2187,21 @@
 static GenOpFunc *gen_op_st##width[] = {                                      \
     &gen_op_st##width##_user,                                                 \
     &gen_op_st##width##_le_user,                                              \
+    &gen_op_st##width##_64_user,                                              \
+    &gen_op_st##width##_le_64_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,                                         \
 };
+#endif
 /* 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_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
+/* Full system - 32 bits */
 #define OP_LD_TABLE(width)                                                    \
 static GenOpFunc *gen_op_l##width[] = {                                       \
     &gen_op_l##width##_user,                                                  \
@@ -1861,8 +2218,8 @@
 };
 #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_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
@@ -1880,11 +2237,11 @@
 {                                                                             \
     if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                  rA(ctx->opcode) == rD(ctx->opcode))) {                       \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     if (type == PPC_64B)                                                      \
-        gen_addr_imm_index(ctx, 1);                                           \
+        gen_addr_imm_index(ctx, 0x03);                                        \
     else                                                                      \
         gen_addr_imm_index(ctx, 0);                                           \
     op_ldst(l##width);                                                        \
@@ -1897,7 +2254,7 @@
 {                                                                             \
     if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                  rA(ctx->opcode) == rD(ctx->opcode))) {                       \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -1945,11 +2302,11 @@
     if (Rc(ctx->opcode)) {
         if (unlikely(rA(ctx->opcode) == 0 ||
                      rA(ctx->opcode) == rD(ctx->opcode))) {
-            RET_INVAL(ctx);
+            GEN_EXCP_INVAL(ctx);
             return;
         }
     }
-    gen_addr_imm_index(ctx, 1);
+    gen_addr_imm_index(ctx, 0x03);
     if (ctx->opcode & 0x02) {
         /* lwa (lwau is undefined) */
         op_ldst(lwa);
@@ -1961,7 +2318,39 @@
     if (Rc(ctx->opcode))
         gen_op_store_T0_gpr(rA(ctx->opcode));
 }
+/* lq */
+GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
+{
+#if defined(CONFIG_USER_ONLY)
+    GEN_EXCP_PRIVOPC(ctx);
+#else
+    int ra, rd;
+
+    /* Restore CPU state */
+    if (unlikely(ctx->supervisor == 0)) {
+        GEN_EXCP_PRIVOPC(ctx);
+        return;
+    }
+    ra = rA(ctx->opcode);
+    rd = rD(ctx->opcode);
+    if (unlikely((rd & 1) || rd == ra)) {
+        GEN_EXCP_INVAL(ctx);
+        return;
+    }
+    if (unlikely(ctx->mem_idx & 1)) {
+        /* Little-endian mode is not handled */
+        GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
+        return;
+    }
+    gen_addr_imm_index(ctx, 0x0F);
+    op_ldst(ld);
+    gen_op_store_T1_gpr(rd);
+    gen_op_addi(8);
+    op_ldst(ld);
+    gen_op_store_T1_gpr(rd + 1);
 #endif
+}
+#endif
 
 /***                              Integer store                            ***/
 #define GEN_ST(width, opc, type)                                              \
@@ -1976,11 +2365,11 @@
 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
 {                                                                             \
     if (unlikely(rA(ctx->opcode) == 0)) {                                     \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     if (type == PPC_64B)                                                      \
-        gen_addr_imm_index(ctx, 1);                                           \
+        gen_addr_imm_index(ctx, 0x03);                                        \
     else                                                                      \
         gen_addr_imm_index(ctx, 0);                                           \
     gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
@@ -1992,7 +2381,7 @@
 GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                \
 {                                                                             \
     if (unlikely(rA(ctx->opcode) == 0)) {                                     \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -2026,19 +2415,50 @@
 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)
+GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
 {
-    if (Rc(ctx->opcode)) {
-        if (unlikely(rA(ctx->opcode) == 0)) {
-            RET_INVAL(ctx);
+    int rs;
+
+    rs = rS(ctx->opcode);
+    if ((ctx->opcode & 0x3) == 0x2) {
+#if defined(CONFIG_USER_ONLY)
+        GEN_EXCP_PRIVOPC(ctx);
+#else
+        /* stq */
+        if (unlikely(ctx->supervisor == 0)) {
+            GEN_EXCP_PRIVOPC(ctx);
             return;
         }
+        if (unlikely(rs & 1)) {
+            GEN_EXCP_INVAL(ctx);
+            return;
+        }
+        if (unlikely(ctx->mem_idx & 1)) {
+            /* Little-endian mode is not handled */
+            GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
+            return;
+        }
+        gen_addr_imm_index(ctx, 0x03);
+        gen_op_load_gpr_T1(rs);
+        op_ldst(std);
+        gen_op_addi(8);
+        gen_op_load_gpr_T1(rs + 1);
+        op_ldst(std);
+#endif
+    } else {
+        /* std / stdu */
+        if (Rc(ctx->opcode)) {
+            if (unlikely(rA(ctx->opcode) == 0)) {
+                GEN_EXCP_INVAL(ctx);
+                return;
+            }
+        }
+        gen_addr_imm_index(ctx, 0x03);
+        gen_op_load_gpr_T1(rs);
+        op_ldst(std);
+        if (Rc(ctx->opcode))
+            gen_op_store_T0_gpr(rA(ctx->opcode));
     }
-    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               ***/
@@ -2057,51 +2477,61 @@
 
 /***                    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)
+/* User-mode only */
 static GenOpFunc1 *gen_op_lmw[] = {
     &gen_op_lmw_raw,
     &gen_op_lmw_le_raw,
+#if defined(TARGET_PPC64)
     &gen_op_lmw_64_raw,
     &gen_op_lmw_le_64_raw,
+#endif
 };
 static GenOpFunc1 *gen_op_stmw[] = {
+    &gen_op_stmw_raw,
+    &gen_op_stmw_le_raw,
+#if defined(TARGET_PPC64)
     &gen_op_stmw_64_raw,
     &gen_op_stmw_le_64_raw,
+#endif
 };
 #else
+#if defined(TARGET_PPC64)
+/* Full system - 64 bits mode */
 static GenOpFunc1 *gen_op_lmw[] = {
     &gen_op_lmw_user,
     &gen_op_lmw_le_user,
+    &gen_op_lmw_64_user,
+    &gen_op_lmw_le_64_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,
+#if defined(TARGET_PPC64H)
+    &gen_op_lmw_hypv,
+    &gen_op_lmw_le_hypv,
+    &gen_op_lmw_64_hypv,
+    &gen_op_lmw_le_64_hypv,
+#endif
 };
 static GenOpFunc1 *gen_op_stmw[] = {
     &gen_op_stmw_user,
     &gen_op_stmw_le_user,
+    &gen_op_stmw_64_user,
+    &gen_op_stmw_le_64_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,
-};
+#if defined(TARGET_PPC64H)
+    &gen_op_stmw_hypv,
+    &gen_op_stmw_le_hypv,
+    &gen_op_stmw_64_hypv,
+    &gen_op_stmw_le_64_hypv,
 #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,
-};
 #else
+/* Full system - 32 bits mode */
 static GenOpFunc1 *gen_op_lmw[] = {
     &gen_op_lmw_user,
     &gen_op_lmw_le_user,
@@ -2138,73 +2568,85 @@
 /***                    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)
+/* User-mode only */
 static GenOpFunc1 *gen_op_lswi[] = {
     &gen_op_lswi_raw,
     &gen_op_lswi_le_raw,
+#if defined(TARGET_PPC64)
     &gen_op_lswi_64_raw,
     &gen_op_lswi_le_64_raw,
+#endif
 };
 static GenOpFunc3 *gen_op_lswx[] = {
     &gen_op_lswx_raw,
     &gen_op_lswx_le_raw,
+#if defined(TARGET_PPC64)
     &gen_op_lswx_64_raw,
     &gen_op_lswx_le_64_raw,
+#endif
 };
 static GenOpFunc1 *gen_op_stsw[] = {
     &gen_op_stsw_raw,
     &gen_op_stsw_le_raw,
+#if defined(TARGET_PPC64)
     &gen_op_stsw_64_raw,
     &gen_op_stsw_le_64_raw,
+#endif
 };
 #else
+#if defined(TARGET_PPC64)
+/* Full system - 64 bits mode */
 static GenOpFunc1 *gen_op_lswi[] = {
     &gen_op_lswi_user,
     &gen_op_lswi_le_user,
+    &gen_op_lswi_64_user,
+    &gen_op_lswi_le_64_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,
+#if defined(TARGET_PPC64H)
+    &gen_op_lswi_hypv,
+    &gen_op_lswi_le_hypv,
+    &gen_op_lswi_64_hypv,
+    &gen_op_lswi_le_64_hypv,
+#endif
 };
 static GenOpFunc3 *gen_op_lswx[] = {
     &gen_op_lswx_user,
     &gen_op_lswx_le_user,
+    &gen_op_lswx_64_user,
+    &gen_op_lswx_le_64_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,
+#if defined(TARGET_PPC64H)
+    &gen_op_lswx_hypv,
+    &gen_op_lswx_le_hypv,
+    &gen_op_lswx_64_hypv,
+    &gen_op_lswx_le_64_hypv,
+#endif
 };
 static GenOpFunc1 *gen_op_stsw[] = {
     &gen_op_stsw_user,
     &gen_op_stsw_le_user,
+    &gen_op_stsw_64_user,
+    &gen_op_stsw_le_64_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,
-};
+#if defined(TARGET_PPC64H)
+    &gen_op_stsw_hypv,
+    &gen_op_stsw_le_hypv,
+    &gen_op_stsw_64_hypv,
+    &gen_op_stsw_le_64_hypv,
 #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
+/* Full system - 32 bits mode */
 static GenOpFunc1 *gen_op_lswi[] = {
     &gen_op_lswi_user,
     &gen_op_lswi_le_user,
@@ -2245,7 +2687,8 @@
     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);
+        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
+                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX);
         return;
     }
     /* NIP cannot be restored if the memory exception comes from an helper */
@@ -2297,64 +2740,73 @@
 
 /***                        Memory synchronisation                         ***/
 /* eieio */
-GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM_EIEIO)
+GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
 {
 }
 
 /* isync */
-GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FF0801, PPC_MEM)
+GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
 {
+    GEN_STOP(ctx);
 }
 
 #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)
+/* User-mode only */
 static GenOpFunc *gen_op_lwarx[] = {
     &gen_op_lwarx_raw,
     &gen_op_lwarx_le_raw,
+#if defined(TARGET_PPC64)
     &gen_op_lwarx_64_raw,
     &gen_op_lwarx_le_64_raw,
+#endif
 };
 static GenOpFunc *gen_op_stwcx[] = {
     &gen_op_stwcx_raw,
     &gen_op_stwcx_le_raw,
+#if defined(TARGET_PPC64)
     &gen_op_stwcx_64_raw,
     &gen_op_stwcx_le_64_raw,
+#endif
 };
 #else
+#if defined(TARGET_PPC64)
+/* Full system - 64 bits mode */
 static GenOpFunc *gen_op_lwarx[] = {
     &gen_op_lwarx_user,
     &gen_op_lwarx_le_user,
+    &gen_op_lwarx_64_user,
+    &gen_op_lwarx_le_64_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,
+#if defined(TARGET_PPC64H)
+    &gen_op_lwarx_hypv,
+    &gen_op_lwarx_le_hypv,
+    &gen_op_lwarx_64_hypv,
+    &gen_op_lwarx_le_64_hypv,
+#endif
 };
 static GenOpFunc *gen_op_stwcx[] = {
     &gen_op_stwcx_user,
     &gen_op_stwcx_le_user,
+    &gen_op_stwcx_64_user,
+    &gen_op_stwcx_le_64_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,
-};
+#if defined(TARGET_PPC64H)
+    &gen_op_stwcx_hypv,
+    &gen_op_stwcx_le_hypv,
+    &gen_op_stwcx_64_hypv,
+    &gen_op_stwcx_le_64_hypv,
 #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
+/* Full system - 32 bits mode */
 static GenOpFunc *gen_op_lwarx[] = {
     &gen_op_lwarx_user,
     &gen_op_lwarx_le_user,
@@ -2373,14 +2825,18 @@
 /* lwarx */
 GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
 {
+    /* 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_lwarx();
     gen_op_store_T1_gpr(rD(ctx->opcode));
 }
 
 /* stwcx. */
-GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
+GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
 {
+    /* 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_gpr_T1(rS(ctx->opcode));
     op_stwcx();
@@ -2390,6 +2846,7 @@
 #define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])()
 #define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])()
 #if defined(CONFIG_USER_ONLY)
+/* User-mode only */
 static GenOpFunc *gen_op_ldarx[] = {
     &gen_op_ldarx_raw,
     &gen_op_ldarx_le_raw,
@@ -2403,39 +2860,56 @@
     &gen_op_stdcx_le_64_raw,
 };
 #else
+/* Full system */
 static GenOpFunc *gen_op_ldarx[] = {
     &gen_op_ldarx_user,
     &gen_op_ldarx_le_user,
+    &gen_op_ldarx_64_user,
+    &gen_op_ldarx_le_64_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,
+#if defined(TARGET_PPC64H)
+    &gen_op_ldarx_hypv,
+    &gen_op_ldarx_le_hypv,
+    &gen_op_ldarx_64_hypv,
+    &gen_op_ldarx_le_64_hypv,
+#endif
 };
 static GenOpFunc *gen_op_stdcx[] = {
     &gen_op_stdcx_user,
     &gen_op_stdcx_le_user,
+    &gen_op_stdcx_64_user,
+    &gen_op_stdcx_le_64_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,
+#if defined(TARGET_PPC64H)
+    &gen_op_stdcx_hypv,
+    &gen_op_stdcx_le_hypv,
+    &gen_op_stdcx_64_hypv,
+    &gen_op_stdcx_le_64_hypv,
+#endif
 };
 #endif
 
 /* ldarx */
-GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_RES)
+GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
 {
+    /* 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_ldarx();
     gen_op_store_T1_gpr(rD(ctx->opcode));
 }
 
 /* stdcx. */
-GEN_HANDLER(stdcx_, 0x1F, 0x16, 0x06, 0x00000000, PPC_RES)
+GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
 {
+    /* 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_gpr_T1(rS(ctx->opcode));
     op_stdcx();
@@ -2443,16 +2917,24 @@
 #endif /* defined(TARGET_PPC64) */
 
 /* sync */
-GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM_SYNC)
+GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC)
 {
 }
 
+/* wait */
+GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
+{
+    /* Stop translation, as the CPU is supposed to sleep from now */
+    gen_op_wait();
+    GEN_EXCP(ctx, EXCP_HLT, 1);
+}
+
 /***                         Floating-point load                           ***/
-#define GEN_LDF(width, opc)                                                   \
-GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                 \
+#define GEN_LDF(width, opc, type)                                             \
+GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type)                      \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_imm_index(ctx, 0);                                               \
@@ -2460,15 +2942,15 @@
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
 }
 
-#define GEN_LDUF(width, opc)                                                  \
-GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)              \
+#define GEN_LDUF(width, opc, type)                                            \
+GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                   \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     if (unlikely(rA(ctx->opcode) == 0)) {                                     \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_imm_index(ctx, 0);                                               \
@@ -2477,15 +2959,15 @@
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
 
-#define GEN_LDUXF(width, opc)                                                 \
-GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)             \
+#define GEN_LDUXF(width, opc, type)                                           \
+GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, type)                  \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     if (unlikely(rA(ctx->opcode) == 0)) {                                     \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -2494,11 +2976,11 @@
     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)             \
+#define GEN_LDXF(width, opc2, opc3, type)                                     \
+GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type)                  \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -2506,24 +2988,24 @@
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
 }
 
-#define GEN_LDFS(width, op)                                                   \
+#define GEN_LDFS(width, op, type)                                             \
 OP_LD_TABLE(width);                                                           \
-GEN_LDF(width, op | 0x20);                                                    \
-GEN_LDUF(width, op | 0x21);                                                   \
-GEN_LDUXF(width, op | 0x01);                                                  \
-GEN_LDXF(width, 0x17, op | 0x00)
+GEN_LDF(width, op | 0x20, type);                                              \
+GEN_LDUF(width, op | 0x21, type);                                             \
+GEN_LDUXF(width, op | 0x01, type);                                            \
+GEN_LDXF(width, 0x17, op | 0x00, type)
 
 /* lfd lfdu lfdux lfdx */
-GEN_LDFS(fd, 0x12);
+GEN_LDFS(fd, 0x12, PPC_FLOAT);
 /* lfs lfsu lfsux lfsx */
-GEN_LDFS(fs, 0x10);
+GEN_LDFS(fs, 0x10, PPC_FLOAT);
 
 /***                         Floating-point store                          ***/
-#define GEN_STF(width, opc)                                                   \
-GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                \
+#define GEN_STF(width, opc, type)                                             \
+GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type)                     \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_imm_index(ctx, 0);                                               \
@@ -2531,15 +3013,15 @@
     op_ldst(st##width);                                                       \
 }
 
-#define GEN_STUF(width, opc)                                                  \
-GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)             \
+#define GEN_STUF(width, opc, type)                                            \
+GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     if (unlikely(rA(ctx->opcode) == 0)) {                                     \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_imm_index(ctx, 0);                                               \
@@ -2548,15 +3030,15 @@
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
 
-#define GEN_STUXF(width, opc)                                                 \
-GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)            \
+#define GEN_STUXF(width, opc, type)                                           \
+GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, type)                 \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     if (unlikely(rA(ctx->opcode) == 0)) {                                     \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -2565,11 +3047,11 @@
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
 
-#define GEN_STXF(width, opc2, opc3)                                           \
-GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT)            \
+#define GEN_STXF(width, opc2, opc3, type)                                     \
+GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type)                 \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -2577,33 +3059,26 @@
     op_ldst(st##width);                                                       \
 }
 
-#define GEN_STFS(width, op)                                                   \
+#define GEN_STFS(width, op, type)                                             \
 OP_ST_TABLE(width);                                                           \
-GEN_STF(width, op | 0x20);                                                    \
-GEN_STUF(width, op | 0x21);                                                   \
-GEN_STUXF(width, op | 0x01);                                                  \
-GEN_STXF(width, 0x17, op | 0x00)
+GEN_STF(width, op | 0x20, type);                                              \
+GEN_STUF(width, op | 0x21, type);                                             \
+GEN_STUXF(width, op | 0x01, type);                                            \
+GEN_STXF(width, 0x17, op | 0x00, type)
 
 /* stfd stfdu stfdux stfdx */
-GEN_STFS(fd, 0x16);
+GEN_STFS(fd, 0x16, PPC_FLOAT);
 /* stfs stfsu stfsux stfsx */
-GEN_STFS(fs, 0x14);
+GEN_STFS(fs, 0x14, PPC_FLOAT);
 
 /* Optional: */
 /* stfiwx */
-GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
-{
-    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);
-}
+OP_ST_TABLE(fiwx);
+GEN_STXF(fiwx, 0x17, 0x1E, PPC_FLOAT_STFIWX);
 
 /***                                Branch                                 ***/
-static inline void gen_goto_tb (DisasContext *ctx, int n, target_ulong dest)
+static always_inline void gen_goto_tb (DisasContext *ctx, int n,
+                                       target_ulong dest)
 {
     TranslationBlock *tb;
     tb = ctx->tb;
@@ -2638,6 +3113,16 @@
     }
 }
 
+static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
+{
+#if defined(TARGET_PPC64)
+    if (ctx->sf_mode != 0 && (nip >> 32))
+        gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
+    else
+#endif
+        gen_op_setlr(ctx->nip);
+}
+
 /* b ba bl bla */
 GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
 {
@@ -2654,23 +3139,21 @@
         target = ctx->nip + li - 4;
     else
         target = li;
-    if (LK(ctx->opcode)) {
 #if defined(TARGET_PPC64)
-        if (ctx->sf_mode)
-            gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
-        else
+    if (!ctx->sf_mode)
+        target = (uint32_t)target;
 #endif
-            gen_op_setlr(ctx->nip);
-    }
+    if (LK(ctx->opcode))
+        gen_setlr(ctx, ctx->nip);
     gen_goto_tb(ctx, 0, target);
-    ctx->exception = EXCP_BRANCH;
+    ctx->exception = POWERPC_EXCP_BRANCH;
 }
 
 #define BCOND_IM  0
 #define BCOND_LR  1
 #define BCOND_CTR 2
 
-static inline void gen_bcond (DisasContext *ctx, int type)
+static always_inline void gen_bcond (DisasContext *ctx, int type)
 {
     target_ulong target = 0;
     target_ulong li;
@@ -2688,6 +3171,10 @@
         } else {
             target = li;
         }
+#if defined(TARGET_PPC64)
+        if (!ctx->sf_mode)
+            target = (uint32_t)target;
+#endif
         break;
     case BCOND_CTR:
         gen_op_movl_T1_ctr();
@@ -2697,14 +3184,8 @@
         gen_op_movl_T1_lr();
         break;
     }
-    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 (LK(ctx->opcode))
+        gen_setlr(ctx, ctx->nip);
     if (bo & 0x10) {
         /* No CR condition */
         switch (bo & 0x6) {
@@ -2729,6 +3210,7 @@
         case 6:
             if (type == BCOND_IM) {
                 gen_goto_tb(ctx, 0, target);
+                goto out;
             } else {
 #if defined(TARGET_PPC64)
                 if (ctx->sf_mode)
@@ -2737,8 +3219,9 @@
 #endif
                     gen_op_b_T1();
                 gen_op_reset_T0();
+                goto no_test;
             }
-            goto no_test;
+            break;
         }
     } else {
         mask = 1 << (3 - (bi & 0x03));
@@ -2812,7 +3295,8 @@
             gen_op_debug();
         gen_op_exit_tb();
     }
-    ctx->exception = EXCP_BRANCH;
+ out:
+    ctx->exception = POWERPC_EXCP_BRANCH;
 }
 
 GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
@@ -2873,45 +3357,66 @@
 GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     /* Restore CPU state */
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_rfi();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 
 #if defined(TARGET_PPC64)
-GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_FLOW)
+GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     /* Restore CPU state */
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_rfid();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 #endif
 
-/* sc */
-GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
+#if defined(TARGET_PPC64H)
+GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64B)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_EXCP(ctx, EXCP_SYSCALL_USER, 0);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
-    RET_EXCP(ctx, EXCP_SYSCALL, 0);
+    /* Restore CPU state */
+    if (unlikely(ctx->supervisor <= 1)) {
+        GEN_EXCP_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_hrfid();
+    GEN_SYNC(ctx);
 #endif
 }
+#endif
 
+/* sc */
+#if defined(CONFIG_USER_ONLY)
+#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
+#else
+#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
+#endif
+GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
+{
+    uint32_t lev;
+
+    lev = (ctx->opcode >> 5) & 0x7F;
+    GEN_EXCP(ctx, POWERPC_SYSCALL, lev);
+}
+
 /***                                Trap                                   ***/
 /* tw */
 GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
@@ -2986,10 +3491,10 @@
 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_load_msr();
@@ -2997,7 +3502,7 @@
 #endif
 }
 
-#if 0
+#if 1
 #define SPR_NOACCESS ((void *)(-1))
 #else
 static void spr_noaccess (void *opaque, int sprn)
@@ -3009,12 +3514,17 @@
 #endif
 
 /* mfspr */
-static inline void gen_op_mfspr (DisasContext *ctx)
+static always_inline void gen_op_mfspr (DisasContext *ctx)
 {
     void (*read_cb)(void *opaque, int sprn);
     uint32_t sprn = SPR(ctx->opcode);
 
 #if !defined(CONFIG_USER_ONLY)
+#if defined(TARGET_PPC64H)
+    if (ctx->supervisor == 2)
+        read_cb = ctx->spr_cb[sprn].hea_read;
+    else
+#endif
     if (ctx->supervisor)
         read_cb = ctx->spr_cb[sprn].oea_read;
     else
@@ -3031,7 +3541,7 @@
                         sprn, sprn);
             }
             printf("Trying to read privileged spr %d %03x\n", sprn, sprn);
-            RET_PRIVREG(ctx);
+            GEN_EXCP_PRIVREG(ctx);
         }
     } else {
         /* Not defined */
@@ -3040,7 +3550,8 @@
                     sprn, sprn);
         }
         printf("Trying to read invalid spr %d %03x\n", sprn, sprn);
-        RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
+        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
+                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
     }
 }
 
@@ -3050,7 +3561,7 @@
 }
 
 /* mftb */
-GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_TB)
+GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
 {
     gen_op_mfspr(ctx);
 }
@@ -3074,20 +3585,30 @@
 
 /* mtmsr */
 #if defined(TARGET_PPC64)
-GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_MISC)
+GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
-    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);
+    if (ctx->opcode & 0x00010000) {
+        /* Special form that does not need any synchronisation */
+        gen_op_update_riee();
+    } else {
+        /* XXX: we need to update nip before the store
+         *      if we enter power saving mode, we will exit the loop
+         *      directly from ppc_store_msr
+         */
+        gen_update_nip(ctx, ctx->nip);
+        gen_op_store_msr();
+        /* Must stop the translation as machine state (may have) changed */
+        /* Note that mtmsr is not always defined as context-synchronizing */
+        ctx->exception = POWERPC_EXCP_STOP;
+    }
 #endif
 }
 #endif
@@ -3095,22 +3616,32 @@
 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
-    gen_update_nip(ctx, ctx->nip);
     gen_op_load_gpr_T0(rS(ctx->opcode));
+    if (ctx->opcode & 0x00010000) {
+        /* Special form that does not need any synchronisation */
+        gen_op_update_riee();
+    } else {
+        /* XXX: we need to update nip before the store
+         *      if we enter power saving mode, we will exit the loop
+         *      directly from ppc_store_msr
+         */
+        gen_update_nip(ctx, ctx->nip);
 #if defined(TARGET_PPC64)
-    if (!ctx->sf_mode)
-        gen_op_store_msr_32();
-    else
+        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);
+            gen_op_store_msr();
+        /* Must stop the translation as machine state (may have) changed */
+        /* Note that mtmsrd is not always defined as context-synchronizing */
+        ctx->exception = POWERPC_EXCP_STOP;
+    }
 #endif
 }
 
@@ -3121,6 +3652,11 @@
     uint32_t sprn = SPR(ctx->opcode);
 
 #if !defined(CONFIG_USER_ONLY)
+#if defined(TARGET_PPC64H)
+    if (ctx->supervisor == 2)
+        write_cb = ctx->spr_cb[sprn].hea_write;
+    else
+#endif
     if (ctx->supervisor)
         write_cb = ctx->spr_cb[sprn].oea_write;
     else
@@ -3137,7 +3673,7 @@
                         sprn, sprn);
             }
             printf("Trying to write privileged spr %d %03x\n", sprn, sprn);
-            RET_PRIVREG(ctx);
+            GEN_EXCP_PRIVREG(ctx);
         }
     } else {
         /* Not defined */
@@ -3146,18 +3682,16 @@
                     sprn, sprn);
         }
         printf("Trying to write invalid spr %d %03x\n", sprn, sprn);
-        RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
+        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
+                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
     }
 }
 
 /***                         Cache management                              ***/
-/* For now, all those will be implemented as nop:
- * this is valid, regarding the PowerPC specs...
- * We just have to flush tb while invalidating instruction cache lines...
- */
 /* dcbf */
-GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
+GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
 {
+    /* XXX: specification says this is treated as a load by the MMU */
     gen_addr_reg_index(ctx);
     op_ldst(lbz);
 }
@@ -3166,15 +3700,15 @@
 GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_addr_reg_index(ctx);
     /* XXX: specification says this should be treated as a store by the MMU */
-    //op_ldst(lbz);
+    op_ldst(lbz);
     op_ldst(stb);
 #endif
 }
@@ -3188,95 +3722,233 @@
 }
 
 /* dcbt */
-GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x03E00001, PPC_CACHE)
+GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
 {
+    /* interpreted as no-op */
     /* 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)
+GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
 {
+    /* interpreted as no-op */
     /* 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])()
+#define op_dcbz(n) (*gen_op_dcbz[n][ctx->mem_idx])()
+#if defined(CONFIG_USER_ONLY)
+/* User-mode only */
+static GenOpFunc *gen_op_dcbz[4][4] = {
+    {
+        &gen_op_dcbz_l32_raw,
+        &gen_op_dcbz_l32_raw,
 #if defined(TARGET_PPC64)
-#if defined(CONFIG_USER_ONLY)
-static GenOpFunc *gen_op_dcbz[] = {
-    &gen_op_dcbz_raw,
-    &gen_op_dcbz_raw,
-    &gen_op_dcbz_64_raw,
-    &gen_op_dcbz_64_raw,
+        &gen_op_dcbz_l32_64_raw,
+        &gen_op_dcbz_l32_64_raw,
+#endif
+    },
+    {
+        &gen_op_dcbz_l64_raw,
+        &gen_op_dcbz_l64_raw,
+#if defined(TARGET_PPC64)
+        &gen_op_dcbz_l64_64_raw,
+        &gen_op_dcbz_l64_64_raw,
+#endif
+    },
+    {
+        &gen_op_dcbz_l128_raw,
+        &gen_op_dcbz_l128_raw,
+#if defined(TARGET_PPC64)
+        &gen_op_dcbz_l128_64_raw,
+        &gen_op_dcbz_l128_64_raw,
+#endif
+    },
+    {
+        &gen_op_dcbz_raw,
+        &gen_op_dcbz_raw,
+#if defined(TARGET_PPC64)
+        &gen_op_dcbz_64_raw,
+        &gen_op_dcbz_64_raw,
+#endif
+    },
 };
 #else
-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,
-};
+#if defined(TARGET_PPC64)
+/* Full system - 64 bits mode */
+static GenOpFunc *gen_op_dcbz[4][12] = {
+    {
+        &gen_op_dcbz_l32_user,
+        &gen_op_dcbz_l32_user,
+        &gen_op_dcbz_l32_64_user,
+        &gen_op_dcbz_l32_64_user,
+        &gen_op_dcbz_l32_kernel,
+        &gen_op_dcbz_l32_kernel,
+        &gen_op_dcbz_l32_64_kernel,
+        &gen_op_dcbz_l32_64_kernel,
+#if defined(TARGET_PPC64H)
+        &gen_op_dcbz_l32_hypv,
+        &gen_op_dcbz_l32_hypv,
+        &gen_op_dcbz_l32_64_hypv,
+        &gen_op_dcbz_l32_64_hypv,
 #endif
-#else
-#if defined(CONFIG_USER_ONLY)
-static GenOpFunc *gen_op_dcbz[] = {
-    &gen_op_dcbz_raw,
-    &gen_op_dcbz_raw,
+    },
+    {
+        &gen_op_dcbz_l64_user,
+        &gen_op_dcbz_l64_user,
+        &gen_op_dcbz_l64_64_user,
+        &gen_op_dcbz_l64_64_user,
+        &gen_op_dcbz_l64_kernel,
+        &gen_op_dcbz_l64_kernel,
+        &gen_op_dcbz_l64_64_kernel,
+        &gen_op_dcbz_l64_64_kernel,
+#if defined(TARGET_PPC64H)
+        &gen_op_dcbz_l64_hypv,
+        &gen_op_dcbz_l64_hypv,
+        &gen_op_dcbz_l64_64_hypv,
+        &gen_op_dcbz_l64_64_hypv,
+#endif
+    },
+    {
+        &gen_op_dcbz_l128_user,
+        &gen_op_dcbz_l128_user,
+        &gen_op_dcbz_l128_64_user,
+        &gen_op_dcbz_l128_64_user,
+        &gen_op_dcbz_l128_kernel,
+        &gen_op_dcbz_l128_kernel,
+        &gen_op_dcbz_l128_64_kernel,
+        &gen_op_dcbz_l128_64_kernel,
+#if defined(TARGET_PPC64H)
+        &gen_op_dcbz_l128_hypv,
+        &gen_op_dcbz_l128_hypv,
+        &gen_op_dcbz_l128_64_hypv,
+        &gen_op_dcbz_l128_64_hypv,
+#endif
+    },
+    {
+        &gen_op_dcbz_user,
+        &gen_op_dcbz_user,
+        &gen_op_dcbz_64_user,
+        &gen_op_dcbz_64_user,
+        &gen_op_dcbz_kernel,
+        &gen_op_dcbz_kernel,
+        &gen_op_dcbz_64_kernel,
+        &gen_op_dcbz_64_kernel,
+#if defined(TARGET_PPC64H)
+        &gen_op_dcbz_hypv,
+        &gen_op_dcbz_hypv,
+        &gen_op_dcbz_64_hypv,
+        &gen_op_dcbz_64_hypv,
+#endif
+    },
 };
 #else
-static GenOpFunc *gen_op_dcbz[] = {
-    &gen_op_dcbz_user,
-    &gen_op_dcbz_user,
-    &gen_op_dcbz_kernel,
-    &gen_op_dcbz_kernel,
+/* Full system - 32 bits mode */
+static GenOpFunc *gen_op_dcbz[4][4] = {
+    {
+        &gen_op_dcbz_l32_user,
+        &gen_op_dcbz_l32_user,
+        &gen_op_dcbz_l32_kernel,
+        &gen_op_dcbz_l32_kernel,
+    },
+    {
+        &gen_op_dcbz_l64_user,
+        &gen_op_dcbz_l64_user,
+        &gen_op_dcbz_l64_kernel,
+        &gen_op_dcbz_l64_kernel,
+    },
+    {
+        &gen_op_dcbz_l128_user,
+        &gen_op_dcbz_l128_user,
+        &gen_op_dcbz_l128_kernel,
+        &gen_op_dcbz_l128_kernel,
+    },
+    {
+        &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)
+static always_inline void handler_dcbz (DisasContext *ctx,
+                                        int dcache_line_size)
 {
+    int n;
+
+    switch (dcache_line_size) {
+    case 32:
+        n = 0;
+        break;
+    case 64:
+        n = 1;
+        break;
+    case 128:
+        n = 2;
+        break;
+    default:
+        n = 3;
+        break;
+    }
+    op_dcbz(n);
+}
+
+GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ)
+{
     gen_addr_reg_index(ctx);
-    op_dcbz();
+    handler_dcbz(ctx, ctx->dcache_line_size);
     gen_op_check_reservation();
 }
 
+GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
+{
+    gen_addr_reg_index(ctx);
+    if (ctx->opcode & 0x00200000)
+        handler_dcbz(ctx, ctx->dcache_line_size);
+    else
+        handler_dcbz(ctx, -1);
+    gen_op_check_reservation();
+}
+
 /* icbi */
 #define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
-#if defined(TARGET_PPC64)
 #if defined(CONFIG_USER_ONLY)
+/* User-mode only */
 static GenOpFunc *gen_op_icbi[] = {
     &gen_op_icbi_raw,
     &gen_op_icbi_raw,
+#if defined(TARGET_PPC64)
     &gen_op_icbi_64_raw,
     &gen_op_icbi_64_raw,
+#endif
 };
 #else
+/* Full system - 64 bits mode */
+#if defined(TARGET_PPC64)
 static GenOpFunc *gen_op_icbi[] = {
     &gen_op_icbi_user,
     &gen_op_icbi_user,
+    &gen_op_icbi_64_user,
+    &gen_op_icbi_64_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,
-};
+#if defined(TARGET_PPC64H)
+    &gen_op_icbi_hypv,
+    &gen_op_icbi_hypv,
+    &gen_op_icbi_64_hypv,
+    &gen_op_icbi_64_hypv,
 #endif
-#else
-#if defined(CONFIG_USER_ONLY)
-static GenOpFunc *gen_op_icbi[] = {
-    &gen_op_icbi_raw,
-    &gen_op_icbi_raw,
 };
 #else
+/* Full system - 32 bits mode */
 static GenOpFunc *gen_op_icbi[] = {
     &gen_op_icbi_user,
     &gen_op_icbi_user,
@@ -3285,19 +3957,23 @@
 };
 #endif
 #endif
+
 GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE)
 {
     /* 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: */
 /* dcba */
-GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_OPT)
+GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
 {
+    /* interpreted as no-op */
+    /* XXX: specification say this is treated as a store by the MMU
+     *      but does not generate any exception
+     */
 }
 
 /***                    Segment register manipulation                      ***/
@@ -3306,10 +3982,10 @@
 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_set_T1(SR(ctx->opcode));
@@ -3322,10 +3998,10 @@
 GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_load_gpr_T1(rB(ctx->opcode));
@@ -3339,16 +4015,15 @@
 GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_set_T1(SR(ctx->opcode));
     gen_op_store_sr();
-    RET_STOP(ctx);
 #endif
 }
 
@@ -3356,36 +4031,105 @@
 GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_load_gpr_T1(rB(ctx->opcode));
     gen_op_srli_T1(28);
     gen_op_store_sr();
-    RET_STOP(ctx);
 #endif
 }
 
+#if defined(TARGET_PPC64)
+/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
+/* mfsr */
+GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
+{
+#if defined(CONFIG_USER_ONLY)
+    GEN_EXCP_PRIVREG(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        GEN_EXCP_PRIVREG(ctx);
+        return;
+    }
+    gen_op_set_T1(SR(ctx->opcode));
+    gen_op_load_slb();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+#endif
+}
+
+/* mfsrin */
+GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
+             PPC_SEGMENT_64B)
+{
+#if defined(CONFIG_USER_ONLY)
+    GEN_EXCP_PRIVREG(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        GEN_EXCP_PRIVREG(ctx);
+        return;
+    }
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_srli_T1(28);
+    gen_op_load_slb();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+#endif
+}
+
+/* mtsr */
+GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
+{
+#if defined(CONFIG_USER_ONLY)
+    GEN_EXCP_PRIVREG(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        GEN_EXCP_PRIVREG(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_set_T1(SR(ctx->opcode));
+    gen_op_store_slb();
+#endif
+}
+
+/* mtsrin */
+GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
+             PPC_SEGMENT_64B)
+{
+#if defined(CONFIG_USER_ONLY)
+    GEN_EXCP_PRIVREG(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        GEN_EXCP_PRIVREG(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_srli_T1(28);
+    gen_op_store_slb();
+#endif
+}
+#endif /* defined(TARGET_PPC64) */
+
 /***                      Lookaside buffer management                      ***/
 /* Optional & supervisor only: */
 /* tlbia */
 GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
         if (loglevel != 0)
             fprintf(logfile, "%s: ! supervisor\n", __func__);
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_tlbia();
-    RET_STOP(ctx);
 #endif
 }
 
@@ -3393,10 +4137,10 @@
 GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_load_gpr_T0(rB(ctx->opcode));
@@ -3406,7 +4150,6 @@
     else
 #endif
         gen_op_tlbie();
-    RET_STOP(ctx);
 #endif
 }
 
@@ -3414,16 +4157,16 @@
 GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* This has no effect: it should ensure that all previous
      * tlbie have completed
      */
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 #endif
 }
 
@@ -3432,16 +4175,15 @@
 GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
         if (loglevel != 0)
             fprintf(logfile, "%s: ! supervisor\n", __func__);
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_slbia();
-    RET_STOP(ctx);
 #endif
 }
 
@@ -3449,15 +4191,14 @@
 GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_load_gpr_T0(rB(ctx->opcode));
     gen_op_slbie();
-    RET_STOP(ctx);
 #endif
 }
 #endif
@@ -3466,53 +4207,61 @@
 /* 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)
+/* User-mode only */
 static GenOpFunc *gen_op_eciwx[] = {
     &gen_op_eciwx_raw,
     &gen_op_eciwx_le_raw,
+#if defined(TARGET_PPC64)
     &gen_op_eciwx_64_raw,
     &gen_op_eciwx_le_64_raw,
+#endif
 };
 static GenOpFunc *gen_op_ecowx[] = {
     &gen_op_ecowx_raw,
     &gen_op_ecowx_le_raw,
+#if defined(TARGET_PPC64)
     &gen_op_ecowx_64_raw,
     &gen_op_ecowx_le_64_raw,
+#endif
 };
 #else
+#if defined(TARGET_PPC64)
+/* Full system - 64 bits mode */
 static GenOpFunc *gen_op_eciwx[] = {
     &gen_op_eciwx_user,
     &gen_op_eciwx_le_user,
+    &gen_op_eciwx_64_user,
+    &gen_op_eciwx_le_64_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,
+#if defined(TARGET_PPC64H)
+    &gen_op_eciwx_hypv,
+    &gen_op_eciwx_le_hypv,
+    &gen_op_eciwx_64_hypv,
+    &gen_op_eciwx_le_64_hypv,
+#endif
 };
 static GenOpFunc *gen_op_ecowx[] = {
     &gen_op_ecowx_user,
     &gen_op_ecowx_le_user,
+    &gen_op_ecowx_64_user,
+    &gen_op_ecowx_le_64_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,
-};
+#if defined(TARGET_PPC64H)
+    &gen_op_ecowx_hypv,
+    &gen_op_ecowx_le_hypv,
+    &gen_op_ecowx_64_hypv,
+    &gen_op_ecowx_le_64_hypv,
 #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
+/* Full system - 32 bits mode */
 static GenOpFunc *gen_op_eciwx[] = {
     &gen_op_eciwx_user,
     &gen_op_eciwx_le_user,
@@ -3568,10 +4317,11 @@
 }
 
 /* clcs */
-GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR) /* 601 ? */
+GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
 {
     gen_op_load_gpr_T0(rA(ctx->opcode));
     gen_op_POWER_clcs();
+    /* Rc=1 sets CR0 to an undefined state */
     gen_op_store_T0_gpr(rD(ctx->opcode));
 }
 
@@ -3651,7 +4401,7 @@
 }
 
 /* As lscbx load from memory byte after byte, it's always endian safe */
-#define op_POWER_lscbx(start, ra, rb) \
+#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[] = {
@@ -3951,24 +4701,24 @@
 GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
 {
     /* XXX: TODO */
-    RET_INVAL(ctx);
+    GEN_EXCP_INVAL(ctx);
 }
 
 /* esa */
 GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
 {
     /* XXX: TODO */
-    RET_INVAL(ctx);
+    GEN_EXCP_INVAL(ctx);
 }
 
 /* mfrom */
 GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_load_gpr_T0(rA(ctx->opcode));
@@ -3979,37 +4729,66 @@
 
 /* 602 - 603 - G2 TLB management */
 /* tlbld */
-GEN_HANDLER(tlbld, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
+GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_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)
+GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_load_gpr_T0(rB(ctx->opcode));
     gen_op_6xx_tlbli();
-    RET_STOP(ctx);
 #endif
 }
 
+/* 74xx TLB management */
+/* tlbld */
+GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
+{
+#if defined(CONFIG_USER_ONLY)
+    GEN_EXCP_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        GEN_EXCP_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rB(ctx->opcode));
+    gen_op_74xx_tlbld();
+#endif
+}
+
+/* tlbli */
+GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
+{
+#if defined(CONFIG_USER_ONLY)
+    GEN_EXCP_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        GEN_EXCP_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rB(ctx->opcode));
+    gen_op_74xx_tlbli();
+#endif
+}
+
 /* POWER instructions not in PowerPC 601 */
 /* clf */
 GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
@@ -4022,10 +4801,10 @@
 {
     /* Cache line invalidate: privileged and treated as no-op */
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
 #endif
@@ -4040,10 +4819,10 @@
 GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     int ra = rA(ctx->opcode);
@@ -4060,10 +4839,10 @@
 GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_addr_reg_index(ctx);
@@ -4075,14 +4854,14 @@
 GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_POWER_rfsvc();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 
@@ -4221,19 +5000,21 @@
 }
 
 /* BookE specific instructions */
-GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_BOOKE)
+/* XXX: not implemented on 440 ? */
+GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_BOOKE_EXT)
 {
     /* XXX: TODO */
-    RET_INVAL(ctx);
+    GEN_EXCP_INVAL(ctx);
 }
 
-GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_BOOKE)
+/* XXX: not implemented on 440 ? */
+GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_BOOKE_EXT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_addr_reg_index(ctx);
@@ -4244,13 +5025,13 @@
     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)
+static always_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);
@@ -4426,12 +5207,12 @@
 GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_EMB_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     uint32_t dcrn = SPR(ctx->opcode);
 
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_set_T0(dcrn);
@@ -4444,12 +5225,12 @@
 GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_EMB_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     uint32_t dcrn = SPR(ctx->opcode);
 
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_set_T0(dcrn);
@@ -4459,45 +5240,67 @@
 }
 
 /* mfdcrx */
-GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000001, PPC_BOOKE)
+/* XXX: not implemented on 440 ? */
+GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_BOOKE_EXT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_load_gpr_T0(rA(ctx->opcode));
     gen_op_load_dcr();
     gen_op_store_T0_gpr(rD(ctx->opcode));
+    /* Note: Rc update flag set leads to undefined state of Rc0 */
 #endif
 }
 
 /* mtdcrx */
-GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000001, PPC_BOOKE)
+/* XXX: not implemented on 440 ? */
+GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_BOOKE_EXT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_load_gpr_T0(rA(ctx->opcode));
     gen_op_load_gpr_T1(rS(ctx->opcode));
     gen_op_store_dcr();
+    /* Note: Rc update flag set leads to undefined state of Rc0 */
 #endif
 }
 
+/* mfdcrux (PPC 460) : user-mode access to DCR */
+GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_dcr();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+    /* Note: Rc update flag set leads to undefined state of Rc0 */
+}
+
+/* mtdcrux (PPC 460) : user-mode access to DCR */
+GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_gpr_T1(rS(ctx->opcode));
+    gen_op_store_dcr();
+    /* Note: Rc update flag set leads to undefined state of Rc0 */
+}
+
 /* dccci */
 GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* interpreted as no-op */
@@ -4508,10 +5311,10 @@
 GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_addr_reg_index(ctx);
@@ -4521,7 +5324,7 @@
 }
 
 /* icbt */
-GEN_HANDLER(icbt_40x, 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_SPEC)
+GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
 {
     /* interpreted as no-op */
     /* XXX: specification say this is treated as a load by the MMU
@@ -4533,10 +5336,10 @@
 GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* interpreted as no-op */
@@ -4547,10 +5350,10 @@
 GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* interpreted as no-op */
@@ -4558,76 +5361,78 @@
 }
 
 /* rfci (supervisor only) */
-GEN_HANDLER(rfci_40x, 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
+GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* Restore CPU state */
     gen_op_40x_rfci();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 
 GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* Restore CPU state */
     gen_op_rfci();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 
 /* BookE specific */
-GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE)
+/* XXX: not implemented on 440 ? */
+GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE_EXT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* Restore CPU state */
     gen_op_rfdi();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 
-GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_BOOKE)
+/* XXX: not implemented on 440 ? */
+GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* Restore CPU state */
     gen_op_rfmci();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 
 /* TLB management - PowerPC 405 implementation */
 /* tlbre */
-GEN_HANDLER(tlbre_40x, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_SPEC)
+GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     switch (rB(ctx->opcode)) {
@@ -4642,39 +5447,38 @@
         gen_op_store_T0_gpr(rD(ctx->opcode));
         break;
     default:
-        RET_INVAL(ctx);
+        GEN_EXCP_INVAL(ctx);
         break;
     }
 #endif
 }
 
 /* tlbsx - tlbsx. */
-GEN_HANDLER(tlbsx_40x, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_SPEC)
+GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_addr_reg_index(ctx);
+    gen_op_4xx_tlbsx();
     if (Rc(ctx->opcode))
-        gen_op_4xx_tlbsx_();
-    else
-        gen_op_4xx_tlbsx();
+        gen_op_4xx_tlbsx_check();
     gen_op_store_T0_gpr(rD(ctx->opcode));
 #endif
 }
 
 /* tlbwe */
-GEN_HANDLER(tlbwe_40x, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_SPEC)
+GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     switch (rB(ctx->opcode)) {
@@ -4689,93 +5493,76 @@
         gen_op_4xx_tlbwe_lo();
         break;
     default:
-        RET_INVAL(ctx);
+        GEN_EXCP_INVAL(ctx);
         break;
     }
 #endif
 }
 
-/* TLB management - PowerPC BookE implementation */
+/* TLB management - PowerPC 440 implementation */
 /* tlbre */
-GEN_HANDLER(tlbre_booke, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
+GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     switch (rB(ctx->opcode)) {
     case 0:
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_booke_tlbre0();
-        gen_op_store_T0_gpr(rD(ctx->opcode));
-        break;
     case 1:
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_booke_tlbre1();
-        gen_op_store_T0_gpr(rD(ctx->opcode));
-        break;
     case 2:
         gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_booke_tlbre2();
+        gen_op_440_tlbre(rB(ctx->opcode));
         gen_op_store_T0_gpr(rD(ctx->opcode));
         break;
     default:
-        RET_INVAL(ctx);
+        GEN_EXCP_INVAL(ctx);
         break;
     }
 #endif
 }
 
 /* tlbsx - tlbsx. */
-GEN_HANDLER(tlbsx_booke, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
+GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_addr_reg_index(ctx);
+    gen_op_440_tlbsx();
     if (Rc(ctx->opcode))
-        gen_op_booke_tlbsx_();
-    else
-        gen_op_booke_tlbsx();
+        gen_op_4xx_tlbsx_check();
     gen_op_store_T0_gpr(rD(ctx->opcode));
 #endif
 }
 
 /* tlbwe */
-GEN_HANDLER(tlbwe_booke, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
+GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_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_booke_tlbwe0();
-        break;
     case 1:
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_load_gpr_T1(rS(ctx->opcode));
-        gen_op_booke_tlbwe1();
-        break;
     case 2:
         gen_op_load_gpr_T0(rA(ctx->opcode));
         gen_op_load_gpr_T1(rS(ctx->opcode));
-        gen_op_booke_tlbwe2();
+        gen_op_440_tlbwe(rB(ctx->opcode));
         break;
     default:
-        RET_INVAL(ctx);
+        GEN_EXCP_INVAL(ctx);
         break;
     }
 #endif
@@ -4785,15 +5572,18 @@
 GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_EMB_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_load_gpr_T0(rD(ctx->opcode));
     gen_op_wrte();
-    RET_EXCP(ctx, EXCP_MTMSR, 0);
+    /* Stop translation to have a chance to raise an exception
+     * if we just set msr_ee to 1
+     */
+    GEN_STOP(ctx);
 #endif
 }
 
@@ -4801,15 +5591,18 @@
 GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_EMB_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_set_T0(ctx->opcode & 0x00010000);
     gen_op_wrte();
-    RET_EXCP(ctx, EXCP_MTMSR, 0);
+    /* Stop translation to have a chance to raise an exception
+     * if we just set msr_ee to 1
+     */
+    GEN_STOP(ctx);
 #endif
 }
 
@@ -4835,13 +5628,13 @@
 }
 
 /* msync replaces sync on 440 */
-GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_BOOKE)
+GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
 {
     /* interpreted as no-op */
 }
 
 /* icbt */
-GEN_HANDLER(icbt_440, 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
+GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
 {
     /* interpreted as no-op */
     /* XXX: specification say this is treated as a load by the MMU
@@ -4849,6 +5642,161 @@
      */
 }
 
+/***                      Altivec vector extension                         ***/
+/* Altivec registers moves */
+GEN32(gen_op_load_avr_A0, gen_op_load_avr_A0_avr);
+GEN32(gen_op_load_avr_A1, gen_op_load_avr_A1_avr);
+GEN32(gen_op_load_avr_A2, gen_op_load_avr_A2_avr);
+
+GEN32(gen_op_store_A0_avr, gen_op_store_A0_avr_avr);
+GEN32(gen_op_store_A1_avr, gen_op_store_A1_avr_avr);
+#if 0 // unused
+GEN32(gen_op_store_A2_avr, gen_op_store_A2_avr_avr);
+#endif
+
+#define op_vr_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
+#if defined(CONFIG_USER_ONLY)
+#if defined(TARGET_PPC64)
+/* User-mode only - 64 bits mode */
+#define OP_VR_LD_TABLE(name)                                                  \
+static GenOpFunc *gen_op_vr_l##name[] = {                                     \
+    &gen_op_vr_l##name##_raw,                                                 \
+    &gen_op_vr_l##name##_le_raw,                                              \
+    &gen_op_vr_l##name##_64_raw,                                              \
+    &gen_op_vr_l##name##_le_64_raw,                                           \
+};
+#define OP_VR_ST_TABLE(name)                                                  \
+static GenOpFunc *gen_op_vr_st##name[] = {                                    \
+    &gen_op_vr_st##name##_raw,                                                \
+    &gen_op_vr_st##name##_le_raw,                                             \
+    &gen_op_vr_st##name##_64_raw,                                             \
+    &gen_op_vr_st##name##_le_64_raw,                                          \
+};
+#else /* defined(TARGET_PPC64) */
+/* User-mode only - 32 bits mode */
+#define OP_VR_LD_TABLE(name)                                                  \
+static GenOpFunc *gen_op_vr_l##name[] = {                                     \
+    &gen_op_vr_l##name##_raw,                                                 \
+    &gen_op_vr_l##name##_le_raw,                                              \
+};
+#define OP_VR_ST_TABLE(name)                                                  \
+static GenOpFunc *gen_op_vr_st##name[] = {                                    \
+    &gen_op_vr_st##name##_raw,                                                \
+    &gen_op_vr_st##name##_le_raw,                                             \
+};
+#endif /* defined(TARGET_PPC64) */
+#else /* defined(CONFIG_USER_ONLY) */
+#if defined(TARGET_PPC64H)
+/* Full system with hypervisor mode */
+#define OP_VR_LD_TABLE(name)                                                  \
+static GenOpFunc *gen_op_vr_l##name[] = {                                     \
+    &gen_op_vr_l##name##_user,                                                \
+    &gen_op_vr_l##name##_le_user,                                             \
+    &gen_op_vr_l##name##_64_user,                                             \
+    &gen_op_vr_l##name##_le_64_user,                                          \
+    &gen_op_vr_l##name##_kernel,                                              \
+    &gen_op_vr_l##name##_le_kernel,                                           \
+    &gen_op_vr_l##name##_64_kernel,                                           \
+    &gen_op_vr_l##name##_le_64_kernel,                                        \
+    &gen_op_vr_l##name##_hypv,                                                \
+    &gen_op_vr_l##name##_le_hypv,                                             \
+    &gen_op_vr_l##name##_64_hypv,                                             \
+    &gen_op_vr_l##name##_le_64_hypv,                                          \
+};
+#define OP_VR_ST_TABLE(name)                                                  \
+static GenOpFunc *gen_op_vr_st##name[] = {                                    \
+    &gen_op_vr_st##name##_user,                                               \
+    &gen_op_vr_st##name##_le_user,                                            \
+    &gen_op_vr_st##name##_64_user,                                            \
+    &gen_op_vr_st##name##_le_64_user,                                         \
+    &gen_op_vr_st##name##_kernel,                                             \
+    &gen_op_vr_st##name##_le_kernel,                                          \
+    &gen_op_vr_st##name##_64_kernel,                                          \
+    &gen_op_vr_st##name##_le_64_kernel,                                       \
+    &gen_op_vr_st##name##_hypv,                                               \
+    &gen_op_vr_st##name##_le_hypv,                                            \
+    &gen_op_vr_st##name##_64_hypv,                                            \
+    &gen_op_vr_st##name##_le_64_hypv,                                         \
+};
+#elif defined(TARGET_PPC64)
+/* Full system - 64 bits mode */
+#define OP_VR_LD_TABLE(name)                                                  \
+static GenOpFunc *gen_op_vr_l##name[] = {                                     \
+    &gen_op_vr_l##name##_user,                                                \
+    &gen_op_vr_l##name##_le_user,                                             \
+    &gen_op_vr_l##name##_64_user,                                             \
+    &gen_op_vr_l##name##_le_64_user,                                          \
+    &gen_op_vr_l##name##_kernel,                                              \
+    &gen_op_vr_l##name##_le_kernel,                                           \
+    &gen_op_vr_l##name##_64_kernel,                                           \
+    &gen_op_vr_l##name##_le_64_kernel,                                        \
+};
+#define OP_VR_ST_TABLE(name)                                                  \
+static GenOpFunc *gen_op_vr_st##name[] = {                                    \
+    &gen_op_vr_st##name##_user,                                               \
+    &gen_op_vr_st##name##_le_user,                                            \
+    &gen_op_vr_st##name##_64_user,                                            \
+    &gen_op_vr_st##name##_le_64_user,                                         \
+    &gen_op_vr_st##name##_kernel,                                             \
+    &gen_op_vr_st##name##_le_kernel,                                          \
+    &gen_op_vr_st##name##_64_kernel,                                          \
+    &gen_op_vr_st##name##_le_64_kernel,                                       \
+};
+#else /* defined(TARGET_PPC64) */
+/* Full system - 32 bits mode */
+#define OP_VR_LD_TABLE(name)                                                  \
+static GenOpFunc *gen_op_vr_l##name[] = {                                     \
+    &gen_op_vr_l##name##_user,                                                \
+    &gen_op_vr_l##name##_le_user,                                             \
+    &gen_op_vr_l##name##_kernel,                                              \
+    &gen_op_vr_l##name##_le_kernel,                                           \
+};
+#define OP_VR_ST_TABLE(name)                                                  \
+static GenOpFunc *gen_op_vr_st##name[] = {                                    \
+    &gen_op_vr_st##name##_user,                                               \
+    &gen_op_vr_st##name##_le_user,                                            \
+    &gen_op_vr_st##name##_kernel,                                             \
+    &gen_op_vr_st##name##_le_kernel,                                          \
+};
+#endif /* defined(TARGET_PPC64) */
+#endif /* defined(CONFIG_USER_ONLY) */
+
+#define GEN_VR_LDX(name, opc2, opc3)                                          \
+GEN_HANDLER(l##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)               \
+{                                                                             \
+    if (unlikely(!ctx->altivec_enabled)) {                                    \
+        GEN_EXCP_NO_VR(ctx);                                                  \
+        return;                                                               \
+    }                                                                         \
+    gen_addr_reg_index(ctx);                                                  \
+    op_vr_ldst(vr_l##name);                                                   \
+    gen_op_store_A0_avr(rD(ctx->opcode));                                     \
+}
+
+#define GEN_VR_STX(name, opc2, opc3)                                          \
+GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC)              \
+{                                                                             \
+    if (unlikely(!ctx->altivec_enabled)) {                                    \
+        GEN_EXCP_NO_VR(ctx);                                                  \
+        return;                                                               \
+    }                                                                         \
+    gen_addr_reg_index(ctx);                                                  \
+    gen_op_load_avr_A0(rS(ctx->opcode));                                      \
+    op_vr_ldst(vr_st##name);                                                  \
+}
+
+OP_VR_LD_TABLE(vx);
+GEN_VR_LDX(vx, 0x07, 0x03);
+/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
+#define gen_op_vr_lvxl gen_op_vr_lvx
+GEN_VR_LDX(vxl, 0x07, 0x0B);
+
+OP_VR_ST_TABLE(vx);
+GEN_VR_STX(vx, 0x07, 0x07);
+/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
+#define gen_op_vr_stvxl gen_op_vr_stvx
+GEN_VR_STX(vxl, 0x07, 0x0F);
+
 #if defined(TARGET_PPCEMB)
 /***                           SPE extension                               ***/
 
@@ -4875,13 +5823,13 @@
 }
 
 /* Handler for undefined SPE opcodes */
-static inline void gen_speundef (DisasContext *ctx)
+static always_inline void gen_speundef (DisasContext *ctx)
 {
-    RET_INVAL(ctx);
+    GEN_EXCP_INVAL(ctx);
 }
 
 /* SPE load and stores */
-static inline void gen_addr_spe_imm_index (DisasContext *ctx, int sh)
+static always_inline void gen_addr_spe_imm_index (DisasContext *ctx, int sh)
 {
     target_long simm = rB(ctx->opcode);
 
@@ -4897,6 +5845,7 @@
 #define op_spe_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
 #if defined(CONFIG_USER_ONLY)
 #if defined(TARGET_PPC64)
+/* User-mode only - 64 bits mode */
 #define OP_SPE_LD_TABLE(name)                                                 \
 static GenOpFunc *gen_op_spe_l##name[] = {                                    \
     &gen_op_spe_l##name##_raw,                                                \
@@ -4912,6 +5861,7 @@
     &gen_op_spe_st##name##_le_64_raw,                                         \
 };
 #else /* defined(TARGET_PPC64) */
+/* User-mode only - 32 bits mode */
 #define OP_SPE_LD_TABLE(name)                                                 \
 static GenOpFunc *gen_op_spe_l##name[] = {                                    \
     &gen_op_spe_l##name##_raw,                                                \
@@ -4924,15 +5874,48 @@
 };
 #endif /* defined(TARGET_PPC64) */
 #else /* defined(CONFIG_USER_ONLY) */
-#if defined(TARGET_PPC64)
+#if defined(TARGET_PPC64H)
+/* Full system with hypervisor mode */
 #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##_64_user,                                            \
+    &gen_op_spe_l##name##_le_64_user,                                         \
     &gen_op_spe_l##name##_kernel,                                             \
     &gen_op_spe_l##name##_le_kernel,                                          \
+    &gen_op_spe_l##name##_64_kernel,                                          \
+    &gen_op_spe_l##name##_le_64_kernel,                                       \
+    &gen_op_spe_l##name##_hypv,                                               \
+    &gen_op_spe_l##name##_le_hypv,                                            \
+    &gen_op_spe_l##name##_64_hypv,                                            \
+    &gen_op_spe_l##name##_le_64_hypv,                                         \
+};
+#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##_64_user,                                           \
+    &gen_op_spe_st##name##_le_64_user,                                        \
+    &gen_op_spe_st##name##_kernel,                                            \
+    &gen_op_spe_st##name##_le_kernel,                                         \
+    &gen_op_spe_st##name##_64_kernel,                                         \
+    &gen_op_spe_st##name##_le_64_kernel,                                      \
+    &gen_op_spe_st##name##_hypv,                                              \
+    &gen_op_spe_st##name##_le_hypv,                                           \
+    &gen_op_spe_st##name##_64_hypv,                                           \
+    &gen_op_spe_st##name##_le_64_hypv,                                        \
+};
+#elif defined(TARGET_PPC64)
+/* Full system - 64 bits mode */
+#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##_64_user,                                            \
     &gen_op_spe_l##name##_le_64_user,                                         \
+    &gen_op_spe_l##name##_kernel,                                             \
+    &gen_op_spe_l##name##_le_kernel,                                          \
     &gen_op_spe_l##name##_64_kernel,                                          \
     &gen_op_spe_l##name##_le_64_kernel,                                       \
 };
@@ -4940,14 +5923,15 @@
 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##_64_user,                                           \
+    &gen_op_spe_st##name##_le_64_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) */
+/* Full system - 32 bits mode */
 #define OP_SPE_LD_TABLE(name)                                                 \
 static GenOpFunc *gen_op_spe_l##name[] = {                                    \
     &gen_op_spe_l##name##_user,                                               \
@@ -4966,10 +5950,10 @@
 #endif /* defined(CONFIG_USER_ONLY) */
 
 #define GEN_SPE_LD(name, sh)                                                  \
-static inline void gen_evl##name (DisasContext *ctx)                          \
+static always_inline void gen_evl##name (DisasContext *ctx)                   \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_spe_imm_index(ctx, sh);                                          \
@@ -4978,10 +5962,10 @@
 }
 
 #define GEN_SPE_LDX(name)                                                     \
-static inline void gen_evl##name##x (DisasContext *ctx)                       \
+static always_inline void gen_evl##name##x (DisasContext *ctx)                \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -4995,10 +5979,10 @@
 GEN_SPE_LDX(name)
 
 #define GEN_SPE_ST(name, sh)                                                  \
-static inline void gen_evst##name (DisasContext *ctx)                         \
+static always_inline void gen_evst##name (DisasContext *ctx)                  \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_spe_imm_index(ctx, sh);                                          \
@@ -5007,10 +5991,10 @@
 }
 
 #define GEN_SPE_STX(name)                                                     \
-static inline void gen_evst##name##x (DisasContext *ctx)                      \
+static always_inline void gen_evst##name##x (DisasContext *ctx)               \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -5029,10 +6013,10 @@
 
 /* SPE arithmetic and logic */
 #define GEN_SPEOP_ARITH2(name)                                                \
-static inline void gen_##name (DisasContext *ctx)                             \
+static always_inline void gen_##name (DisasContext *ctx)                      \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
@@ -5042,10 +6026,10 @@
 }
 
 #define GEN_SPEOP_ARITH1(name)                                                \
-static inline void gen_##name (DisasContext *ctx)                             \
+static always_inline void gen_##name (DisasContext *ctx)                      \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
@@ -5054,10 +6038,10 @@
 }
 
 #define GEN_SPEOP_COMP(name)                                                  \
-static inline void gen_##name (DisasContext *ctx)                             \
+static always_inline void gen_##name (DisasContext *ctx)                      \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
@@ -5094,7 +6078,7 @@
 GEN_SPEOP_ARITH1(evrndw);
 GEN_SPEOP_ARITH1(evcntlzw);
 GEN_SPEOP_ARITH1(evcntlsw);
-static inline void gen_brinc (DisasContext *ctx)
+static always_inline void gen_brinc (DisasContext *ctx)
 {
     /* Note: brinc is usable even if SPE is disabled */
     gen_op_load_gpr64_T0(rA(ctx->opcode));
@@ -5104,10 +6088,10 @@
 }
 
 #define GEN_SPEOP_ARITH_IMM2(name)                                            \
-static inline void gen_##name##i (DisasContext *ctx)                          \
+static always_inline void gen_##name##i (DisasContext *ctx)                   \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_load_gpr64_T0(rB(ctx->opcode));                                    \
@@ -5117,10 +6101,10 @@
 }
 
 #define GEN_SPEOP_LOGIC_IMM2(name)                                            \
-static inline void gen_##name##i (DisasContext *ctx)                          \
+static always_inline void gen_##name##i (DisasContext *ctx)                   \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
@@ -5140,7 +6124,7 @@
 #define gen_evsrwiu gen_evsrwui
 GEN_SPEOP_LOGIC_IMM2(evrlw);
 
-static inline void gen_evsplati (DisasContext *ctx)
+static always_inline void gen_evsplati (DisasContext *ctx)
 {
     int32_t imm = (int32_t)(rA(ctx->opcode) << 27) >> 27;
 
@@ -5148,7 +6132,7 @@
     gen_op_store_T0_gpr64(rD(ctx->opcode));
 }
 
-static inline void gen_evsplatfi (DisasContext *ctx)
+static always_inline void gen_evsplatfi (DisasContext *ctx)
 {
     uint32_t imm = rA(ctx->opcode) << 27;
 
@@ -5189,10 +6173,10 @@
 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)
+static always_inline void gen_evsel (DisasContext *ctx)
 {
     if (unlikely(!ctx->spe_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);
+        GEN_EXCP_NO_AP(ctx);
         return;
     }
     gen_op_load_crf_T0(ctx->opcode & 0x7);
@@ -5202,19 +6186,19 @@
     gen_op_store_T0_gpr64(rD(ctx->opcode));
 }
 
-GEN_HANDLER(evsel0, 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
+GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
 {
     gen_evsel(ctx);
 }
-GEN_HANDLER(evsel1, 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
+GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
 {
     gen_evsel(ctx);
 }
-GEN_HANDLER(evsel2, 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
+GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
 {
     gen_evsel(ctx);
 }
-GEN_HANDLER(evsel3, 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
+GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
 {
     gen_evsel(ctx);
 }
@@ -5279,13 +6263,13 @@
 #endif
 #endif
 #define _GEN_OP_SPE_STWWE(suffix)                                             \
-static inline void gen_op_spe_stwwe_##suffix (void)                           \
+static always_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)                        \
+static always_inline void gen_op_spe_stwwe_le_##suffix (void)                 \
 {                                                                             \
     gen_op_srli32_T1_64();                                                    \
     gen_op_spe_stwwo_le_##suffix();                                           \
@@ -5294,12 +6278,12 @@
 #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)                        \
+static always_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)                     \
+static always_inline void gen_op_spe_stwwe_le_64_##suffix (void)              \
 {                                                                             \
     gen_op_srli32_T1_64();                                                    \
     gen_op_spe_stwwo_le_64_##suffix();                                        \
@@ -5319,21 +6303,21 @@
 GEN_SPEOP_ST(wwo, 2);
 
 #define GEN_SPE_LDSPLAT(name, op, suffix)                                     \
-static inline void gen_op_spe_l##name##_##suffix (void)                       \
+static always_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)                             \
+static always_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)                             \
+static always_inline void gen_op_spe_lhx_##suffix (void)                      \
 {                                                                             \
     gen_op_spe_lh_##suffix();                                                 \
     gen_op_extsh_T1_64();                                                     \
@@ -5509,7 +6493,7 @@
 
 /***                      SPE floating-point extension                     ***/
 #define GEN_SPEFPUOP_CONV(name)                                               \
-static inline void gen_##name (DisasContext *ctx)                             \
+static always_inline void gen_##name (DisasContext *ctx)                      \
 {                                                                             \
     gen_op_load_gpr64_T0(rB(ctx->opcode));                                    \
     gen_op_##name();                                                          \
@@ -5661,18 +6645,10 @@
 GEN_OPCODE_MARK(end);
 
 #include "translate_init.c"
+#include "helper_regs.h"
 
 /*****************************************************************************/
 /* 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)
@@ -5689,8 +6665,8 @@
 
     int i;
 
-    cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX "\n",
-                env->nip, env->lr, env->ctr);
+    cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX " idx %d\n",
+                env->nip, env->lr, env->ctr, env->mmu_idx);
     cpu_fprintf(f, "MSR " REGX FILL " XER %08x      "
 #if !defined(NO_TIMER_DUMP)
                 "TB %08x %08x "
@@ -5699,7 +6675,7 @@
 #endif
 #endif
                 "\n",
-                do_load_msr(env), load_xer(env)
+                env->msr, hreg_load_xer(env)
 #if !defined(NO_TIMER_DUMP)
                 , cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
 #if !defined(CONFIG_USER_ONLY)
@@ -5710,7 +6686,7 @@
     for (i = 0; i < 32; i++) {
         if ((i & (RGPL - 1)) == 0)
             cpu_fprintf(f, "GPR%02d", i);
-        cpu_fprintf(f, " " REGX, env->gpr[i]);
+        cpu_fprintf(f, " " REGX, (target_ulong)env->gpr[i]);
         if ((i & (RGPL - 1)) == (RGPL - 1))
             cpu_fprintf(f, "\n");
     }
@@ -5736,9 +6712,11 @@
         if ((i & (RFPL - 1)) == (RFPL - 1))
             cpu_fprintf(f, "\n");
     }
+#if !defined(CONFIG_USER_ONLY)
     cpu_fprintf(f, "SRR0 " REGX " SRR1 " REGX "         " FILL FILL FILL
                 "SDR1 " REGX "\n",
                 env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
+#endif
 
 #undef RGPL
 #undef RFPL
@@ -5793,51 +6771,67 @@
 }
 
 /*****************************************************************************/
-static inline int gen_intermediate_code_internal (CPUState *env,
-                                                  TranslationBlock *tb,
-                                                  int search_pc)
+static always_inline int gen_intermediate_code_internal (CPUState *env,
+                                                         TranslationBlock *tb,
+                                                         int search_pc)
 {
     DisasContext ctx, *ctxp = &ctx;
     opc_handler_t **table, *handler;
     target_ulong pc_start;
     uint16_t *gen_opc_end;
+    int supervisor;
+    int single_step, branch_step;
     int j, lj = -1;
 
     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;
+#if defined(OPTIMIZE_FPRF_UPDATE)
+    gen_fprf_ptr = gen_fprf_buf;
+#endif
     nb_gen_labels = 0;
     ctx.nip = pc_start;
     ctx.tb = tb;
-    ctx.exception = EXCP_NONE;
+    ctx.exception = POWERPC_EXCP_NONE;
     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;
+    supervisor = env->mmu_idx;
+#if !defined(CONFIG_USER_ONLY)
+    ctx.supervisor = supervisor;
 #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;
+    ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | msr_le;
+#else
+    ctx.mem_idx = (supervisor << 1) | msr_le;
 #endif
+    ctx.dcache_line_size = env->dcache_line_size;
     ctx.fpu_enabled = msr_fp;
 #if defined(TARGET_PPCEMB)
-    ctx.spe_enabled = msr_spe;
+    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
+        ctx.spe_enabled = msr_spe;
+    else
+        ctx.spe_enabled = 0;
 #endif
-    ctx.singlestep_enabled = env->singlestep_enabled;
+    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
+        ctx.altivec_enabled = msr_vr;
+    else
+        ctx.altivec_enabled = 0;
+    if ((env->flags & POWERPC_FLAG_SE) && msr_se)
+        single_step = 1;
+    else
+        single_step = 0;
+    if ((env->flags & POWERPC_FLAG_BE) && msr_be)
+        branch_step = 1;
+    else
+        branch_step = 0;
+    ctx.singlestep_enabled = env->singlestep_enabled || single_step == 1;
 #if defined (DO_SINGLE_STEP) && 0
     /* Single step trace mode */
     msr_se = 1;
 #endif
     /* Set env in case of segfault during code fetch */
-    while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) {
+    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
         if (unlikely(env->nb_breakpoints > 0)) {
             for (j = 0; j < env->nb_breakpoints; j++) {
                 if (env->breakpoints[j] == ctx.nip) {
@@ -5861,7 +6855,7 @@
         if (loglevel & CPU_LOG_TB_IN_ASM) {
             fprintf(logfile, "----------------\n");
             fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
-                    ctx.nip, 1 - msr_pr, msr_ir);
+                    ctx.nip, supervisor, (int)msr_ir);
         }
 #endif
         ctx.opcode = ldl_code(ctx.nip);
@@ -5895,29 +6889,29 @@
                 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);
+                        opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
             } else {
                 printf("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);
+                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
             }
         } else {
             if (unlikely((ctx.opcode & handler->inval) != 0)) {
                 if (loglevel != 0) {
                     fprintf(logfile, "invalid bits: %08x for opcode: "
-                            "%02x -%02x - %02x (%08x) 0x" ADDRX "\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 (%08x) 0x" ADDRX "\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);
                 }
-                RET_INVAL(ctxp);
+                GEN_EXCP_INVAL(ctxp);
                 break;
             }
         }
@@ -5926,36 +6920,29 @@
         handler->count++;
 #endif
         /* Check trace mode exceptions */
-#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 (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
-                     (env->singlestep_enabled))) {
+        if (unlikely(branch_step != 0 &&
+                     ctx.exception == POWERPC_EXCP_BRANCH)) {
+            GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
+        } else if (unlikely(single_step != 0 &&
+                            (ctx.nip <= 0x100 || ctx.nip > 0xF00 ||
+                             (ctx.nip & 0xFC) != 0x04) &&
+                            ctx.exception != POWERPC_SYSCALL &&
+                            ctx.exception != POWERPC_EXCP_TRAP)) {
+            GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
+        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
+                            (env->singlestep_enabled))) {
+            /* if we reach a page boundary or are single stepping, stop
+             * generation
+             */
             break;
         }
 #if defined (DO_SINGLE_STEP)
         break;
 #endif
     }
-    if (ctx.exception == EXCP_NONE) {
+    if (ctx.exception == POWERPC_EXCP_NONE) {
         gen_goto_tb(&ctx, 0, ctx.nip);
-    } else if (ctx.exception != EXCP_BRANCH) {
+    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
         gen_op_reset_T0();
         /* Generate the return instruction */
         gen_op_exit_tb();
@@ -5976,7 +6963,8 @@
     }
     if (loglevel & CPU_LOG_TB_IN_ASM) {
         int flags;
-        flags = msr_le;
+        flags = env->bfd_mach;
+        flags |= msr_le << 16;
         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
         target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
         fprintf(logfile, "\n");

Modified: trunk/src/host/qemu-neo1973/target-ppc/translate_init.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/translate_init.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-ppc/translate_init.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -23,6 +23,8 @@
  * inside "#if defined(TODO) ... #endif" statements to make tests easier.
  */
 
+#include "dis-asm.h"
+
 //#define PPC_DUMP_CPU
 //#define PPC_DEBUG_SPR
 //#define PPC_DEBUG_IRQ
@@ -32,21 +34,29 @@
     uint32_t pvr;
     uint32_t pvr_mask;
     uint64_t insns_flags;
+    uint64_t msr_mask;
+    uint8_t mmu_model;
+    uint8_t excp_model;
+    uint8_t bus_model;
+    uint8_t pad;
     uint32_t flags;
-    uint64_t msr_mask;
+    int bfd_mach;
+    void (*init_proc)(CPUPPCState *env);
+    int (*check_pow)(CPUPPCState *env);
 };
 
 /* 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) \
-{                                                                     \
+#define PPC_IRQ_INIT_FN(name)                                                 \
+static inline void glue(glue(ppc, name),_irq_init) (CPUPPCState *env)         \
+{                                                                             \
 }
 #else
-#define PPC_IRQ_INIT_FN(name)                                         \
+#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(40x);
 PPC_IRQ_INIT_FN(6xx);
 PPC_IRQ_INIT_FN(970);
 
@@ -153,6 +163,18 @@
     gen_op_load_tbu();
 }
 
+__attribute__ (( unused ))
+static void spr_read_atbl (void *opaque, int sprn)
+{
+    gen_op_load_atbl();
+}
+
+__attribute__ (( unused ))
+static void spr_read_atbu (void *opaque, int sprn)
+{
+    gen_op_load_atbu();
+}
+
 #if !defined(CONFIG_USER_ONLY)
 static void spr_write_tbl (void *opaque, int sprn)
 {
@@ -163,6 +185,18 @@
 {
     gen_op_store_tbu();
 }
+
+__attribute__ (( unused ))
+static void spr_write_atbl (void *opaque, int sprn)
+{
+    gen_op_store_atbl();
+}
+
+__attribute__ (( unused ))
+static void spr_write_atbu (void *opaque, int sprn)
+{
+    gen_op_store_atbu();
+}
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
@@ -180,34 +214,22 @@
 
 static void spr_write_ibatu (void *opaque, int sprn)
 {
-    DisasContext *ctx = opaque;
-
     gen_op_store_ibatu((sprn - SPR_IBAT0U) / 2);
-    RET_STOP(ctx);
 }
 
 static void spr_write_ibatu_h (void *opaque, int sprn)
 {
-    DisasContext *ctx = opaque;
-
     gen_op_store_ibatu((sprn - SPR_IBAT4U) / 2);
-    RET_STOP(ctx);
 }
 
 static void spr_write_ibatl (void *opaque, int sprn)
 {
-    DisasContext *ctx = opaque;
-
     gen_op_store_ibatl((sprn - SPR_IBAT0L) / 2);
-    RET_STOP(ctx);
 }
 
 static void spr_write_ibatl_h (void *opaque, int sprn)
 {
-    DisasContext *ctx = opaque;
-
     gen_op_store_ibatl((sprn - SPR_IBAT4L) / 2);
-    RET_STOP(ctx);
 }
 
 /* DBAT0U...DBAT7U */
@@ -224,34 +246,22 @@
 
 static void spr_write_dbatu (void *opaque, int sprn)
 {
-    DisasContext *ctx = opaque;
-
     gen_op_store_dbatu((sprn - SPR_DBAT0U) / 2);
-    RET_STOP(ctx);
 }
 
 static void spr_write_dbatu_h (void *opaque, int sprn)
 {
-    DisasContext *ctx = opaque;
-
     gen_op_store_dbatu((sprn - SPR_DBAT4U) / 2);
-    RET_STOP(ctx);
 }
 
 static void spr_write_dbatl (void *opaque, int sprn)
 {
-    DisasContext *ctx = opaque;
-
     gen_op_store_dbatl((sprn - SPR_DBAT0L) / 2);
-    RET_STOP(ctx);
 }
 
 static void spr_write_dbatl_h (void *opaque, int sprn)
 {
-    DisasContext *ctx = opaque;
-
     gen_op_store_dbatl((sprn - SPR_DBAT4L) / 2);
-    RET_STOP(ctx);
 }
 
 /* SDR1 */
@@ -262,30 +272,25 @@
 
 static void spr_write_sdr1 (void *opaque, int sprn)
 {
-    DisasContext *ctx = opaque;
-
     gen_op_store_sdr1();
-    RET_STOP(ctx);
 }
 
 /* 64 bits PowerPC specific SPRs */
 /* ASR */
-/* Currently unused */
-#if 0 && defined(TARGET_PPC64)
+#if defined(TARGET_PPC64)
+__attribute__ (( unused ))
 static void spr_read_asr (void *opaque, int sprn)
 {
     gen_op_load_asr();
 }
 
+__attribute__ (( unused ))
 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) */
+#endif
 
 /* PowerPC 601 specific registers */
 /* RTC */
@@ -320,18 +325,12 @@
 
 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
 
@@ -353,18 +352,12 @@
 
     gen_op_store_40x_dbcr0();
     /* We must stop translation as we may have rebooted */
-    RET_STOP(ctx);
+    GEN_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)
@@ -388,10 +381,7 @@
 
 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)
@@ -400,6 +390,32 @@
 }
 #endif
 
+#if !defined(CONFIG_USER_ONLY)
+/* Callback used to write the exception vector base */
+static void spr_write_excp_prefix (void *opaque, int sprn)
+{
+    gen_op_store_excp_prefix();
+    gen_op_store_spr(sprn);
+}
+
+static void spr_write_excp_vector (void *opaque, int sprn)
+{
+    DisasContext *ctx = opaque;
+
+    if (sprn >= SPR_BOOKE_IVOR0 && sprn <= SPR_BOOKE_IVOR15) {
+        gen_op_store_excp_vector(sprn - SPR_BOOKE_IVOR0);
+        gen_op_store_spr(sprn);
+    } else if (sprn >= SPR_BOOKE_IVOR32 && sprn <= SPR_BOOKE_IVOR37) {
+        gen_op_store_excp_vector(sprn - SPR_BOOKE_IVOR32 + 32);
+        gen_op_store_spr(sprn);
+    } else {
+        printf("Trying to write an unknown exception vector %d %03x\n",
+               sprn, sprn);
+        GEN_EXCP_PRIVREG(ctx);
+    }
+}
+#endif
+
 #if defined(CONFIG_USER_ONLY)
 #define spr_register(env, num, name, uea_read, uea_write,                     \
                      oea_read, oea_write, initial_value)                      \
@@ -518,6 +534,7 @@
 /* BATs 0-3 */
 static void gen_low_BATs (CPUPPCState *env)
 {
+#if !defined(CONFIG_USER_ONLY)
     spr_register(env, SPR_IBAT0U, "IBAT0U",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_ibat, &spr_write_ibatu,
@@ -582,12 +599,14 @@
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_dbat, &spr_write_dbatl,
                  0x00000000);
-    env->nb_BATs = 4;
+    env->nb_BATs += 4;
+#endif
 }
 
 /* BATs 4-7 */
 static void gen_high_BATs (CPUPPCState *env)
 {
+#if !defined(CONFIG_USER_ONLY)
     spr_register(env, SPR_IBAT4U, "IBAT4U",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_ibat_h, &spr_write_ibatu_h,
@@ -652,7 +671,8 @@
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_dbat_h, &spr_write_dbatl_h,
                  0x00000000);
-    env->nb_BATs = 8;
+    env->nb_BATs += 4;
+#endif
 }
 
 /* Generic PowerPC time base */
@@ -679,6 +699,7 @@
 /* Softare table search registers */
 static void gen_6xx_7xx_soft_tlb (CPUPPCState *env, int nb_tlbs, int nb_ways)
 {
+#if !defined(CONFIG_USER_ONLY)
     env->nb_tlb = nb_tlbs;
     env->nb_ways = nb_ways;
     env->id_tlbs = 1;
@@ -710,6 +731,7 @@
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+#endif
 }
 
 /* SPR common to MPC755 and G2 */
@@ -797,38 +819,55 @@
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_SIA, "SIA",
+    spr_register(env, SPR_SIAR, "SIAR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
                  0x00000000);
+    /* XXX : not implemented */
     spr_register(env, SPR_UMMCR0, "UMMCR0",
                  &spr_read_ureg, SPR_NOACCESS,
                  &spr_read_ureg, SPR_NOACCESS,
                  0x00000000);
+    /* XXX : not implemented */
     spr_register(env, SPR_UMMCR1, "UMMCR1",
                  &spr_read_ureg, SPR_NOACCESS,
                  &spr_read_ureg, SPR_NOACCESS,
                  0x00000000);
+    /* XXX : not implemented */
     spr_register(env, SPR_UPMC1, "UPMC1",
                  &spr_read_ureg, SPR_NOACCESS,
                  &spr_read_ureg, SPR_NOACCESS,
                  0x00000000);
+    /* XXX : not implemented */
     spr_register(env, SPR_UPMC2, "UPMC2",
                  &spr_read_ureg, SPR_NOACCESS,
                  &spr_read_ureg, SPR_NOACCESS,
                  0x00000000);
+    /* XXX : not implemented */
     spr_register(env, SPR_UPMC3, "UPMC3",
                  &spr_read_ureg, SPR_NOACCESS,
                  &spr_read_ureg, SPR_NOACCESS,
                  0x00000000);
+    /* XXX : not implemented */
     spr_register(env, SPR_UPMC4, "UPMC4",
                  &spr_read_ureg, SPR_NOACCESS,
                  &spr_read_ureg, SPR_NOACCESS,
                  0x00000000);
-    spr_register(env, SPR_USIA, "USIA",
+    /* XXX : not implemented */
+    spr_register(env, SPR_USIAR, "USIAR",
                  &spr_read_ureg, SPR_NOACCESS,
                  &spr_read_ureg, SPR_NOACCESS,
                  0x00000000);
+    /* External access control */
+    /* XXX : not implemented */
+    spr_register(env, SPR_EAR, "EAR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+
+static void gen_spr_thrm (CPUPPCState *env)
+{
     /* Thermal management */
     /* XXX : not implemented */
     spr_register(env, SPR_THRM1, "THRM1",
@@ -845,12 +884,6 @@
                  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 specific to PowerPC 604 implementation */
@@ -904,7 +937,7 @@
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_SIA, "SIA",
+    spr_register(env, SPR_SIAR, "SIAR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
                  0x00000000);
@@ -937,12 +970,14 @@
 {
     /* Memory base address */
     /* MBAR */
+    /* XXX : not implemented */
     spr_register(env, SPR_MBAR, "MBAR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* System version register */
     /* SVR */
+    /* XXX : TODO: initialize it to an appropriate value */
     spr_register(env, SPR_SVR, "SVR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
@@ -1004,7 +1039,7 @@
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_ESASR, "ESASR",
+    spr_register(env, SPR_ESASRR, "ESASRR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
@@ -1030,6 +1065,11 @@
                  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);
 }
 
 /* SPR specific to PowerPC 601 implementation */
@@ -1072,6 +1112,7 @@
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* Memory management */
+#if !defined(CONFIG_USER_ONLY)
     spr_register(env, SPR_IBAT0U, "IBAT0U",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_601_ubat, &spr_write_601_ubatu,
@@ -1104,8 +1145,130 @@
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_601_ubat, &spr_write_601_ubatl,
                  0x00000000);
+    env->nb_BATs = 4;
+#endif
 }
 
+static void gen_spr_74xx (CPUPPCState *env)
+{
+    /* Processor identification */
+    spr_register(env, SPR_PIR, "PIR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_pir,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_MMCR2, "MMCR2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_UMMCR2, "UMMCR2",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    /* XXX: not implemented */
+    spr_register(env, SPR_BAMR, "BAMR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_UBAMR, "UBAMR",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_MSSCR0, "MSSCR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* 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);
+    /* Altivec */
+    spr_register(env, SPR_VRSAVE, "VRSAVE",
+                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+
+static void gen_l3_ctrl (CPUPPCState *env)
+{
+    /* L3CR */
+    /* XXX : not implemented */
+    spr_register(env, SPR_L3CR, "L3CR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* L3ITCR0 */
+    /* XXX : not implemented */
+    spr_register(env, SPR_L3ITCR0, "L3ITCR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* L3ITCR1 */
+    /* XXX : not implemented */
+    spr_register(env, SPR_L3ITCR1, "L3ITCR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* L3ITCR2 */
+    /* XXX : not implemented */
+    spr_register(env, SPR_L3ITCR2, "L3ITCR2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* L3ITCR3 */
+    /* XXX : not implemented */
+    spr_register(env, SPR_L3ITCR3, "L3ITCR3",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* L3OHCR */
+    /* XXX : not implemented */
+    spr_register(env, SPR_L3OHCR, "L3OHCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* L3PM */
+    /* XXX : not implemented */
+    spr_register(env, SPR_L3PM, "L3PM",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+
+static void gen_74xx_soft_tlb (CPUPPCState *env, int nb_tlbs, int nb_ways)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->nb_tlb = nb_tlbs;
+    env->nb_ways = nb_ways;
+    env->id_tlbs = 1;
+    /* XXX : not implemented */
+    spr_register(env, SPR_PTEHI, "PTEHI",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_PTELO, "PTELO",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_TLBMISS, "TLBMISS",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+#endif
+}
+
 /* PowerPC BookE SPR */
 static void gen_spr_BookE (CPUPPCState *env)
 {
@@ -1123,6 +1286,7 @@
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+#if 0
     spr_register(env, SPR_BOOKE_DSRR0, "DSRR0",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
@@ -1131,14 +1295,7 @@
                  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);
+#endif
     /* Debug */
     /* XXX : not implemented */
     spr_register(env, SPR_BOOKE_IAC1, "IAC1",
@@ -1210,97 +1367,99 @@
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVPR, "IVPR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_prefix,
                  0x00000000);
     /* Exception vectors */
     spr_register(env, SPR_BOOKE_IVOR0, "IVOR0",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR1, "IVOR1",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR2, "IVOR2",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR3, "IVOR3",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR4, "IVOR4",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR5, "IVOR5",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR6, "IVOR6",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR7, "IVOR7",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR8, "IVOR8",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR9, "IVOR9",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR10, "IVOR10",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR11, "IVOR11",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR12, "IVOR12",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR13, "IVOR13",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR14, "IVOR14",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR15, "IVOR15",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
+#if 0
     spr_register(env, SPR_BOOKE_IVOR32, "IVOR32",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR33, "IVOR33",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR34, "IVOR34",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR35, "IVOR35",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR36, "IVOR36",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
     spr_register(env, SPR_BOOKE_IVOR37, "IVOR37",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_vector,
                  0x00000000);
+#endif
     spr_register(env, SPR_BOOKE_PID, "PID",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
@@ -1364,75 +1523,91 @@
 /* FSL storage control registers */
 static void gen_spr_BookE_FSL (CPUPPCState *env)
 {
+#if !defined(CONFIG_USER_ONLY)
     /* TLB assist registers */
+    /* XXX : not implemented */
     spr_register(env, SPR_BOOKE_MAS0, "MAS0",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+    /* XXX : not implemented */
     spr_register(env, SPR_BOOKE_MAS1, "MAS2",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+    /* XXX : not implemented */
     spr_register(env, SPR_BOOKE_MAS2, "MAS3",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+    /* XXX : not implemented */
     spr_register(env, SPR_BOOKE_MAS3, "MAS4",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+    /* XXX : not implemented */
     spr_register(env, SPR_BOOKE_MAS4, "MAS5",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+    /* XXX : not implemented */
     spr_register(env, SPR_BOOKE_MAS6, "MAS6",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+    /* XXX : not implemented */
     spr_register(env, SPR_BOOKE_MAS7, "MAS7",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     if (env->nb_pids > 1) {
+        /* XXX : not implemented */
         spr_register(env, SPR_BOOKE_PID1, "PID1",
                      SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, &spr_write_generic,
                      0x00000000);
     }
     if (env->nb_pids > 2) {
+        /* XXX : not implemented */
         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",
+    /* XXX : not implemented */
+    spr_register(env, SPR_MMUCFG, "MMUCFG",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
                  0x00000000); /* TOFIX */
-    spr_register(env, SPR_BOOKE_MMUCSR0, "MMUCSR0",
+    /* XXX : not implemented */
+    spr_register(env, SPR_MMUCSR0, "MMUCSR0",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000); /* TOFIX */
     switch (env->nb_ways) {
     case 4:
+        /* XXX : not implemented */
         spr_register(env, SPR_BOOKE_TLB3CFG, "TLB3CFG",
                      SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, SPR_NOACCESS,
                      0x00000000); /* TOFIX */
         /* Fallthru */
     case 3:
+        /* XXX : not implemented */
         spr_register(env, SPR_BOOKE_TLB2CFG, "TLB2CFG",
                      SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, SPR_NOACCESS,
                      0x00000000); /* TOFIX */
         /* Fallthru */
     case 2:
+        /* XXX : not implemented */
         spr_register(env, SPR_BOOKE_TLB1CFG, "TLB1CFG",
                      SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, SPR_NOACCESS,
                      0x00000000); /* TOFIX */
         /* Fallthru */
     case 1:
+        /* XXX : not implemented */
         spr_register(env, SPR_BOOKE_TLB0CFG, "TLB0CFG",
                      SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, SPR_NOACCESS,
@@ -1442,6 +1617,7 @@
     default:
         break;
     }
+#endif
 }
 
 /* SPR specific to PowerPC 440 implementation */
@@ -1469,22 +1645,22 @@
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_440_DVT0, "DVT0",
+    spr_register(env, SPR_440_DTV0, "DTV0",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_440_DVT1, "DVT1",
+    spr_register(env, SPR_440_DTV1, "DTV1",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_440_DVT2, "DVT2",
+    spr_register(env, SPR_440_DTV2, "DTV2",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_440_DVT3, "DVT3",
+    spr_register(env, SPR_440_DTV3, "DTV3",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
@@ -1514,22 +1690,22 @@
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_440_IVT0, "IVT0",
+    spr_register(env, SPR_440_ITV0, "ITV0",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_440_IVT1, "IVT1",
+    spr_register(env, SPR_440_ITV1, "ITV1",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_440_IVT2, "IVT2",
+    spr_register(env, SPR_440_ITV2, "ITV2",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_440_IVT3, "IVT3",
+    spr_register(env, SPR_440_ITV3, "ITV3",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
@@ -1540,27 +1716,27 @@
                  0x00000000);
     /* Cache debug */
     /* XXX : not implemented */
-    spr_register(env, SPR_BOOKE_DCBTRH, "DCBTRH",
+    spr_register(env, SPR_BOOKE_DCDBTRH, "DCDBTRH",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_BOOKE_DCBTRL, "DCBTRL",
+    spr_register(env, SPR_BOOKE_DCDBTRL, "DCDBTRL",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_BOOKE_ICBDR, "ICBDR",
+    spr_register(env, SPR_BOOKE_ICDBDR, "ICDBDR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_BOOKE_ICBTRH, "ICBTRH",
+    spr_register(env, SPR_BOOKE_ICDBTRH, "ICDBTRH",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_BOOKE_ICBTRL, "ICBTRL",
+    spr_register(env, SPR_BOOKE_ICDBTRL, "ICDBTRL",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
                  0x00000000);
@@ -1589,40 +1765,21 @@
 static void gen_spr_40x (CPUPPCState *env)
 {
     /* Cache */
-    /* XXX : not implemented */
+    /* not emulated, as Qemu do not emulate caches */
     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 */
+    /* not emulated, as Qemu do not emulate caches */
     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",
+    /* not emulated, as Qemu do not emulate caches */
+    spr_register(env, SPR_BOOKE_ICDBDR, "ICDBDR",
                  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,
@@ -1634,7 +1791,7 @@
                  0x00000000);
     spr_register(env, SPR_40x_EVPR, "EVPR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_excp_prefix,
                  0x00000000);
     spr_register(env, SPR_40x_SRR2, "SRR2",
                  &spr_read_generic, &spr_write_generic,
@@ -1657,58 +1814,62 @@
                  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 specific to PowerPC 405 implementation */
+static void gen_spr_405 (CPUPPCState *env)
+{
+    /* MMU */
+    spr_register(env, SPR_40x_PID, "PID",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
-    spr_register(env, SPR_40x_DAC2, "DAC2",
+    spr_register(env, SPR_4xx_CCR0, "CCR0",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
-                 0x00000000);
+                 0x00700000);
+    /* Debug interface */
     /* 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_405_DBCR1, "DBCR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 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_register(env, SPR_40x_DAC1, "DAC1",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
-    spr_register(env, SPR_40x_IAC2, "IAC2",
+    spr_register(env, SPR_40x_DAC2, "DAC2",
                  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",
+    /* XXX : not implemented */
+    spr_register(env, SPR_405_DVC1, "DVC1",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
-                 0x00700000);
-    /* Debug */
+                 0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_405_DBCR1, "DBCR1",
+    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_DVC1, "DVC1",
+    spr_register(env, SPR_40x_IAC1, "IAC1",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_405_DVC2, "DVC2",
+    spr_register(env, SPR_40x_IAC2, "IAC2",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
@@ -1723,10 +1884,15 @@
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* Storage control */
+    /* XXX: TODO: not implemented */
     spr_register(env, SPR_405_SLER, "SLER",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_40x_sler,
                  0x00000000);
+    spr_register(env, SPR_40x_ZPR, "ZPR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
     /* XXX : not implemented */
     spr_register(env, SPR_405_SU0R, "SU0R",
                  SPR_NOACCESS, SPR_NOACCESS,
@@ -1792,17 +1958,108 @@
                  SPR_NOACCESS, &spr_write_tbu,
                  0x00000000);
     /* Debug */
-    /* XXX: not implemented */
+    /* not emulated, as Qemu do not emulate caches */
     spr_register(env, SPR_403_CDBCR, "CDBCR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
 }
 
+/* SPR specific to PowerPC 401 implementation */
+static void gen_spr_401 (CPUPPCState *env)
+{
+    /* Debug interface */
+    /* XXX : not implemented */
+    spr_register(env, SPR_40x_DBCR0, "DBCR",
+                 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_DAC1, "DAC",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_40x_IAC1, "IAC",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Storage control */
+    /* XXX: TODO: not implemented */
+    spr_register(env, SPR_405_SLER, "SLER",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_40x_sler,
+                 0x00000000);
+    /* not emulated, as Qemu never does speculative access */
+    spr_register(env, SPR_40x_SGR, "SGR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0xFFFFFFFF);
+    /* not emulated, as Qemu do not emulate caches */
+    spr_register(env, SPR_40x_DCWR, "DCWR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+
+static void gen_spr_401x2 (CPUPPCState *env)
+{
+    gen_spr_401(env);
+    spr_register(env, SPR_40x_PID, "PID",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_40x_ZPR, "ZPR",
+                 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 */
+    /* Debug interface */
+    /* 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_DAC1, "DAC1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* 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_IAC1, "IAC1",
+                 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);
+}
+
+static void gen_spr_403_real (CPUPPCState *env)
+{
     spr_register(env, SPR_403_PBL1,  "PBL1",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_403_pbr, &spr_write_403_pbr,
@@ -1819,614 +2076,3960 @@
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_403_pbr, &spr_write_403_pbr,
                  0x00000000);
-    /* Debug */
-    /* XXX : not implemented */
-    spr_register(env, SPR_40x_DAC2, "DAC2",
+}
+
+static void gen_spr_403_mmu (CPUPPCState *env)
+{
+    /* MMU */
+    spr_register(env, SPR_40x_PID, "PID",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_40x_IAC2, "IAC2",
+    spr_register(env, SPR_40x_ZPR, "ZPR",
                  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)
 {
+    /* XXX : not implemented */
     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)
+#if defined (TARGET_PPC64)
+/* SPR specific to PowerPC 620 */
+static void gen_spr_620 (CPUPPCState *env)
+{
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMR0, "PMR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMR1, "PMR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMR2, "PMR2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMR3, "PMR3",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMR4, "PMR4",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMR5, "PMR5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMR6, "PMR6",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMR7, "PMR7",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMR8, "PMR8",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMR9, "PMR9",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMRA, "PMR10",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMRB, "PMR11",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMRC, "PMR12",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMRD, "PMR13",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMRE, "PMR14",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_PMRF, "PMR15",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_HID8, "HID8",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_620_HID9, "HID9",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+#endif /* defined (TARGET_PPC64) */
+
+// XXX: TODO
 /*
- * ASR => SPR 280 (64 bits)
- * FPECR => SPR 1022 (?)
- * VRSAVE => SPR 256 (Altivec)
- * SCOMC => SPR 276 (64 bits ?)
- * SCOMD => SPR 277 (64 bits ?)
- * HSPRG0 => SPR 304 (hypervisor)
- * HSPRG1 => SPR 305 (hypervisor)
- * HDEC => SPR 310 (hypervisor)
- * HIOR => SPR 311 (hypervisor)
- * RMOR => SPR 312 (970)
- * HRMOR => SPR 313 (hypervisor)
- * HSRR0 => SPR 314 (hypervisor)
- * HSRR1 => SPR 315 (hypervisor)
- * LPCR => SPR 316 (970)
- * LPIDR => SPR 317 (970)
+ * AMR     => SPR 29 (Power 2.04)
+ * CTRL    => SPR 136 (Power 2.04)
+ * CTRL    => SPR 152 (Power 2.04)
+ * SCOMC   => SPR 276 (64 bits ?)
+ * SCOMD   => SPR 277 (64 bits ?)
+ * TBU40   => SPR 286 (Power 2.04 hypv)
+ * HSPRG0  => SPR 304 (Power 2.04 hypv)
+ * HSPRG1  => SPR 305 (Power 2.04 hypv)
+ * HDSISR  => SPR 306 (Power 2.04 hypv)
+ * HDAR    => SPR 307 (Power 2.04 hypv)
+ * PURR    => SPR 309 (Power 2.04 hypv)
+ * HDEC    => SPR 310 (Power 2.04 hypv)
+ * HIOR    => SPR 311 (hypv)
+ * RMOR    => SPR 312 (970)
+ * HRMOR   => SPR 313 (Power 2.04 hypv)
+ * HSRR0   => SPR 314 (Power 2.04 hypv)
+ * HSRR1   => SPR 315 (Power 2.04 hypv)
+ * LPCR    => SPR 316 (970)
+ * LPIDR   => SPR 317 (970)
+ * SPEFSCR => SPR 512 (Power 2.04 emb)
+ * EPR     => SPR 702 (Power 2.04 emb)
+ * perf    => 768-783 (Power 2.04)
+ * perf    => 784-799 (Power 2.04)
+ * PPR     => SPR 896 (Power 2.04)
+ * EPLC    => SPR 947 (Power 2.04 emb)
+ * EPSC    => SPR 948 (Power 2.04 emb)
+ * DABRX   => 1015    (Power 2.04 hypv)
+ * FPECR   => SPR 1022 (?)
  * ... and more (thermal management, performance counters, ...)
  */
 
-static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
+/*****************************************************************************/
+/* Exception vectors models                                                  */
+static void init_excp_4xx_real (CPUPPCState *env)
 {
-    env->reserve = -1;
-    /* Default MMU definitions */
-    env->nb_BATs = -1;
-    env->nb_tlb = 0;
-    env->nb_ways = 0;
-    /* XXX: missing:
-     * 32 bits PowerPC:
-     * - MPC5xx(x)
-     * - MPC8xx(x)
-     * - RCPU (same as MPC5xx ?)
-     */
-    spr_register(env, SPR_PVR, "PVR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, SPR_NOACCESS,
-                 def->pvr);
-    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);
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_PIT]      = 0x00001000;
+    env->excp_vectors[POWERPC_EXCP_FIT]      = 0x00001010;
+    env->excp_vectors[POWERPC_EXCP_WDT]      = 0x00001020;
+    env->excp_vectors[POWERPC_EXCP_DEBUG]    = 0x00002000;
+    env->excp_prefix = 0x00000000;
+    env->ivor_mask = 0x0000FFF0;
+    env->ivpr_mask = 0xFFFF0000;
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
 #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;
+static void init_excp_4xx_softmmu (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_PIT]      = 0x00001000;
+    env->excp_vectors[POWERPC_EXCP_FIT]      = 0x00001010;
+    env->excp_vectors[POWERPC_EXCP_WDT]      = 0x00001020;
+    env->excp_vectors[POWERPC_EXCP_DTLB]     = 0x00001100;
+    env->excp_vectors[POWERPC_EXCP_ITLB]     = 0x00001200;
+    env->excp_vectors[POWERPC_EXCP_DEBUG]    = 0x00002000;
+    env->excp_prefix = 0x00000000;
+    env->ivor_mask = 0x0000FFF0;
+    env->ivpr_mask = 0xFFFF0000;
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
+#endif
+}
 
-    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;
+static void init_excp_BookE (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_APU]      = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_FIT]      = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_WDT]      = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_DTLB]     = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_ITLB]     = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_DEBUG]    = 0x00000000;
+    env->excp_prefix = 0x00000000;
+    env->ivor_mask = 0x0000FFE0;
+    env->ivpr_mask = 0xFFFF0000;
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
+#endif
+}
 
-    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;
+static void init_excp_601 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_IO]       = 0x00000A00;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_RUNM]     = 0x00002000;
+    env->excp_prefix = 0xFFF00000;
+    /* Hardware reset vector */
+    env->hreset_vector = 0x00000100UL;
+#endif
+}
 
-#if defined (TODO)
-    case CPU_PPC_STB01000:
+static void init_excp_602 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_FPA]      = 0x00000E00;
+    env->excp_vectors[POWERPC_EXCP_IFTLB]    = 0x00001000;
+    env->excp_vectors[POWERPC_EXCP_DLTLB]    = 0x00001100;
+    env->excp_vectors[POWERPC_EXCP_DSTLB]    = 0x00001200;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+    env->excp_vectors[POWERPC_EXCP_WDT]      = 0x00001500;
+    env->excp_vectors[POWERPC_EXCP_EMUL]     = 0x00001600;
+    env->excp_prefix = 0xFFF00000;
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
 #endif
-#if defined (TODO)
-    case CPU_PPC_STB01010:
+}
+
+static void init_excp_603 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_IFTLB]    = 0x00001000;
+    env->excp_vectors[POWERPC_EXCP_DLTLB]    = 0x00001100;
+    env->excp_vectors[POWERPC_EXCP_DSTLB]    = 0x00001200;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
 #endif
-#if defined (TODO)
-    case CPU_PPC_STB0210:
+}
+
+static void init_excp_G2 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000A00;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_IFTLB]    = 0x00001000;
+    env->excp_vectors[POWERPC_EXCP_DLTLB]    = 0x00001100;
+    env->excp_vectors[POWERPC_EXCP_DSTLB]    = 0x00001200;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
 #endif
-    case CPU_PPC_STB03:   /* STB03 family                  */
-#if defined (TODO)
-    case CPU_PPC_STB043:  /* STB043 family                  */
+}
+
+static void init_excp_604 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
 #endif
-#if defined (TODO)
-    case CPU_PPC_STB045:  /* STB045 family                  */
+}
+
+#if defined(TARGET_PPC64)
+static void init_excp_620 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_FPA]      = 0x00000E00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+    /* Hardware reset vector */
+    env->hreset_vector = 0x0000000000000100ULL; /* ? */
 #endif
-    case CPU_PPC_STB25:   /* STB25 family                  */
-#if defined (TODO)
-    case CPU_PPC_STB130:  /* STB130 family                 */
+}
+#endif /* defined(TARGET_PPC64) */
+
+static void init_excp_7x0 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
 #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;
+static void init_excp_750FX (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+    env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
+#endif
+}
 
-    /* Embedded PowerPC from Freescale                     */
-#if defined (TODO)
-    case CPU_PPC_5xx:
-        break;
+/* XXX: Check if this is correct */
+static void init_excp_7x5 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_IFTLB]    = 0x00001000;
+    env->excp_vectors[POWERPC_EXCP_DLTLB]    = 0x00001100;
+    env->excp_vectors[POWERPC_EXCP_DSTLB]    = 0x00001200;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
 #endif
-#if defined (TODO)
-    case CPU_PPC_8xx:     /* MPC821 / 823 / 850 / 860      */
-        break;
+}
+
+static void init_excp_7400 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_VPU]      = 0x00000F20;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+    env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001600;
+    env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
 #endif
-#if defined (TODO)
-    case CPU_PPC_82xx_HIP3:    /* MPC8240 / 8260                */
-    case CPU_PPC_82xx_HIP4:    /* MPC8240 / 8260                */
-        break;
+}
+
+static void init_excp_7450 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_VPU]      = 0x00000F20;
+    env->excp_vectors[POWERPC_EXCP_IFTLB]    = 0x00001000;
+    env->excp_vectors[POWERPC_EXCP_DLTLB]    = 0x00001100;
+    env->excp_vectors[POWERPC_EXCP_DSTLB]    = 0x00001200;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+    env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001600;
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
 #endif
-#if defined (TODO)
-    case CPU_PPC_827x:    /* MPC 827x / 828x               */
-        break;
+}
+
+#if defined (TARGET_PPC64)
+static void init_excp_970 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_DSEG]     = 0x00000380;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_ISEG]     = 0x00000480;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+    env->excp_vectors[POWERPC_EXCP_HDECR]    = 0x00000980;
 #endif
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_VPU]      = 0x00000F20;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_MAINT]    = 0x00001600;
+    env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001700;
+    env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001800;
+    /* Hardware reset vector */
+    env->hreset_vector = 0x0000000000000100ULL;
+#endif
+}
+#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;
+/*****************************************************************************/
+/* Power management enable checks                                            */
+static int check_pow_none (CPUPPCState *env)
+{
+    return 0;
+}
 
-#if defined (TODO)
-    case CPU_PPC_e600:
-        break;
+static int check_pow_nocheck (CPUPPCState *env)
+{
+    return 1;
+}
+
+static int check_pow_hid0 (CPUPPCState *env)
+{
+    if (env->spr[SPR_HID0] & 0x00E00000)
+        return 1;
+
+    return 0;
+}
+
+/*****************************************************************************/
+/* PowerPC implementations definitions                                       */
+
+/* PowerPC 40x instruction set                                               */
+#define POWERPC_INSNS_EMB    (PPC_INSNS_BASE | PPC_CACHE_DCBZ | PPC_EMB_COMMON)
+
+/* PowerPC 401                                                               */
+#define POWERPC_INSNS_401    (POWERPC_INSNS_EMB |                             \
+                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
+                              PPC_4xx_COMMON | PPC_40x_EXCP | PPC_40x_ICBT)
+#define POWERPC_MSRM_401     (0x00000000000FD201ULL)
+#define POWERPC_MMU_401      (POWERPC_MMU_REAL_4xx)
+#define POWERPC_EXCP_401     (POWERPC_EXCP_40x)
+#define POWERPC_INPUT_401    (PPC_FLAGS_INPUT_401)
+#define POWERPC_BFDM_401     (bfd_mach_ppc_403)
+#define POWERPC_FLAG_401     (POWERPC_FLAG_CE | POWERPC_FLAG_DE)
+#define check_pow_401        check_pow_nocheck
+
+static void init_proc_401 (CPUPPCState *env)
+{
+    gen_spr_40x(env);
+    gen_spr_401_403(env);
+    gen_spr_401(env);
+    init_excp_4xx_real(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc40x_irq_init(env);
+}
+
+/* PowerPC 401x2                                                             */
+#define POWERPC_INSNS_401x2  (POWERPC_INSNS_EMB |                             \
+                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
+                              PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
+                              PPC_CACHE_DCBA | PPC_MFTB |                     \
+                              PPC_4xx_COMMON | PPC_40x_EXCP | PPC_40x_ICBT)
+#define POWERPC_MSRM_401x2   (0x00000000001FD231ULL)
+#define POWERPC_MMU_401x2    (POWERPC_MMU_SOFT_4xx_Z)
+#define POWERPC_EXCP_401x2   (POWERPC_EXCP_40x)
+#define POWERPC_INPUT_401x2  (PPC_FLAGS_INPUT_401)
+#define POWERPC_BFDM_401x2   (bfd_mach_ppc_403)
+#define POWERPC_FLAG_401x2   (POWERPC_FLAG_CE | POWERPC_FLAG_DE)
+#define check_pow_401x2      check_pow_nocheck
+
+static void init_proc_401x2 (CPUPPCState *env)
+{
+    gen_spr_40x(env);
+    gen_spr_401_403(env);
+    gen_spr_401x2(env);
+    gen_spr_compress(env);
+    /* Memory management */
+#if !defined(CONFIG_USER_ONLY)
+    env->nb_tlb = 64;
+    env->nb_ways = 1;
+    env->id_tlbs = 0;
 #endif
+    init_excp_4xx_softmmu(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc40x_irq_init(env);
+}
 
-    /* 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);
+/* PowerPC 401x3                                                             */
+#define POWERPC_INSNS_401x3  (POWERPC_INSNS_EMB |                             \
+                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
+                              PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
+                              PPC_CACHE_DCBA | PPC_MFTB |                     \
+                              PPC_4xx_COMMON | PPC_40x_EXCP | PPC_40x_ICBT)
+#define POWERPC_MSRM_401x3   (0x00000000001FD631ULL)
+#define POWERPC_MMU_401x3    (POWERPC_MMU_SOFT_4xx_Z)
+#define POWERPC_EXCP_401x3   (POWERPC_EXCP_40x)
+#define POWERPC_INPUT_401x3  (PPC_FLAGS_INPUT_401)
+#define POWERPC_BFDM_401x3   (bfd_mach_ppc_403)
+#define POWERPC_FLAG_401x3   (POWERPC_FLAG_CE | POWERPC_FLAG_DE)
+#define check_pow_401x3      check_pow_nocheck
+
+__attribute__ (( unused ))
+static void init_proc_401x3 (CPUPPCState *env)
+{
+    gen_spr_40x(env);
+    gen_spr_401_403(env);
+    gen_spr_401(env);
+    gen_spr_401x2(env);
+    gen_spr_compress(env);
+    init_excp_4xx_softmmu(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc40x_irq_init(env);
+}
+
+/* IOP480                                                                    */
+#define POWERPC_INSNS_IOP480 (POWERPC_INSNS_EMB |                             \
+                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
+                              PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
+                              PPC_CACHE_DCBA |                                \
+                              PPC_4xx_COMMON | PPC_40x_EXCP |  PPC_40x_ICBT)
+#define POWERPC_MSRM_IOP480  (0x00000000001FD231ULL)
+#define POWERPC_MMU_IOP480   (POWERPC_MMU_SOFT_4xx_Z)
+#define POWERPC_EXCP_IOP480  (POWERPC_EXCP_40x)
+#define POWERPC_INPUT_IOP480 (PPC_FLAGS_INPUT_401)
+#define POWERPC_BFDM_IOP480  (bfd_mach_ppc_403)
+#define POWERPC_FLAG_IOP480  (POWERPC_FLAG_CE | POWERPC_FLAG_DE)
+#define check_pow_IOP480     check_pow_nocheck
+
+static void init_proc_IOP480 (CPUPPCState *env)
+{
+    gen_spr_40x(env);
+    gen_spr_401_403(env);
+    gen_spr_401x2(env);
+    gen_spr_compress(env);
+    /* Memory management */
+#if !defined(CONFIG_USER_ONLY)
+    env->nb_tlb = 64;
+    env->nb_ways = 1;
+    env->id_tlbs = 0;
 #endif
-        env->nb_tlb = 64;
-        env->nb_ways = 2;
-        env->id_tlbs = 0;
-        env->id_tlbs = 0;
-        /* XXX: TODO: allocate internal IRQ controller */
-        break;
+    init_excp_4xx_softmmu(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc40x_irq_init(env);
+}
 
-    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_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,
-                     &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;
+/* PowerPC 403                                                               */
+#define POWERPC_INSNS_403    (POWERPC_INSNS_EMB |                             \
+                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
+                              PPC_4xx_COMMON | PPC_40x_EXCP | PPC_40x_ICBT)
+#define POWERPC_MSRM_403     (0x000000000007D00DULL)
+#define POWERPC_MMU_403      (POWERPC_MMU_REAL_4xx)
+#define POWERPC_EXCP_403     (POWERPC_EXCP_40x)
+#define POWERPC_INPUT_403    (PPC_FLAGS_INPUT_401)
+#define POWERPC_BFDM_403     (bfd_mach_ppc_403)
+#define POWERPC_FLAG_403     (POWERPC_FLAG_CE | POWERPC_FLAG_PX)
+#define check_pow_403        check_pow_nocheck
 
-    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_6xx_7xx_soft_tlb(env, 64, 2);
-        gen_spr_603(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;
+static void init_proc_403 (CPUPPCState *env)
+{
+    gen_spr_40x(env);
+    gen_spr_401_403(env);
+    gen_spr_403(env);
+    gen_spr_403_real(env);
+    init_excp_4xx_real(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc40x_irq_init(env);
+#if !defined(CONFIG_USER_ONLY)
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
+#endif
+}
 
-    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;
+/* PowerPC 403 GCX                                                           */
+#define POWERPC_INSNS_403GCX (POWERPC_INSNS_EMB |                             \
+                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
+                              PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
+                              PPC_4xx_COMMON | PPC_40x_EXCP | PPC_40x_ICBT)
+#define POWERPC_MSRM_403GCX  (0x000000000007D00DULL)
+#define POWERPC_MMU_403GCX   (POWERPC_MMU_SOFT_4xx_Z)
+#define POWERPC_EXCP_403GCX  (POWERPC_EXCP_40x)
+#define POWERPC_INPUT_403GCX (PPC_FLAGS_INPUT_401)
+#define POWERPC_BFDM_403GCX  (bfd_mach_ppc_403)
+#define POWERPC_FLAG_403GCX  (POWERPC_FLAG_CE | POWERPC_FLAG_PX)
+#define check_pow_403GCX     check_pow_nocheck
 
-    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",
-                     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;
+static void init_proc_403GCX (CPUPPCState *env)
+{
+    gen_spr_40x(env);
+    gen_spr_401_403(env);
+    gen_spr_403(env);
+    gen_spr_403_real(env);
+    gen_spr_403_mmu(env);
+    /* Bus access control */
+    /* not emulated, as Qemu never does speculative access */
+    spr_register(env, SPR_40x_SGR, "SGR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0xFFFFFFFF);
+    /* not emulated, as Qemu do not emulate caches */
+    spr_register(env, SPR_40x_DCWR, "DCWR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Memory management */
+#if !defined(CONFIG_USER_ONLY)
+    env->nb_tlb = 64;
+    env->nb_ways = 1;
+    env->id_tlbs = 0;
+#endif
+    init_excp_4xx_softmmu(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc40x_irq_init(env);
+}
 
-    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;
+/* PowerPC 405                                                               */
+#define POWERPC_INSNS_405    (POWERPC_INSNS_EMB | PPC_MFTB |                  \
+                              PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_CACHE_DCBA | \
+                              PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
+                              PPC_4xx_COMMON | PPC_40x_EXCP | PPC_40x_ICBT |  \
+                              PPC_405_MAC)
+#define POWERPC_MSRM_405     (0x000000000006E630ULL)
+#define POWERPC_MMU_405      (POWERPC_MMU_SOFT_4xx)
+#define POWERPC_EXCP_405     (POWERPC_EXCP_40x)
+#define POWERPC_INPUT_405    (PPC_FLAGS_INPUT_405)
+#define POWERPC_BFDM_405     (bfd_mach_ppc_403)
+#define POWERPC_FLAG_405     (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
+                              POWERPC_FLAG_DE)
+#define check_pow_405        check_pow_nocheck
 
-    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_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;
+static void init_proc_405 (CPUPPCState *env)
+{
+    /* Time base */
+    gen_tbl(env);
+    gen_spr_40x(env);
+    gen_spr_405(env);
+    /* Bus access control */
+    /* not emulated, as Qemu never does speculative access */
+    spr_register(env, SPR_40x_SGR, "SGR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0xFFFFFFFF);
+    /* not emulated, as Qemu do not emulate caches */
+    spr_register(env, SPR_40x_DCWR, "DCWR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Memory management */
+#if !defined(CONFIG_USER_ONLY)
+    env->nb_tlb = 64;
+    env->nb_ways = 1;
+    env->id_tlbs = 0;
+#endif
+    init_excp_4xx_softmmu(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc40x_irq_init(env);
+}
 
-    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",
-                     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;
+/* PowerPC 440 EP                                                            */
+#define POWERPC_INSNS_440EP  (POWERPC_INSNS_EMB |                             \
+                              PPC_CACHE_DCBA | PPC_MEM_TLBSYNC |              \
+                              PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |      \
+                              PPC_440_SPEC | PPC_RFMCI)
+#define POWERPC_MSRM_440EP   (0x000000000006D630ULL)
+#define POWERPC_MMU_440EP    (POWERPC_MMU_BOOKE)
+#define POWERPC_EXCP_440EP   (POWERPC_EXCP_BOOKE)
+#define POWERPC_INPUT_440EP  (PPC_FLAGS_INPUT_BookE)
+#define POWERPC_BFDM_440EP   (bfd_mach_ppc_403)
+#define POWERPC_FLAG_440EP   (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
+                              POWERPC_FLAG_DE)
+#define check_pow_440EP      check_pow_nocheck
 
-#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;
+static void init_proc_440EP (CPUPPCState *env)
+{
+    /* Time base */
+    gen_tbl(env);
+    gen_spr_BookE(env);
+    gen_spr_440(env);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_MCSR, "MCSR",
+                 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);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_CCR1, "CCR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Memory management */
+#if !defined(CONFIG_USER_ONLY)
+    env->nb_tlb = 64;
+    env->nb_ways = 1;
+    env->id_tlbs = 0;
 #endif
+    init_excp_BookE(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* XXX: TODO: allocate internal IRQ controller */
+}
 
-    /* 64 bits PowerPC                                     */
+/* PowerPC 440 GP                                                            */
+#define POWERPC_INSNS_440GP  (POWERPC_INSNS_EMB |                             \
+                              PPC_CACHE_DCBA | PPC_MEM_TLBSYNC |              \
+                              PPC_BOOKE | PPC_BOOKE_EXT | PPC_4xx_COMMON |    \
+                              PPC_405_MAC | PPC_440_SPEC)
+#define POWERPC_MSRM_440GP   (0x000000000006FF30ULL)
+#define POWERPC_MMU_440GP    (POWERPC_MMU_BOOKE)
+#define POWERPC_EXCP_440GP   (POWERPC_EXCP_BOOKE)
+#define POWERPC_INPUT_440GP  (PPC_FLAGS_INPUT_BookE)
+#define POWERPC_BFDM_440GP   (bfd_mach_ppc_403)
+#define POWERPC_FLAG_440GP   (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
+                              POWERPC_FLAG_DE)
+#define check_pow_440GP      check_pow_nocheck
+
+static void init_proc_440GP (CPUPPCState *env)
+{
+    /* Time base */
+    gen_tbl(env);
+    gen_spr_BookE(env);
+    gen_spr_440(env);
+    /* Memory management */
+#if !defined(CONFIG_USER_ONLY)
+    env->nb_tlb = 64;
+    env->nb_ways = 1;
+    env->id_tlbs = 0;
+#endif
+    init_excp_BookE(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* XXX: TODO: allocate internal IRQ controller */
+}
+
+/* PowerPC 440x4                                                             */
+#define POWERPC_INSNS_440x4  (POWERPC_INSNS_EMB |                             \
+                              PPC_CACHE_DCBA | PPC_MEM_TLBSYNC |              \
+                              PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |      \
+                              PPC_440_SPEC)
+#define POWERPC_MSRM_440x4   (0x000000000006FF30ULL)
+#define POWERPC_MMU_440x4    (POWERPC_MMU_BOOKE)
+#define POWERPC_EXCP_440x4   (POWERPC_EXCP_BOOKE)
+#define POWERPC_INPUT_440x4  (PPC_FLAGS_INPUT_BookE)
+#define POWERPC_BFDM_440x4   (bfd_mach_ppc_403)
+#define POWERPC_FLAG_440x4   (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
+                              POWERPC_FLAG_DE)
+#define check_pow_440x4      check_pow_nocheck
+
+__attribute__ (( unused ))
+static void init_proc_440x4 (CPUPPCState *env)
+{
+    /* Time base */
+    gen_tbl(env);
+    gen_spr_BookE(env);
+    gen_spr_440(env);
+    /* Memory management */
+#if !defined(CONFIG_USER_ONLY)
+    env->nb_tlb = 64;
+    env->nb_ways = 1;
+    env->id_tlbs = 0;
+#endif
+    init_excp_BookE(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* XXX: TODO: allocate internal IRQ controller */
+}
+
+/* PowerPC 440x5                                                             */
+#define POWERPC_INSNS_440x5  (POWERPC_INSNS_EMB |                             \
+                              PPC_CACHE_DCBA | PPC_MEM_TLBSYNC |              \
+                              PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |      \
+                              PPC_440_SPEC | PPC_RFMCI)
+#define POWERPC_MSRM_440x5   (0x000000000006FF30ULL)
+#define POWERPC_MMU_440x5    (POWERPC_MMU_BOOKE)
+#define POWERPC_EXCP_440x5   (POWERPC_EXCP_BOOKE)
+#define POWERPC_INPUT_440x5  (PPC_FLAGS_INPUT_BookE)
+#define POWERPC_BFDM_440x5   (bfd_mach_ppc_403)
+#define POWERPC_FLAG_440x5   (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |           \
+                              POWERPC_FLAG_DE)
+#define check_pow_440x5      check_pow_nocheck
+
+static void init_proc_440x5 (CPUPPCState *env)
+{
+    /* Time base */
+    gen_tbl(env);
+    gen_spr_BookE(env);
+    gen_spr_440(env);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_MCSR, "MCSR",
+                 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);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_CCR1, "CCR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Memory management */
+#if !defined(CONFIG_USER_ONLY)
+    env->nb_tlb = 64;
+    env->nb_ways = 1;
+    env->id_tlbs = 0;
+#endif
+    init_excp_BookE(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* XXX: TODO: allocate internal IRQ controller */
+}
+
+/* PowerPC 460 (guessed)                                                     */
+#define POWERPC_INSNS_460    (POWERPC_INSNS_EMB |                             \
+                              PPC_CACHE_DCBA | PPC_MEM_TLBSYNC |              \
+                              PPC_BOOKE | PPC_BOOKE_EXT | PPC_4xx_COMMON |    \
+                              PPC_405_MAC | PPC_440_SPEC | PPC_DCRUX)
+#define POWERPC_MSRM_460     (0x000000000006FF30ULL)
+#define POWERPC_MMU_460      (POWERPC_MMU_BOOKE)
+#define POWERPC_EXCP_460     (POWERPC_EXCP_BOOKE)
+#define POWERPC_INPUT_460    (PPC_FLAGS_INPUT_BookE)
+#define POWERPC_BFDM_460     (bfd_mach_ppc_403)
+#define POWERPC_FLAG_460     (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
+                              POWERPC_FLAG_DE)
+#define check_pow_460        check_pow_nocheck
+
+__attribute__ (( unused ))
+static void init_proc_460 (CPUPPCState *env)
+{
+    /* Time base */
+    gen_tbl(env);
+    gen_spr_BookE(env);
+    gen_spr_440(env);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_MCSR, "MCSR",
+                 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);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_CCR1, "CCR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_DCRIPR, "SPR_DCRIPR",
+                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Memory management */
+#if !defined(CONFIG_USER_ONLY)
+    env->nb_tlb = 64;
+    env->nb_ways = 1;
+    env->id_tlbs = 0;
+#endif
+    init_excp_BookE(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* XXX: TODO: allocate internal IRQ controller */
+}
+
+/* PowerPC 460F (guessed)                                                    */
+#define POWERPC_INSNS_460F   (POWERPC_INSNS_EMB |                             \
+                              PPC_CACHE_DCBA | PPC_MEM_TLBSYNC |              \
+                              PPC_FLOAT | PPC_FLOAT_FSQRT | PPC_FLOAT_FRES |  \
+                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_FSEL |            \
+                              PPC_FLOAT_STFIWX |                              \
+                              PPC_BOOKE | PPC_BOOKE_EXT | PPC_4xx_COMMON |    \
+                              PPC_405_MAC | PPC_440_SPEC | PPC_DCRUX)
+#define POWERPC_MSRM_460     (0x000000000006FF30ULL)
+#define POWERPC_MMU_460F     (POWERPC_MMU_BOOKE)
+#define POWERPC_EXCP_460F    (POWERPC_EXCP_BOOKE)
+#define POWERPC_INPUT_460F   (PPC_FLAGS_INPUT_BookE)
+#define POWERPC_BFDM_460F    (bfd_mach_ppc_403)
+#define POWERPC_FLAG_460F    (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
+                              POWERPC_FLAG_DE)
+#define check_pow_460F       check_pow_nocheck
+
+__attribute__ (( unused ))
+static void init_proc_460F (CPUPPCState *env)
+{
+    /* Time base */
+    gen_tbl(env);
+    gen_spr_BookE(env);
+    gen_spr_440(env);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_MCSR, "MCSR",
+                 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);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_CCR1, "CCR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_DCRIPR, "SPR_DCRIPR",
+                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Memory management */
+#if !defined(CONFIG_USER_ONLY)
+    env->nb_tlb = 64;
+    env->nb_ways = 1;
+    env->id_tlbs = 0;
+#endif
+    init_excp_BookE(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* XXX: TODO: allocate internal IRQ controller */
+}
+
+/* Generic BookE PowerPC                                                     */
+#define POWERPC_INSNS_BookE  (POWERPC_INSNS_EMB |                             \
+                              PPC_MEM_EIEIO | PPC_MEM_TLBSYNC |               \
+                              PPC_CACHE_DCBA |                                \
+                              PPC_FLOAT | PPC_FLOAT_FSQRT |                   \
+                              PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE |            \
+                              PPC_FLOAT_FSEL | PPC_FLOAT_STFIW |              \
+                              PPC_BOOKE)
+#define POWERPC_MSRM_BookE   (0x000000000006D630ULL)
+#define POWERPC_MMU_BookE    (POWERPC_MMU_BOOKE)
+#define POWERPC_EXCP_BookE   (POWERPC_EXCP_BOOKE)
+#define POWERPC_INPUT_BookE  (PPC_FLAGS_INPUT_BookE)
+#define POWERPC_BFDM_BookE   (bfd_mach_ppc_403)
+#define POWERPC_FLAG_BookE   (POWERPC_FLAG_NONE)
+#define check_pow_BookE      check_pow_nocheck
+
+__attribute__ (( unused ))
+static void init_proc_BookE (CPUPPCState *env)
+{
+    init_excp_BookE(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+}
+
+/* e200 core                                                                 */
+
+/* e300 core                                                                 */
+
+/* e500 core                                                                 */
+#define POWERPC_INSNS_e500   (POWERPC_INSNS_EMB |                             \
+                              PPC_MEM_EIEIO | PPC_MEM_TLBSYNC |               \
+                              PPC_CACHE_DCBA |                                \
+                              PPC_BOOKE | PPC_E500_VECTOR)
+#define POWERPC_MMU_e500     (POWERPC_MMU_SOFT_4xx)
+#define POWERPC_EXCP_e500    (POWERPC_EXCP_40x)
+#define POWERPC_INPUT_e500   (PPC_FLAGS_INPUT_BookE)
+#define POWERPC_BFDM_e500    (bfd_mach_ppc_403)
+#define POWERPC_FLAG_e500    (POWERPC_FLAG_SPE)
+#define check_pow_e500       check_pow_hid0
+
+__attribute__ (( unused ))
+static void init_proc_e500 (CPUPPCState *env)
+{
+    /* Time base */
+    gen_tbl(env);
+    gen_spr_BookE(env);
+    /* Memory management */
+    gen_spr_BookE_FSL(env);
+#if !defined(CONFIG_USER_ONLY)
+    env->nb_tlb = 64;
+    env->nb_ways = 1;
+    env->id_tlbs = 0;
+#endif
+    init_excp_BookE(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* XXX: TODO: allocate internal IRQ controller */
+}
+
+/* e600 core                                                                 */
+
+/* Non-embedded PowerPC                                                      */
+/* Base instructions set for all 6xx/7xx/74xx/970 PowerPC                    */
+#define POWERPC_INSNS_6xx    (PPC_INSNS_BASE | PPC_FLOAT | PPC_MEM_SYNC |     \
+                              PPC_MEM_EIEIO | PPC_MEM_TLBIE)
+/* Instructions common to all 6xx/7xx/74xx/970 PowerPC except 601 & 602      */
+#define POWERPC_INSNS_WORKS  (POWERPC_INSNS_6xx | PPC_FLOAT_FSQRT |           \
+                              PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE |            \
+                              PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX |             \
+                              PPC_MEM_TLBSYNC | PPC_CACHE_DCBZ | PPC_MFTB |   \
+                              PPC_SEGMENT)
+
+/* POWER : same as 601, without mfmsr, mfsr                                  */
+#if defined(TODO)
+#define POWERPC_INSNS_POWER  (XXX_TODO)
+/* POWER RSC (from RAD6000) */
+#define POWERPC_MSRM_POWER   (0x00000000FEF0ULL)
+#endif /* TODO */
+
+/* PowerPC 601                                                               */
+#define POWERPC_INSNS_601    (POWERPC_INSNS_6xx | PPC_CACHE_DCBZ |            \
+                              PPC_SEGMENT | PPC_EXTERN | PPC_POWER_BR)
+#define POWERPC_MSRM_601     (0x000000000000FD70ULL)
+#define POWERPC_MMU_601      (POWERPC_MMU_32B)
+//#define POWERPC_EXCP_601     (POWERPC_EXCP_601)
+#define POWERPC_INPUT_601    (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_601     (bfd_mach_ppc_601)
+#define POWERPC_FLAG_601     (POWERPC_FLAG_SE)
+#define check_pow_601        check_pow_none
+
+static void init_proc_601 (CPUPPCState *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 */
+    spr_register(env, SPR_601_HID15, "HID15",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Memory management */
+#if !defined(CONFIG_USER_ONLY)
+    env->nb_tlb = 64;
+    env->nb_ways = 2;
+    env->id_tlbs = 0;
+#endif
+    init_excp_601(env);
+    env->dcache_line_size = 64;
+    env->icache_line_size = 64;
+    /* XXX: TODO: allocate internal IRQ controller */
+}
+
+/* PowerPC 602                                                               */
+#define POWERPC_INSNS_602    (POWERPC_INSNS_6xx | PPC_MFTB |                  \
+                              PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE |            \
+                              PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX |             \
+                              PPC_6xx_TLB | PPC_MEM_TLBSYNC | PPC_CACHE_DCBZ |\
+                              PPC_SEGMENT | PPC_602_SPEC)
+#define POWERPC_MSRM_602     (0x000000000033FF73ULL)
+#define POWERPC_MMU_602      (POWERPC_MMU_SOFT_6xx)
+//#define POWERPC_EXCP_602     (POWERPC_EXCP_602)
+#define POWERPC_INPUT_602    (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_602     (bfd_mach_ppc_602)
+#define POWERPC_FLAG_602     (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
+                              POWERPC_FLAG_BE)
+#define check_pow_602        check_pow_hid0
+
+static void init_proc_602 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_602(env);
+    /* Time base */
+    gen_tbl(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);
+    /* Memory management */
+    gen_low_BATs(env);
+    gen_6xx_7xx_soft_tlb(env, 64, 2);
+    init_excp_602(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
+/* PowerPC 603                                                               */
+#define POWERPC_INSNS_603    (POWERPC_INSNS_WORKS | PPC_6xx_TLB | PPC_EXTERN)
+#define POWERPC_MSRM_603     (0x000000000007FF73ULL)
+#define POWERPC_MMU_603      (POWERPC_MMU_SOFT_6xx)
+//#define POWERPC_EXCP_603     (POWERPC_EXCP_603)
+#define POWERPC_INPUT_603    (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_603     (bfd_mach_ppc_603)
+#define POWERPC_FLAG_603     (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
+                              POWERPC_FLAG_BE)
+#define check_pow_603        check_pow_hid0
+
+static void init_proc_603 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_603(env);
+    /* Time base */
+    gen_tbl(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);
+    /* Memory management */
+    gen_low_BATs(env);
+    gen_6xx_7xx_soft_tlb(env, 64, 2);
+    init_excp_603(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
+/* PowerPC 603e                                                              */
+#define POWERPC_INSNS_603E   (POWERPC_INSNS_WORKS | PPC_6xx_TLB | PPC_EXTERN)
+#define POWERPC_MSRM_603E    (0x000000000007FF73ULL)
+#define POWERPC_MMU_603E     (POWERPC_MMU_SOFT_6xx)
+//#define POWERPC_EXCP_603E    (POWERPC_EXCP_603E)
+#define POWERPC_INPUT_603E   (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_603E    (bfd_mach_ppc_ec603e)
+#define POWERPC_FLAG_603E    (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
+                              POWERPC_FLAG_BE)
+#define check_pow_603E       check_pow_hid0
+
+static void init_proc_603E (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_603(env);
+    /* Time base */
+    gen_tbl(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_IABR, "IABR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Memory management */
+    gen_low_BATs(env);
+    gen_6xx_7xx_soft_tlb(env, 64, 2);
+    init_excp_603(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
+/* PowerPC G2                                                                */
+#define POWERPC_INSNS_G2     (POWERPC_INSNS_WORKS | PPC_6xx_TLB | PPC_EXTERN)
+#define POWERPC_MSRM_G2      (0x000000000006FFF2ULL)
+#define POWERPC_MMU_G2       (POWERPC_MMU_SOFT_6xx)
+//#define POWERPC_EXCP_G2      (POWERPC_EXCP_G2)
+#define POWERPC_INPUT_G2     (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_G2      (bfd_mach_ppc_ec603e)
+#define POWERPC_FLAG_G2      (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
+                              POWERPC_FLAG_BE)
+#define check_pow_G2         check_pow_hid0
+
+static void init_proc_G2 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_G2_755(env);
+    gen_spr_G2(env);
+    /* Time base */
+    gen_tbl(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);
+    /* Memory management */
+    gen_low_BATs(env);
+    gen_high_BATs(env);
+    gen_6xx_7xx_soft_tlb(env, 64, 2);
+    init_excp_G2(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
+/* PowerPC G2LE                                                              */
+#define POWERPC_INSNS_G2LE   (POWERPC_INSNS_WORKS | PPC_6xx_TLB | PPC_EXTERN)
+#define POWERPC_MSRM_G2LE    (0x000000000007FFF3ULL)
+#define POWERPC_MMU_G2LE     (POWERPC_MMU_SOFT_6xx)
+#define POWERPC_EXCP_G2LE    (POWERPC_EXCP_G2)
+#define POWERPC_INPUT_G2LE   (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_G2LE    (bfd_mach_ppc_ec603e)
+#define POWERPC_FLAG_G2LE    (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
+                              POWERPC_FLAG_BE)
+#define check_pow_G2LE       check_pow_hid0
+
+static void init_proc_G2LE (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_G2_755(env);
+    gen_spr_G2(env);
+    /* Time base */
+    gen_tbl(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);
+    /* Memory management */
+    gen_low_BATs(env);
+    gen_high_BATs(env);
+    gen_6xx_7xx_soft_tlb(env, 64, 2);
+    init_excp_G2(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
+/* PowerPC 604                                                               */
+#define POWERPC_INSNS_604    (POWERPC_INSNS_WORKS | PPC_EXTERN)
+#define POWERPC_MSRM_604     (0x000000000005FF77ULL)
+#define POWERPC_MMU_604      (POWERPC_MMU_32B)
+//#define POWERPC_EXCP_604     (POWERPC_EXCP_604)
+#define POWERPC_INPUT_604    (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_604     (bfd_mach_ppc_604)
+#define POWERPC_FLAG_604     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
+                              POWERPC_FLAG_PMM)
+#define check_pow_604        check_pow_nocheck
+
+static void init_proc_604 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_604(env);
+    /* Time base */
+    gen_tbl(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);
+    /* Memory management */
+    gen_low_BATs(env);
+    init_excp_604(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
+/* PowerPC 740/750 (aka G3)                                                  */
+#define POWERPC_INSNS_7x0    (POWERPC_INSNS_WORKS | PPC_EXTERN)
+#define POWERPC_MSRM_7x0     (0x000000000005FF77ULL)
+#define POWERPC_MMU_7x0      (POWERPC_MMU_32B)
+//#define POWERPC_EXCP_7x0     (POWERPC_EXCP_7x0)
+#define POWERPC_INPUT_7x0    (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_7x0     (bfd_mach_ppc_750)
+#define POWERPC_FLAG_7x0     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
+                              POWERPC_FLAG_PMM)
+#define check_pow_7x0        check_pow_hid0
+
+static void init_proc_7x0 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_7xx(env);
+    /* Time base */
+    gen_tbl(env);
+    /* Thermal management */
+    gen_spr_thrm(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);
+    /* Memory management */
+    gen_low_BATs(env);
+    init_excp_7x0(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
+/* PowerPC 750FX/GX                                                          */
+#define POWERPC_INSNS_750fx  (POWERPC_INSNS_WORKS | PPC_EXTERN)
+#define POWERPC_MSRM_750fx   (0x000000000005FF77ULL)
+#define POWERPC_MMU_750fx    (POWERPC_MMU_32B)
+#define POWERPC_EXCP_750fx   (POWERPC_EXCP_7x0)
+#define POWERPC_INPUT_750fx  (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_750fx   (bfd_mach_ppc_750)
+#define POWERPC_FLAG_750fx   (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
+                              POWERPC_FLAG_PMM)
+#define check_pow_750fx      check_pow_hid0
+
+static void init_proc_750fx (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_7xx(env);
+    /* Time base */
+    gen_tbl(env);
+    /* Thermal management */
+    gen_spr_thrm(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);
+    /* Memory management */
+    gen_low_BATs(env);
+    /* PowerPC 750fx & 750gx has 8 DBATs and 8 IBATs */
+    gen_high_BATs(env);
+    init_excp_750FX(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
+/* PowerPC 745/755                                                           */
+#define POWERPC_INSNS_7x5    (POWERPC_INSNS_WORKS | PPC_EXTERN | PPC_6xx_TLB)
+#define POWERPC_MSRM_7x5     (0x000000000005FF77ULL)
+#define POWERPC_MMU_7x5      (POWERPC_MMU_SOFT_6xx)
+//#define POWERPC_EXCP_7x5     (POWERPC_EXCP_7x5)
+#define POWERPC_INPUT_7x5    (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_7x5     (bfd_mach_ppc_750)
+#define POWERPC_FLAG_7x5     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
+                              POWERPC_FLAG_PMM)
+#define check_pow_7x5        check_pow_hid0
+
+static void init_proc_7x5 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_G2_755(env);
+    /* Time base */
+    gen_tbl(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_L2PMCR, "L2PMCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* 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_HID2, "HID2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Memory management */
+    gen_low_BATs(env);
+    gen_high_BATs(env);
+    gen_6xx_7xx_soft_tlb(env, 64, 2);
+    init_excp_7x5(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+#if !defined(CONFIG_USER_ONLY)
+    /* Hardware reset vector */
+    env->hreset_vector = 0xFFFFFFFCUL;
+#endif
+}
+
+/* PowerPC 7400 (aka G4)                                                     */
+#define POWERPC_INSNS_7400   (POWERPC_INSNS_WORKS | PPC_CACHE_DCBA |          \
+                              PPC_EXTERN | PPC_MEM_TLBIA |                    \
+                              PPC_ALTIVEC)
+#define POWERPC_MSRM_7400    (0x000000000205FF77ULL)
+#define POWERPC_MMU_7400     (POWERPC_MMU_32B)
+#define POWERPC_EXCP_7400    (POWERPC_EXCP_74xx)
+#define POWERPC_INPUT_7400   (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_7400    (bfd_mach_ppc_7400)
+#define POWERPC_FLAG_7400    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
+                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM)
+#define check_pow_7400       check_pow_hid0
+
+static void init_proc_7400 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_7xx(env);
+    /* Time base */
+    gen_tbl(env);
+    /* 74xx specific SPR */
+    gen_spr_74xx(env);
+    /* Thermal management */
+    gen_spr_thrm(env);
+    /* Memory management */
+    gen_low_BATs(env);
+    init_excp_7400(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
+/* PowerPC 7410 (aka G4)                                                     */
+#define POWERPC_INSNS_7410   (POWERPC_INSNS_WORKS | PPC_CACHE_DCBA |          \
+                              PPC_EXTERN | PPC_MEM_TLBIA |                    \
+                              PPC_ALTIVEC)
+#define POWERPC_MSRM_7410    (0x000000000205FF77ULL)
+#define POWERPC_MMU_7410     (POWERPC_MMU_32B)
+#define POWERPC_EXCP_7410    (POWERPC_EXCP_74xx)
+#define POWERPC_INPUT_7410   (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_7410    (bfd_mach_ppc_7400)
+#define POWERPC_FLAG_7410    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
+                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM)
+#define check_pow_7410       check_pow_hid0
+
+static void init_proc_7410 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_7xx(env);
+    /* Time base */
+    gen_tbl(env);
+    /* 74xx specific SPR */
+    gen_spr_74xx(env);
+    /* Thermal management */
+    gen_spr_thrm(env);
+    /* L2PMCR */
+    /* XXX : not implemented */
+    spr_register(env, SPR_L2PMCR, "L2PMCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* LDSTDB */
+    /* XXX : not implemented */
+    spr_register(env, SPR_LDSTDB, "LDSTDB",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Memory management */
+    gen_low_BATs(env);
+    init_excp_7400(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
+/* PowerPC 7440 (aka G4)                                                     */
+#define POWERPC_INSNS_7440   (POWERPC_INSNS_WORKS | PPC_CACHE_DCBA |          \
+                              PPC_EXTERN | PPC_74xx_TLB | PPC_MEM_TLBIA |     \
+                              PPC_ALTIVEC)
+#define POWERPC_MSRM_7440    (0x000000000205FF77ULL)
+#define POWERPC_MMU_7440     (POWERPC_MMU_SOFT_74xx)
+#define POWERPC_EXCP_7440    (POWERPC_EXCP_74xx)
+#define POWERPC_INPUT_7440   (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_7440    (bfd_mach_ppc_7400)
+#define POWERPC_FLAG_7440    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
+                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM)
+#define check_pow_7440       check_pow_hid0
+
+__attribute__ (( unused ))
+static void init_proc_7440 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_7xx(env);
+    /* Time base */
+    gen_tbl(env);
+    /* 74xx specific SPR */
+    gen_spr_74xx(env);
+    /* LDSTCR */
+    /* XXX : not implemented */
+    spr_register(env, SPR_LDSTCR, "LDSTCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* ICTRL */
+    /* XXX : not implemented */
+    spr_register(env, SPR_ICTRL, "ICTRL",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* MSSSR0 */
+    /* XXX : not implemented */
+    spr_register(env, SPR_MSSSR0, "MSSSR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* PMC */
+    /* XXX : not implemented */
+    spr_register(env, SPR_PMC5, "PMC5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_UPMC5, "UPMC5",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_PMC6, "PMC6",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_UPMC6, "UPMC6",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    /* Memory management */
+    gen_low_BATs(env);
+    gen_74xx_soft_tlb(env, 128, 2);
+    init_excp_7450(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
+/* PowerPC 7450 (aka G4)                                                     */
+#define POWERPC_INSNS_7450   (POWERPC_INSNS_WORKS | PPC_CACHE_DCBA |          \
+                              PPC_EXTERN | PPC_74xx_TLB | PPC_MEM_TLBIA |     \
+                              PPC_ALTIVEC)
+#define POWERPC_MSRM_7450    (0x000000000205FF77ULL)
+#define POWERPC_MMU_7450     (POWERPC_MMU_SOFT_74xx)
+#define POWERPC_EXCP_7450    (POWERPC_EXCP_74xx)
+#define POWERPC_INPUT_7450   (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_7450    (bfd_mach_ppc_7400)
+#define POWERPC_FLAG_7450    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
+                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM)
+#define check_pow_7450       check_pow_hid0
+
+__attribute__ (( unused ))
+static void init_proc_7450 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_7xx(env);
+    /* Time base */
+    gen_tbl(env);
+    /* 74xx specific SPR */
+    gen_spr_74xx(env);
+    /* Level 3 cache control */
+    gen_l3_ctrl(env);
+    /* LDSTCR */
+    /* XXX : not implemented */
+    spr_register(env, SPR_LDSTCR, "LDSTCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* ICTRL */
+    /* XXX : not implemented */
+    spr_register(env, SPR_ICTRL, "ICTRL",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* MSSSR0 */
+    /* XXX : not implemented */
+    spr_register(env, SPR_MSSSR0, "MSSSR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* PMC */
+    /* XXX : not implemented */
+    spr_register(env, SPR_PMC5, "PMC5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_UPMC5, "UPMC5",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_PMC6, "PMC6",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_UPMC6, "UPMC6",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    /* Memory management */
+    gen_low_BATs(env);
+    gen_74xx_soft_tlb(env, 128, 2);
+    init_excp_7450(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
+/* PowerPC 7445 (aka G4)                                                     */
+#define POWERPC_INSNS_7445   (POWERPC_INSNS_WORKS | PPC_CACHE_DCBA |          \
+                              PPC_EXTERN | PPC_74xx_TLB | PPC_MEM_TLBIA |     \
+                              PPC_ALTIVEC)
+#define POWERPC_MSRM_7445    (0x000000000205FF77ULL)
+#define POWERPC_MMU_7445     (POWERPC_MMU_SOFT_74xx)
+#define POWERPC_EXCP_7445    (POWERPC_EXCP_74xx)
+#define POWERPC_INPUT_7445   (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_7445    (bfd_mach_ppc_7400)
+#define POWERPC_FLAG_7445    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
+                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM)
+#define check_pow_7445       check_pow_hid0
+
+__attribute__ (( unused ))
+static void init_proc_7445 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_7xx(env);
+    /* Time base */
+    gen_tbl(env);
+    /* 74xx specific SPR */
+    gen_spr_74xx(env);
+    /* LDSTCR */
+    /* XXX : not implemented */
+    spr_register(env, SPR_LDSTCR, "LDSTCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* ICTRL */
+    /* XXX : not implemented */
+    spr_register(env, SPR_ICTRL, "ICTRL",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* MSSSR0 */
+    /* XXX : not implemented */
+    spr_register(env, SPR_MSSSR0, "MSSSR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* PMC */
+    /* XXX : not implemented */
+    spr_register(env, SPR_PMC5, "PMC5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_UPMC5, "UPMC5",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_PMC6, "PMC6",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_UPMC6, "UPMC6",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    /* SPRGs */
+    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);
+    /* Memory management */
+    gen_low_BATs(env);
+    gen_high_BATs(env);
+    gen_74xx_soft_tlb(env, 128, 2);
+    init_excp_7450(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
+/* PowerPC 7455 (aka G4)                                                     */
+#define POWERPC_INSNS_7455   (POWERPC_INSNS_WORKS | PPC_CACHE_DCBA |          \
+                              PPC_EXTERN | PPC_74xx_TLB | PPC_MEM_TLBIA |     \
+                              PPC_ALTIVEC)
+#define POWERPC_MSRM_7455    (0x000000000205FF77ULL)
+#define POWERPC_MMU_7455     (POWERPC_MMU_SOFT_74xx)
+#define POWERPC_EXCP_7455    (POWERPC_EXCP_74xx)
+#define POWERPC_INPUT_7455   (PPC_FLAGS_INPUT_6xx)
+#define POWERPC_BFDM_7455    (bfd_mach_ppc_7400)
+#define POWERPC_FLAG_7455    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
+                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM)
+#define check_pow_7455       check_pow_hid0
+
+__attribute__ (( unused ))
+static void init_proc_7455 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_7xx(env);
+    /* Time base */
+    gen_tbl(env);
+    /* 74xx specific SPR */
+    gen_spr_74xx(env);
+    /* Level 3 cache control */
+    gen_l3_ctrl(env);
+    /* LDSTCR */
+    /* XXX : not implemented */
+    spr_register(env, SPR_LDSTCR, "LDSTCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* ICTRL */
+    /* XXX : not implemented */
+    spr_register(env, SPR_ICTRL, "ICTRL",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* MSSSR0 */
+    /* XXX : not implemented */
+    spr_register(env, SPR_MSSSR0, "MSSSR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* PMC */
+    /* XXX : not implemented */
+    spr_register(env, SPR_PMC5, "PMC5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_UPMC5, "UPMC5",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_PMC6, "PMC6",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_UPMC6, "UPMC6",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    /* SPRGs */
+    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);
+    /* Memory management */
+    gen_low_BATs(env);
+    gen_high_BATs(env);
+    gen_74xx_soft_tlb(env, 128, 2);
+    init_excp_7450(env);
+    env->dcache_line_size = 32;
+    env->icache_line_size = 32;
+    /* Allocate hardware IRQ controller */
+    ppc6xx_irq_init(env);
+}
+
 #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+                      */
+#define POWERPC_INSNS_WORK64  (POWERPC_INSNS_6xx | PPC_FLOAT_FSQRT |          \
+                               PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE |           \
+                               PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX |            \
+                               PPC_MEM_TLBSYNC | PPC_CACHE_DCBZT | PPC_MFTB)
+/* PowerPC 970                                                               */
+#define POWERPC_INSNS_970    (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT |        \
+                              PPC_64B | PPC_ALTIVEC |                         \
+                              PPC_SEGMENT_64B | PPC_SLBI)
+#define POWERPC_MSRM_970     (0x900000000204FF36ULL)
+#define POWERPC_MMU_970      (POWERPC_MMU_64B)
+//#define POWERPC_EXCP_970     (POWERPC_EXCP_970)
+#define POWERPC_INPUT_970    (PPC_FLAGS_INPUT_970)
+#define POWERPC_BFDM_970     (bfd_mach_ppc64)
+#define POWERPC_FLAG_970     (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
+                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM)
+
+#if defined(CONFIG_USER_ONLY)
+#define POWERPC970_HID5_INIT 0x00000080
+#else
+#define POWERPC970_HID5_INIT 0x00000000
 #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;
+static int check_pow_970 (CPUPPCState *env)
+{
+    if (env->spr[SPR_HID0] & 0x00600000)
+        return 1;
 
+    return 0;
+}
+
+static void init_proc_970 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_7xx(env);
+    /* Time base */
+    gen_tbl(env);
+    /* Hardware implementation registers */
+    /* XXX : not implemented */
+    spr_register(env, SPR_HID0, "HID0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_clear,
+                 0x60000000);
+    /* 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);
+    /* XXX : not implemented */
+    spr_register(env, SPR_970_HID5, "HID5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 POWERPC970_HID5_INIT);
+    /* Memory management */
+    /* XXX: not correct */
+    gen_low_BATs(env);
+    /* XXX : not implemented */
+    spr_register(env, SPR_MMUCFG, "MMUCFG",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000); /* TOFIX */
+    /* XXX : not implemented */
+    spr_register(env, SPR_MMUCSR0, "MMUCSR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000); /* TOFIX */
+    spr_register(env, SPR_HIOR, "SPR_HIOR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0xFFF00000); /* XXX: This is a hack */
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_prefix = 0xFFF00000;
+#endif
+#if !defined(CONFIG_USER_ONLY)
+    env->slb_nr = 32;
+#endif
+    init_excp_970(env);
+    env->dcache_line_size = 128;
+    env->icache_line_size = 128;
+    /* Allocate hardware IRQ controller */
+    ppc970_irq_init(env);
+}
+
+/* PowerPC 970FX (aka G5)                                                    */
+#define POWERPC_INSNS_970FX  (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT |        \
+                              PPC_64B | PPC_ALTIVEC |                         \
+                              PPC_SEGMENT_64B | PPC_SLBI)
+#define POWERPC_MSRM_970FX   (0x800000000204FF36ULL)
+#define POWERPC_MMU_970FX    (POWERPC_MMU_64B)
+#define POWERPC_EXCP_970FX   (POWERPC_EXCP_970)
+#define POWERPC_INPUT_970FX  (PPC_FLAGS_INPUT_970)
+#define POWERPC_BFDM_970FX   (bfd_mach_ppc64)
+#define POWERPC_FLAG_970FX   (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
+                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM)
+
+static int check_pow_970FX (CPUPPCState *env)
+{
+    if (env->spr[SPR_HID0] & 0x00600000)
+        return 1;
+
+    return 0;
+}
+
+static void init_proc_970FX (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_7xx(env);
+    /* Time base */
+    gen_tbl(env);
+    /* Hardware implementation registers */
+    /* XXX : not implemented */
+    spr_register(env, SPR_HID0, "HID0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_clear,
+                 0x60000000);
+    /* 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);
+    /* XXX : not implemented */
+    spr_register(env, SPR_970_HID5, "HID5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 POWERPC970_HID5_INIT);
+    /* Memory management */
+    /* XXX: not correct */
+    gen_low_BATs(env);
+    /* XXX : not implemented */
+    spr_register(env, SPR_MMUCFG, "MMUCFG",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000); /* TOFIX */
+    /* XXX : not implemented */
+    spr_register(env, SPR_MMUCSR0, "MMUCSR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000); /* TOFIX */
+    spr_register(env, SPR_HIOR, "SPR_HIOR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0xFFF00000); /* XXX: This is a hack */
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_prefix = 0xFFF00000;
+#endif
+#if !defined(CONFIG_USER_ONLY)
+    env->slb_nr = 32;
+#endif
+    init_excp_970(env);
+    env->dcache_line_size = 128;
+    env->icache_line_size = 128;
+    /* Allocate hardware IRQ controller */
+    ppc970_irq_init(env);
+}
+
+/* PowerPC 970 GX                                                            */
+#define POWERPC_INSNS_970GX  (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT |        \
+                              PPC_64B | PPC_ALTIVEC |                         \
+                              PPC_SEGMENT_64B | PPC_SLBI)
+#define POWERPC_MSRM_970GX   (0x800000000204FF36ULL)
+#define POWERPC_MMU_970GX    (POWERPC_MMU_64B)
+#define POWERPC_EXCP_970GX   (POWERPC_EXCP_970)
+#define POWERPC_INPUT_970GX  (PPC_FLAGS_INPUT_970)
+#define POWERPC_BFDM_970GX   (bfd_mach_ppc64)
+#define POWERPC_FLAG_970GX   (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
+                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM)
+
+static int check_pow_970GX (CPUPPCState *env)
+{
+    if (env->spr[SPR_HID0] & 0x00600000)
+        return 1;
+
+    return 0;
+}
+
+static void init_proc_970GX (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_7xx(env);
+    /* Time base */
+    gen_tbl(env);
+    /* Hardware implementation registers */
+    /* XXX : not implemented */
+    spr_register(env, SPR_HID0, "HID0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_clear,
+                 0x60000000);
+    /* 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);
+    /* XXX : not implemented */
+    spr_register(env, SPR_970_HID5, "HID5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 POWERPC970_HID5_INIT);
+    /* Memory management */
+    /* XXX: not correct */
+    gen_low_BATs(env);
+    /* XXX : not implemented */
+    spr_register(env, SPR_MMUCFG, "MMUCFG",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000); /* TOFIX */
+    /* XXX : not implemented */
+    spr_register(env, SPR_MMUCSR0, "MMUCSR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000); /* TOFIX */
+    spr_register(env, SPR_HIOR, "SPR_HIOR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0xFFF00000); /* XXX: This is a hack */
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_prefix = 0xFFF00000;
+#endif
+#if !defined(CONFIG_USER_ONLY)
+    env->slb_nr = 32;
+#endif
+    init_excp_970(env);
+    env->dcache_line_size = 128;
+    env->icache_line_size = 128;
+    /* Allocate hardware IRQ controller */
+    ppc970_irq_init(env);
+}
+
+/* PowerPC 970 MP                                                            */
+#define POWERPC_INSNS_970MP  (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT |        \
+                              PPC_64B | PPC_ALTIVEC |                         \
+                              PPC_SEGMENT_64B | PPC_SLBI)
+#define POWERPC_MSRM_970MP   (0x900000000204FF36ULL)
+#define POWERPC_MMU_970MP    (POWERPC_MMU_64B)
+#define POWERPC_EXCP_970MP   (POWERPC_EXCP_970)
+#define POWERPC_INPUT_970MP  (PPC_FLAGS_INPUT_970)
+#define POWERPC_BFDM_970MP   (bfd_mach_ppc64)
+#define POWERPC_FLAG_970MP   (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
+                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM)
+
+static int check_pow_970MP (CPUPPCState *env)
+{
+    if (env->spr[SPR_HID0] & 0x01C00000)
+        return 1;
+
+    return 0;
+}
+
+static void init_proc_970MP (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_7xx(env);
+    /* Time base */
+    gen_tbl(env);
+    /* Hardware implementation registers */
+    /* XXX : not implemented */
+    spr_register(env, SPR_HID0, "HID0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_clear,
+                 0x60000000);
+    /* 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);
+    /* XXX : not implemented */
+    spr_register(env, SPR_970_HID5, "HID5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 POWERPC970_HID5_INIT);
+    /* Memory management */
+    /* XXX: not correct */
+    gen_low_BATs(env);
+    /* XXX : not implemented */
+    spr_register(env, SPR_MMUCFG, "MMUCFG",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000); /* TOFIX */
+    /* XXX : not implemented */
+    spr_register(env, SPR_MMUCSR0, "MMUCSR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000); /* TOFIX */
+    spr_register(env, SPR_HIOR, "SPR_HIOR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0xFFF00000); /* XXX: This is a hack */
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_prefix = 0xFFF00000;
+#endif
+#if !defined(CONFIG_USER_ONLY)
+    env->slb_nr = 32;
+#endif
+    init_excp_970(env);
+    env->dcache_line_size = 128;
+    env->icache_line_size = 128;
+    /* Allocate hardware IRQ controller */
+    ppc970_irq_init(env);
+}
+
+/* PowerPC 620                                                               */
+#define POWERPC_INSNS_620    (POWERPC_INSNS_WORKS | PPC_FLOAT_FSQRT |         \
+                              PPC_64B | PPC_SLBI)
+#define POWERPC_MSRM_620     (0x800000000005FF73ULL)
+#define POWERPC_MMU_620      (POWERPC_MMU_64B)
+#define POWERPC_EXCP_620     (POWERPC_EXCP_970)
+#define POWERPC_INPUT_620    (PPC_FLAGS_INPUT_970)
+#define POWERPC_BFDM_620     (bfd_mach_ppc64)
+#define POWERPC_FLAG_620     (POWERPC_FLAG_SE | POWERPC_FLAG_BE)
+#define check_pow_620        check_pow_nocheck /* Check this */
+
+__attribute__ (( unused ))
+static void init_proc_620 (CPUPPCState *env)
+{
+    gen_spr_ne_601(env);
+    gen_spr_620(env);
+    /* Time base */
+    gen_tbl(env);
+    /* Hardware implementation registers */
+    /* XXX : not implemented */
+    spr_register(env, SPR_HID0, "HID0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Memory management */
+    gen_low_BATs(env);
+    gen_high_BATs(env);
+    init_excp_620(env);
+    env->dcache_line_size = 64;
+    env->icache_line_size = 64;
+    /* XXX: TODO: initialize internal interrupt controller */
+}
+#endif /* defined (TARGET_PPC64) */
+
+/* Default 32 bits PowerPC target will be 604 */
+#define CPU_POWERPC_PPC32     CPU_POWERPC_604
+#define POWERPC_INSNS_PPC32   POWERPC_INSNS_604
+#define POWERPC_MSRM_PPC32    POWERPC_MSRM_604
+#define POWERPC_MMU_PPC32     POWERPC_MMU_604
+#define POWERPC_EXCP_PPC32    POWERPC_EXCP_604
+#define POWERPC_INPUT_PPC32   POWERPC_INPUT_604
+#define POWERPC_BFDM_PPC32    POWERPC_BFDM_604
+#define POWERPC_FLAG_PPC32    POWERPC_FLAG_604
+#define check_pow_PPC32       check_pow_604
+#define init_proc_PPC32       init_proc_604
+
+/* Default 64 bits PowerPC target will be 970 FX */
+#define CPU_POWERPC_PPC64     CPU_POWERPC_970FX
+#define POWERPC_INSNS_PPC64   POWERPC_INSNS_970FX
+#define POWERPC_MSRM_PPC64    POWERPC_MSRM_970FX
+#define POWERPC_MMU_PPC64     POWERPC_MMU_970FX
+#define POWERPC_EXCP_PPC64    POWERPC_EXCP_970FX
+#define POWERPC_INPUT_PPC64   POWERPC_INPUT_970FX
+#define POWERPC_BFDM_PPC64    POWERPC_BFDM_970FX
+#define POWERPC_FLAG_PPC64    POWERPC_FLAG_970FX
+#define check_pow_PPC64       check_pow_970FX
+#define init_proc_PPC64       init_proc_970FX
+
+/* Default PowerPC target will be PowerPC 32 */
+#if defined (TARGET_PPC64) && 0 // XXX: TODO
+#define CPU_POWERPC_DEFAULT   CPU_POWERPC_PPC64
+#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC64
+#define POWERPC_MSRM_DEFAULT  POWERPC_MSRM_PPC64
+#define POWERPC_MMU_DEFAULT   POWERPC_MMU_PPC64
+#define POWERPC_EXCP_DEFAULT  POWERPC_EXCP_PPC64
+#define POWERPC_INPUT_DEFAULT POWERPC_INPUT_PPC64
+#define POWERPC_BFDM_DEFAULT  POWERPC_BFDM_PPC64
+#define POWERPC_FLAG_DEFAULT  POWERPC_FLAG_PPC64
+#define check_pow_DEFAULT     check_pow_PPC64
+#define init_proc_DEFAULT     init_proc_PPC64
+#else
+#define CPU_POWERPC_DEFAULT   CPU_POWERPC_PPC32
+#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC32
+#define POWERPC_MSRM_DEFAULT  POWERPC_MSRM_PPC32
+#define POWERPC_MMU_DEFAULT   POWERPC_MMU_PPC32
+#define POWERPC_EXCP_DEFAULT  POWERPC_EXCP_PPC32
+#define POWERPC_INPUT_DEFAULT POWERPC_INPUT_PPC32
+#define POWERPC_BFDM_DEFAULT  POWERPC_BFDM_PPC32
+#define POWERPC_FLAG_DEFAULT  POWERPC_FLAG_PPC32
+#define check_pow_DEFAULT     check_pow_PPC32
+#define init_proc_DEFAULT     init_proc_PPC32
+#endif
+
+/*****************************************************************************/
+/* PVR definitions for most known PowerPC                                    */
+enum {
+    /* PowerPC 401 family */
+    /* Generic PowerPC 401 */
+#define CPU_POWERPC_401       CPU_POWERPC_401G2
+    /* PowerPC 401 cores */
+    CPU_POWERPC_401A1       = 0x00210000,
+    CPU_POWERPC_401B2       = 0x00220000,
+#if 0
+    CPU_POWERPC_401B3       = xxx,
+#endif
+    CPU_POWERPC_401C2       = 0x00230000,
+    CPU_POWERPC_401D2       = 0x00240000,
+    CPU_POWERPC_401E2       = 0x00250000,
+    CPU_POWERPC_401F2       = 0x00260000,
+    CPU_POWERPC_401G2       = 0x00270000,
+    /* PowerPC 401 microcontrolers */
+#if 0
+    CPU_POWERPC_401GF       = xxx,
+#endif
+#define CPU_POWERPC_IOP480    CPU_POWERPC_401B2
+    /* IBM Processor for Network Resources */
+    CPU_POWERPC_COBRA       = 0x10100000, /* XXX: 405 ? */
+#if 0
+    CPU_POWERPC_XIPCHIP     = xxx,
+#endif
+    /* PowerPC 403 family */
+    /* Generic PowerPC 403 */
+#define CPU_POWERPC_403       CPU_POWERPC_403GC
+    /* PowerPC 403 microcontrollers */
+    CPU_POWERPC_403GA       = 0x00200011,
+    CPU_POWERPC_403GB       = 0x00200100,
+    CPU_POWERPC_403GC       = 0x00200200,
+    CPU_POWERPC_403GCX      = 0x00201400,
+#if 0
+    CPU_POWERPC_403GP       = xxx,
+#endif
+    /* PowerPC 405 family */
+    /* Generic PowerPC 405 */
+#define CPU_POWERPC_405       CPU_POWERPC_405D4
+    /* PowerPC 405 cores */
+#if 0
+    CPU_POWERPC_405A3       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405A4       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405B3       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405B4       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405C3       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405C4       = xxx,
+#endif
+    CPU_POWERPC_405D2       = 0x20010000,
+#if 0
+    CPU_POWERPC_405D3       = xxx,
+#endif
+    CPU_POWERPC_405D4       = 0x41810000,
+#if 0
+    CPU_POWERPC_405D5       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405E4       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405F4       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405F5       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405F6       = xxx,
+#endif
+    /* PowerPC 405 microcontrolers */
+    /* XXX: missing 0x200108a0 */
+#define CPU_POWERPC_405CR     CPU_POWERPC_405CRc
+    CPU_POWERPC_405CRa      = 0x40110041,
+    CPU_POWERPC_405CRb      = 0x401100C5,
+    CPU_POWERPC_405CRc      = 0x40110145,
+    CPU_POWERPC_405EP       = 0x51210950,
+#if 0
+    CPU_POWERPC_405EXr      = xxx,
+#endif
+    CPU_POWERPC_405EZ       = 0x41511460, /* 0x51210950 ? */
+#if 0
+    CPU_POWERPC_405FX       = xxx,
+#endif
+#define CPU_POWERPC_405GP     CPU_POWERPC_405GPd
+    CPU_POWERPC_405GPa      = 0x40110000,
+    CPU_POWERPC_405GPb      = 0x40110040,
+    CPU_POWERPC_405GPc      = 0x40110082,
+    CPU_POWERPC_405GPd      = 0x401100C4,
+#define CPU_POWERPC_405GPe    CPU_POWERPC_405CRc
+    CPU_POWERPC_405GPR      = 0x50910951,
+#if 0
+    CPU_POWERPC_405H        = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405L        = xxx,
+#endif
+    CPU_POWERPC_405LP       = 0x41F10000,
+#if 0
+    CPU_POWERPC_405PM       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405PS       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405S        = xxx,
+#endif
+    /* IBM network processors */
+    CPU_POWERPC_NPE405H     = 0x414100C0,
+    CPU_POWERPC_NPE405H2    = 0x41410140,
+    CPU_POWERPC_NPE405L     = 0x416100C0,
+    CPU_POWERPC_NPE4GS3     = 0x40B10000,
+#if 0
+    CPU_POWERPC_NPCxx1      = xxx,
+#endif
+#if 0
+    CPU_POWERPC_NPR161      = xxx,
+#endif
+#if 0
+    CPU_POWERPC_LC77700     = xxx,
+#endif
+    /* IBM STBxxx (PowerPC 401/403/405 core based microcontrollers) */
+#if 0
+    CPU_POWERPC_STB01000    = xxx,
+#endif
+#if 0
+    CPU_POWERPC_STB01010    = xxx,
+#endif
+#if 0
+    CPU_POWERPC_STB0210     = xxx, /* 401B3 */
+#endif
+    CPU_POWERPC_STB03       = 0x40310000, /* 0x40130000 ? */
+#if 0
+    CPU_POWERPC_STB043      = xxx,
+#endif
+#if 0
+    CPU_POWERPC_STB045      = xxx,
+#endif
+    CPU_POWERPC_STB04       = 0x41810000,
+    CPU_POWERPC_STB25       = 0x51510950,
+#if 0
+    CPU_POWERPC_STB130      = xxx,
+#endif
+    /* Xilinx cores */
+    CPU_POWERPC_X2VP4       = 0x20010820,
+#define CPU_POWERPC_X2VP7     CPU_POWERPC_X2VP4
+    CPU_POWERPC_X2VP20      = 0x20010860,
+#define CPU_POWERPC_X2VP50    CPU_POWERPC_X2VP20
+#if 0
+    CPU_POWERPC_ZL10310     = xxx,
+#endif
+#if 0
+    CPU_POWERPC_ZL10311     = xxx,
+#endif
+#if 0
+    CPU_POWERPC_ZL10320     = xxx,
+#endif
+#if 0
+    CPU_POWERPC_ZL10321     = xxx,
+#endif
+    /* PowerPC 440 family */
+    /* Generic PowerPC 440 */
+#define CPU_POWERPC_440       CPU_POWERPC_440GXf
+    /* PowerPC 440 cores */
+#if 0
+    CPU_POWERPC_440A4       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_440A5       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_440B4       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_440F5       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_440G5       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_440H4       = xxx,
+#endif
+#if 0
+    CPU_POWERPC_440H6       = xxx,
+#endif
+    /* PowerPC 440 microcontrolers */
+#define CPU_POWERPC_440EP     CPU_POWERPC_440EPb
+    CPU_POWERPC_440EPa      = 0x42221850,
+    CPU_POWERPC_440EPb      = 0x422218D3,
+#define CPU_POWERPC_440GP     CPU_POWERPC_440GPc
+    CPU_POWERPC_440GPb      = 0x40120440,
+    CPU_POWERPC_440GPc      = 0x40120481,
+#define CPU_POWERPC_440GR     CPU_POWERPC_440GRa
+#define CPU_POWERPC_440GRa    CPU_POWERPC_440EPb
+    CPU_POWERPC_440GRX      = 0x200008D0,
+#define CPU_POWERPC_440EPX    CPU_POWERPC_440GRX
+#define CPU_POWERPC_440GX     CPU_POWERPC_440GXf
+    CPU_POWERPC_440GXa      = 0x51B21850,
+    CPU_POWERPC_440GXb      = 0x51B21851,
+    CPU_POWERPC_440GXc      = 0x51B21892,
+    CPU_POWERPC_440GXf      = 0x51B21894,
+#if 0
+    CPU_POWERPC_440S        = xxx,
+#endif
+    CPU_POWERPC_440SP       = 0x53221850,
+    CPU_POWERPC_440SP2      = 0x53221891,
+    CPU_POWERPC_440SPE      = 0x53421890,
+    /* PowerPC 460 family */
+#if 0
+    /* Generic PowerPC 464 */
+#define CPU_POWERPC_464       CPU_POWERPC_464H90
+#endif
+    /* PowerPC 464 microcontrolers */
+#if 0
+    CPU_POWERPC_464H90      = xxx,
+#endif
+#if 0
+    CPU_POWERPC_464H90FP    = xxx,
+#endif
+    /* Freescale embedded PowerPC cores */
+    /* e200 family */
+#define CPU_POWERPC_e200      CPU_POWERPC_e200z6
+#if 0
+    CPU_POWERPC_e200z0      = xxx,
+#endif
+#if 0
+    CPU_POWERPC_e200z3      = xxx,
+#endif
+    CPU_POWERPC_e200z5      = 0x81000000,
+    CPU_POWERPC_e200z6      = 0x81120000,
+    /* e300 family */
+#define CPU_POWERPC_e300      CPU_POWERPC_e300c3
+    CPU_POWERPC_e300c1      = 0x00830000,
+    CPU_POWERPC_e300c2      = 0x00840000,
+    CPU_POWERPC_e300c3      = 0x00850000,
+    /* e500 family */
+#define CPU_POWERPC_e500      CPU_POWERPC_e500_v22
+    CPU_POWERPC_e500_v11    = 0x80200010,
+    CPU_POWERPC_e500_v12    = 0x80200020,
+    CPU_POWERPC_e500_v21    = 0x80210010,
+    CPU_POWERPC_e500_v22    = 0x80210020,
+#if 0
+    CPU_POWERPC_e500mc      = xxx,
+#endif
+    /* e600 family */
+    CPU_POWERPC_e600        = 0x80040010,
+    /* PowerPC MPC 5xx cores */
+    CPU_POWERPC_5xx         = 0x00020020,
+    /* PowerPC MPC 8xx cores (aka PowerQUICC) */
+    CPU_POWERPC_8xx         = 0x00500000,
+    /* PowerPC MPC 8xxx cores (aka PowerQUICC-II) */
+    CPU_POWERPC_82xx_HIP3   = 0x00810101,
+    CPU_POWERPC_82xx_HIP4   = 0x80811014,
+    CPU_POWERPC_827x        = 0x80822013,
+    /* PowerPC 6xx cores */
+    CPU_POWERPC_601         = 0x00010001,
+    CPU_POWERPC_601a        = 0x00010002,
+    CPU_POWERPC_602         = 0x00050100,
+    CPU_POWERPC_603         = 0x00030100,
+#define CPU_POWERPC_603E      CPU_POWERPC_603E_v41
+    CPU_POWERPC_603E_v11    = 0x00060101,
+    CPU_POWERPC_603E_v12    = 0x00060102,
+    CPU_POWERPC_603E_v13    = 0x00060103,
+    CPU_POWERPC_603E_v14    = 0x00060104,
+    CPU_POWERPC_603E_v22    = 0x00060202,
+    CPU_POWERPC_603E_v3     = 0x00060300,
+    CPU_POWERPC_603E_v4     = 0x00060400,
+    CPU_POWERPC_603E_v41    = 0x00060401,
+    CPU_POWERPC_603E7t      = 0x00071201,
+    CPU_POWERPC_603E7v      = 0x00070100,
+    CPU_POWERPC_603E7v1     = 0x00070101,
+    CPU_POWERPC_603E7v2     = 0x00070201,
+    CPU_POWERPC_603E7       = 0x00070200,
+    CPU_POWERPC_603P        = 0x00070000,
+#define CPU_POWERPC_603R      CPU_POWERPC_603E7t
+    CPU_POWERPC_G2          = 0x00810011,
+#if 0 // Linux pretends the MSB is zero...
+    CPU_POWERPC_G2H4        = 0x80811010,
+    CPU_POWERPC_G2gp        = 0x80821010,
+    CPU_POWERPC_G2ls        = 0x90810010,
+    CPU_POWERPC_G2LE        = 0x80820010,
+    CPU_POWERPC_G2LEgp      = 0x80822010,
+    CPU_POWERPC_G2LEls      = 0xA0822010,
+#else
+    CPU_POWERPC_G2H4        = 0x00811010,
+    CPU_POWERPC_G2gp        = 0x00821010,
+    CPU_POWERPC_G2ls        = 0x10810010,
+    CPU_POWERPC_G2LE        = 0x00820010,
+    CPU_POWERPC_G2LEgp      = 0x00822010,
+    CPU_POWERPC_G2LEls      = 0x20822010,
+#endif
+    CPU_POWERPC_604         = 0x00040103,
+#define CPU_POWERPC_604E      CPU_POWERPC_604E_v24
+    CPU_POWERPC_604E_v10    = 0x00090100, /* Also 2110 & 2120 */
+    CPU_POWERPC_604E_v22    = 0x00090202,
+    CPU_POWERPC_604E_v24    = 0x00090204,
+    CPU_POWERPC_604R        = 0x000a0101, /* Also 0x00093102 */
+#if 0
+    CPU_POWERPC_604EV       = xxx,
+#endif
+    /* PowerPC 740/750 cores (aka G3) */
+    /* XXX: missing 0x00084202 */
+#define CPU_POWERPC_7x0       CPU_POWERPC_7x0_v31
+    CPU_POWERPC_7x0_v20     = 0x00080200,
+    CPU_POWERPC_7x0_v21     = 0x00080201,
+    CPU_POWERPC_7x0_v22     = 0x00080202,
+    CPU_POWERPC_7x0_v30     = 0x00080300,
+    CPU_POWERPC_7x0_v31     = 0x00080301,
+    CPU_POWERPC_740E        = 0x00080100,
+    CPU_POWERPC_7x0P        = 0x10080000,
+    /* XXX: missing 0x00087010 (CL ?) */
+    CPU_POWERPC_750CL       = 0x00087200,
+#define CPU_POWERPC_750CX     CPU_POWERPC_750CX_v22
+    CPU_POWERPC_750CX_v21   = 0x00082201,
+    CPU_POWERPC_750CX_v22   = 0x00082202,
+#define CPU_POWERPC_750CXE    CPU_POWERPC_750CXE_v31b
+    CPU_POWERPC_750CXE_v21  = 0x00082211,
+    CPU_POWERPC_750CXE_v22  = 0x00082212,
+    CPU_POWERPC_750CXE_v23  = 0x00082213,
+    CPU_POWERPC_750CXE_v24  = 0x00082214,
+    CPU_POWERPC_750CXE_v24b = 0x00083214,
+    CPU_POWERPC_750CXE_v31  = 0x00083211,
+    CPU_POWERPC_750CXE_v31b = 0x00083311,
+    CPU_POWERPC_750CXR      = 0x00083410,
+    CPU_POWERPC_750E        = 0x00080200,
+    CPU_POWERPC_750FL       = 0x700A0203,
+#define CPU_POWERPC_750FX     CPU_POWERPC_750FX_v23
+    CPU_POWERPC_750FX_v10   = 0x70000100,
+    CPU_POWERPC_750FX_v20   = 0x70000200,
+    CPU_POWERPC_750FX_v21   = 0x70000201,
+    CPU_POWERPC_750FX_v22   = 0x70000202,
+    CPU_POWERPC_750FX_v23   = 0x70000203,
+    CPU_POWERPC_750GL       = 0x70020102,
+#define CPU_POWERPC_750GX     CPU_POWERPC_750GX_v12
+    CPU_POWERPC_750GX_v10   = 0x70020100,
+    CPU_POWERPC_750GX_v11   = 0x70020101,
+    CPU_POWERPC_750GX_v12   = 0x70020102,
+#define CPU_POWERPC_750L      CPU_POWERPC_750L_v32 /* Aka LoneStar */
+    CPU_POWERPC_750L_v22    = 0x00088202,
+    CPU_POWERPC_750L_v30    = 0x00088300,
+    CPU_POWERPC_750L_v32    = 0x00088302,
+    /* PowerPC 745/755 cores */
+#define CPU_POWERPC_7x5       CPU_POWERPC_7x5_v28
+    CPU_POWERPC_7x5_v10     = 0x00083100,
+    CPU_POWERPC_7x5_v11     = 0x00083101,
+    CPU_POWERPC_7x5_v20     = 0x00083200,
+    CPU_POWERPC_7x5_v21     = 0x00083201,
+    CPU_POWERPC_7x5_v22     = 0x00083202, /* aka D */
+    CPU_POWERPC_7x5_v23     = 0x00083203, /* aka E */
+    CPU_POWERPC_7x5_v24     = 0x00083204,
+    CPU_POWERPC_7x5_v25     = 0x00083205,
+    CPU_POWERPC_7x5_v26     = 0x00083206,
+    CPU_POWERPC_7x5_v27     = 0x00083207,
+    CPU_POWERPC_7x5_v28     = 0x00083208,
+#if 0
+    CPU_POWERPC_7x5P        = xxx,
+#endif
+    /* PowerPC 74xx cores (aka G4) */
+    /* XXX: missing 0x000C1101 */
+#define CPU_POWERPC_7400      CPU_POWERPC_7400_v29
+    CPU_POWERPC_7400_v10    = 0x000C0100,
+    CPU_POWERPC_7400_v11    = 0x000C0101,
+    CPU_POWERPC_7400_v20    = 0x000C0200,
+    CPU_POWERPC_7400_v22    = 0x000C0202,
+    CPU_POWERPC_7400_v26    = 0x000C0206,
+    CPU_POWERPC_7400_v27    = 0x000C0207,
+    CPU_POWERPC_7400_v28    = 0x000C0208,
+    CPU_POWERPC_7400_v29    = 0x000C0209,
+#define CPU_POWERPC_7410      CPU_POWERPC_7410_v14
+    CPU_POWERPC_7410_v10    = 0x800C1100,
+    CPU_POWERPC_7410_v11    = 0x800C1101,
+    CPU_POWERPC_7410_v12    = 0x800C1102, /* aka C */
+    CPU_POWERPC_7410_v13    = 0x800C1103, /* aka D */
+    CPU_POWERPC_7410_v14    = 0x800C1104, /* aka E */
+#define CPU_POWERPC_7448      CPU_POWERPC_7448_v21
+    CPU_POWERPC_7448_v10    = 0x80040100,
+    CPU_POWERPC_7448_v11    = 0x80040101,
+    CPU_POWERPC_7448_v20    = 0x80040200,
+    CPU_POWERPC_7448_v21    = 0x80040201,
+#define CPU_POWERPC_7450      CPU_POWERPC_7450_v21
+    CPU_POWERPC_7450_v10    = 0x80000100,
+    CPU_POWERPC_7450_v11    = 0x80000101,
+    CPU_POWERPC_7450_v12    = 0x80000102,
+    CPU_POWERPC_7450_v20    = 0x80000200, /* aka D: 2.04 */
+    CPU_POWERPC_7450_v21    = 0x80000201, /* aka E */
+    CPU_POWERPC_74x1        = 0x80000203,
+    CPU_POWERPC_74x1G       = 0x80000210, /* aka G: 2.3 */
+    /* XXX: missing 0x80010200 */
+#define CPU_POWERPC_74x5      CPU_POWERPC_74x5_v32
+    CPU_POWERPC_74x5_v10    = 0x80010100,
+    CPU_POWERPC_74x5_v21    = 0x80010201, /* aka C: 2.1 */
+    CPU_POWERPC_74x5_v32    = 0x80010302,
+    CPU_POWERPC_74x5_v33    = 0x80010303, /* aka F: 3.3 */
+    CPU_POWERPC_74x5_v34    = 0x80010304, /* aka G: 3.4 */
+#define CPU_POWERPC_74x7      CPU_POWERPC_74x7_v12
+    CPU_POWERPC_74x7_v10    = 0x80020100, /* aka A: 1.0 */
+    CPU_POWERPC_74x7_v11    = 0x80030101, /* aka B: 1.1 */
+    CPU_POWERPC_74x7_v12    = 0x80020102, /* aka C: 1.2 */
+    /* 64 bits PowerPC */
+#if defined(TARGET_PPC64)
+    CPU_POWERPC_620         = 0x00140000,
+    CPU_POWERPC_630         = 0x00400000,
+    CPU_POWERPC_631         = 0x00410104,
+    CPU_POWERPC_POWER4      = 0x00350000,
+    CPU_POWERPC_POWER4P     = 0x00380000,
+    CPU_POWERPC_POWER5      = 0x003A0203,
+#define CPU_POWERPC_POWER5GR  CPU_POWERPC_POWER5
+    CPU_POWERPC_POWER5P     = 0x003B0000,
+#define CPU_POWERPC_POWER5GS  CPU_POWERPC_POWER5P
+    CPU_POWERPC_POWER6      = 0x003E0000,
+    CPU_POWERPC_POWER6_5    = 0x0F000001, /* POWER6 running POWER5 mode */
+    CPU_POWERPC_POWER6A     = 0x0F000002,
+    CPU_POWERPC_970         = 0x00390202,
+#define CPU_POWERPC_970FX     CPU_POWERPC_970FX_v31
+    CPU_POWERPC_970FX_v10   = 0x00391100,
+    CPU_POWERPC_970FX_v20   = 0x003C0200,
+    CPU_POWERPC_970FX_v21   = 0x003C0201,
+    CPU_POWERPC_970FX_v30   = 0x003C0300,
+    CPU_POWERPC_970FX_v31   = 0x003C0301,
+    CPU_POWERPC_970GX       = 0x00450000,
+#define CPU_POWERPC_970MP     CPU_POWERPC_970MP_v11
+    CPU_POWERPC_970MP_v10   = 0x00440100,
+    CPU_POWERPC_970MP_v11   = 0x00440101,
+#define CPU_POWERPC_CELL      CPU_POWERPC_CELL_v32
+    CPU_POWERPC_CELL_v10    = 0x00700100,
+    CPU_POWERPC_CELL_v20    = 0x00700400,
+    CPU_POWERPC_CELL_v30    = 0x00700500,
+    CPU_POWERPC_CELL_v31    = 0x00700501,
+#define CPU_POWERPC_CELL_v32  CPU_POWERPC_CELL_v31
+    CPU_POWERPC_RS64        = 0x00330000,
+    CPU_POWERPC_RS64II      = 0x00340000,
+    CPU_POWERPC_RS64III     = 0x00360000,
+    CPU_POWERPC_RS64IV      = 0x00370000,
+#endif /* defined(TARGET_PPC64) */
+    /* Original POWER */
+    /* XXX: should be POWER (RIOS), RSC3308, RSC4608,
+     * POWER2 (RIOS2) & RSC2 (P2SC) here
+     */
+#if 0
+    CPU_POWER           = xxx, /* 0x20000 ? 0x30000 for RSC ? */
+#endif
+#if 0
+    CPU_POWER2          = xxx, /* 0x40000 ? */
+#endif
+    /* PA Semi core */
+    CPU_POWERPC_PA6T        = 0x00900000,
+};
+
+/* System version register (used on MPC 8xxx)                                */
+enum {
+    PPC_SVR_8540      = 0x80300000,
+    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,
+};
+
+/*****************************************************************************/
+/* PowerPC CPU definitions                                                   */
+#define POWERPC_DEF(_name, _pvr, _pvr_mask, _type)                            \
+    {                                                                         \
+        .name        = _name,                                                 \
+        .pvr         = _pvr,                                                  \
+        .pvr_mask    = _pvr_mask,                                             \
+        .insns_flags = glue(POWERPC_INSNS_,_type),                            \
+        .msr_mask    = glue(POWERPC_MSRM_,_type),                             \
+        .mmu_model   = glue(POWERPC_MMU_,_type),                              \
+        .excp_model  = glue(POWERPC_EXCP_,_type),                             \
+        .bus_model   = glue(POWERPC_INPUT_,_type),                            \
+        .bfd_mach    = glue(POWERPC_BFDM_,_type),                             \
+        .flags       = glue(POWERPC_FLAG_,_type),                             \
+        .init_proc   = &glue(init_proc_,_type),                               \
+        .check_pow   = &glue(check_pow_,_type),                               \
+    }
+
+static ppc_def_t ppc_defs[] = {
+    /* Embedded PowerPC                                                      */
+    /* PowerPC 401 family                                                    */
+    /* Generic PowerPC 401 */
+    POWERPC_DEF("401",         CPU_POWERPC_401,         0xFFFF0000, 401),
+    /* PowerPC 401 cores                                                     */
+    /* PowerPC 401A1 */
+    POWERPC_DEF("401A1",       CPU_POWERPC_401A1,       0xFFFFFFFF, 401),
+    /* PowerPC 401B2                                                         */
+    POWERPC_DEF("401B2",       CPU_POWERPC_401B2,       0xFFFFFFFF, 401x2),
 #if defined (TODO)
-    case CPU_PPC_CELL10:  /* Cell family                   */
-    case CPU_PPC_CELL20:
-    case CPU_PPC_CELL30:
-    case CPU_PPC_CELL31:
+    /* PowerPC 401B3                                                         */
+    POWERPC_DEF("401B3",       CPU_POWERPC_401B3,       0xFFFFFFFF, 401x3),
 #endif
-        break;
+    /* PowerPC 401C2                                                         */
+    POWERPC_DEF("401C2",       CPU_POWERPC_401C2,       0xFFFFFFFF, 401x2),
+    /* PowerPC 401D2                                                         */
+    POWERPC_DEF("401D2",       CPU_POWERPC_401D2,       0xFFFFFFFF, 401x2),
+    /* PowerPC 401E2                                                         */
+    POWERPC_DEF("401E2",       CPU_POWERPC_401E2,       0xFFFFFFFF, 401x2),
+    /* PowerPC 401F2                                                         */
+    POWERPC_DEF("401F2",       CPU_POWERPC_401F2,       0xFFFFFFFF, 401x2),
+    /* PowerPC 401G2                                                         */
+    /* XXX: to be checked */
+    POWERPC_DEF("401G2",       CPU_POWERPC_401G2,       0xFFFFFFFF, 401x2),
+    /* PowerPC 401 microcontrolers                                           */
+#if defined (TODO)
+    /* PowerPC 401GF                                                         */
+    POWERPC_DEF("401GF",       CPU_POWERPC_401GF,       0xFFFFFFFF, 401),
+#endif
+    /* IOP480 (401 microcontroler)                                           */
+    POWERPC_DEF("IOP480",      CPU_POWERPC_IOP480,      0xFFFFFFFF, IOP480),
+    /* IBM Processor for Network Resources                                   */
+    POWERPC_DEF("Cobra",       CPU_POWERPC_COBRA,       0xFFFFFFFF, 401),
+#if defined (TODO)
+    POWERPC_DEF("Xipchip",     CPU_POWERPC_XIPCHIP,     0xFFFFFFFF, 401),
+#endif
+    /* PowerPC 403 family                                                    */
+    /* Generic PowerPC 403                                                   */
+    POWERPC_DEF("403",         CPU_POWERPC_403,         0xFFFF0000, 403),
+    /* PowerPC 403 microcontrolers                                           */
+    /* PowerPC 403 GA                                                        */
+    POWERPC_DEF("403GA",       CPU_POWERPC_403GA,       0xFFFFFFFF, 403),
+    /* PowerPC 403 GB                                                        */
+    POWERPC_DEF("403GB",       CPU_POWERPC_403GB,       0xFFFFFFFF, 403),
+    /* PowerPC 403 GC                                                        */
+    POWERPC_DEF("403GC",       CPU_POWERPC_403GC,       0xFFFFFFFF, 403),
+    /* PowerPC 403 GCX                                                       */
+    POWERPC_DEF("403GCX",      CPU_POWERPC_403GCX,      0xFFFFFFFF, 403GCX),
+#if defined (TODO)
+    /* PowerPC 403 GP                                                        */
+    POWERPC_DEF("403GP",       CPU_POWERPC_403GP,       0xFFFFFFFF, 403),
+#endif
+    /* PowerPC 405 family                                                    */
+    /* Generic PowerPC 405                                                   */
+    POWERPC_DEF("405",         CPU_POWERPC_405,         0xFFFF0000, 405),
+    /* PowerPC 405 cores                                                     */
+#if defined (TODO)
+    /* PowerPC 405 A3                                                        */
+    POWERPC_DEF("405A3",       CPU_POWERPC_405A3,       0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* PowerPC 405 A4                                                        */
+    POWERPC_DEF("405A4",       CPU_POWERPC_405A4,       0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* PowerPC 405 B3                                                        */
+    POWERPC_DEF("405B3",       CPU_POWERPC_405B3,       0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* PowerPC 405 B4                                                        */
+    POWERPC_DEF("405B4",       CPU_POWERPC_405B4,       0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* PowerPC 405 C3                                                        */
+    POWERPC_DEF("405C3",       CPU_POWERPC_405C3,       0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* PowerPC 405 C4                                                        */
+    POWERPC_DEF("405C4",       CPU_POWERPC_405C4,       0xFFFFFFFF, 405),
+#endif
+    /* PowerPC 405 D2                                                        */
+    POWERPC_DEF("405D2",       CPU_POWERPC_405D2,       0xFFFFFFFF, 405),
+#if defined (TODO)
+    /* PowerPC 405 D3                                                        */
+    POWERPC_DEF("405D3",       CPU_POWERPC_405D3,       0xFFFFFFFF, 405),
+#endif
+    /* PowerPC 405 D4                                                        */
+    POWERPC_DEF("405D4",       CPU_POWERPC_405D4,       0xFFFFFFFF, 405),
+#if defined (TODO)
+    /* PowerPC 405 D5                                                        */
+    POWERPC_DEF("405D5",       CPU_POWERPC_405D5,       0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* PowerPC 405 E4                                                        */
+    POWERPC_DEF("405E4",       CPU_POWERPC_405E4,       0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* PowerPC 405 F4                                                        */
+    POWERPC_DEF("405F4",       CPU_POWERPC_405F4,       0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* PowerPC 405 F5                                                        */
+    POWERPC_DEF("405F5",       CPU_POWERPC_405F5,       0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* PowerPC 405 F6                                                        */
+    POWERPC_DEF("405F6",       CPU_POWERPC_405F6,       0xFFFFFFFF, 405),
+#endif
+    /* PowerPC 405 microcontrolers                                           */
+    /* PowerPC 405 CR                                                        */
+    POWERPC_DEF("405CR",       CPU_POWERPC_405CR,       0xFFFFFFFF, 405),
+    /* PowerPC 405 CRa                                                       */
+    POWERPC_DEF("405CRa",      CPU_POWERPC_405CRa,      0xFFFFFFFF, 405),
+    /* PowerPC 405 CRb                                                       */
+    POWERPC_DEF("405CRb",      CPU_POWERPC_405CRb,      0xFFFFFFFF, 405),
+    /* PowerPC 405 CRc                                                       */
+    POWERPC_DEF("405CRc",      CPU_POWERPC_405CRc,      0xFFFFFFFF, 405),
+    /* PowerPC 405 EP                                                        */
+    POWERPC_DEF("405EP",       CPU_POWERPC_405EP,       0xFFFFFFFF, 405),
+#if defined(TODO)
+    /* PowerPC 405 EXr                                                       */
+    POWERPC_DEF("405EXr",      CPU_POWERPC_405EXr,      0xFFFFFFFF, 405),
+#endif
+    /* PowerPC 405 EZ                                                        */
+    POWERPC_DEF("405EZ",       CPU_POWERPC_405EZ,       0xFFFFFFFF, 405),
+#if defined(TODO)
+    /* PowerPC 405 FX                                                        */
+    POWERPC_DEF("405FX",       CPU_POWERPC_405FX,       0xFFFFFFFF, 405),
+#endif
+    /* PowerPC 405 GP                                                        */
+    POWERPC_DEF("405GP",       CPU_POWERPC_405GP,       0xFFFFFFFF, 405),
+    /* PowerPC 405 GPa                                                       */
+    POWERPC_DEF("405GPa",      CPU_POWERPC_405GPa,      0xFFFFFFFF, 405),
+    /* PowerPC 405 GPb                                                       */
+    POWERPC_DEF("405GPb",      CPU_POWERPC_405GPb,      0xFFFFFFFF, 405),
+    /* PowerPC 405 GPc                                                       */
+    POWERPC_DEF("405GPc",      CPU_POWERPC_405GPc,      0xFFFFFFFF, 405),
+    /* PowerPC 405 GPd                                                       */
+    POWERPC_DEF("405GPd",      CPU_POWERPC_405GPd,      0xFFFFFFFF, 405),
+    /* PowerPC 405 GPe                                                       */
+    POWERPC_DEF("405GPe",      CPU_POWERPC_405GPe,      0xFFFFFFFF, 405),
+    /* PowerPC 405 GPR                                                       */
+    POWERPC_DEF("405GPR",      CPU_POWERPC_405GPR,      0xFFFFFFFF, 405),
+#if defined(TODO)
+    /* PowerPC 405 H                                                         */
+    POWERPC_DEF("405H",        CPU_POWERPC_405H,        0xFFFFFFFF, 405),
+#endif
+#if defined(TODO)
+    /* PowerPC 405 L                                                         */
+    POWERPC_DEF("405L",        CPU_POWERPC_405L,        0xFFFFFFFF, 405),
+#endif
+    /* PowerPC 405 LP                                                        */
+    POWERPC_DEF("405LP",       CPU_POWERPC_405LP,       0xFFFFFFFF, 405),
+#if defined(TODO)
+    /* PowerPC 405 PM                                                        */
+    POWERPC_DEF("405PM",       CPU_POWERPC_405PM,       0xFFFFFFFF, 405),
+#endif
+#if defined(TODO)
+    /* PowerPC 405 PS                                                        */
+    POWERPC_DEF("405PS",       CPU_POWERPC_405PS,       0xFFFFFFFF, 405),
+#endif
+#if defined(TODO)
+    /* PowerPC 405 S                                                         */
+    POWERPC_DEF("405S",        CPU_POWERPC_405S,        0xFFFFFFFF, 405),
+#endif
+    /* Npe405 H                                                              */
+    POWERPC_DEF("Npe405H",     CPU_POWERPC_NPE405H,     0xFFFFFFFF, 405),
+    /* Npe405 H2                                                             */
+    POWERPC_DEF("Npe405H2",    CPU_POWERPC_NPE405H2,    0xFFFFFFFF, 405),
+    /* Npe405 L                                                              */
+    POWERPC_DEF("Npe405L",     CPU_POWERPC_NPE405L,     0xFFFFFFFF, 405),
+    /* Npe4GS3                                                               */
+    POWERPC_DEF("Npe4GS3",     CPU_POWERPC_NPE4GS3,     0xFFFFFFFF, 405),
+#if defined (TODO)
+    POWERPC_DEF("Npcxx1",      CPU_POWERPC_NPCxx1,      0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    POWERPC_DEF("Npr161",      CPU_POWERPC_NPR161,      0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* PowerPC LC77700 (Sanyo)                                               */
+    POWERPC_DEF("LC77700",     CPU_POWERPC_LC77700,     0xFFFFFFFF, 405),
+#endif
+    /* PowerPC 401/403/405 based set-top-box microcontrolers                 */
+#if defined (TODO)
+    /* STB010000                                                             */
+    POWERPC_DEF("STB01000",    CPU_POWERPC_STB01000,    0xFFFFFFFF, 401x2),
+#endif
+#if defined (TODO)
+    /* STB01010                                                              */
+    POWERPC_DEF("STB01010",    CPU_POWERPC_STB01010,    0xFFFFFFFF, 401x2),
+#endif
+#if defined (TODO)
+    /* STB0210                                                               */
+    POWERPC_DEF("STB0210",     CPU_POWERPC_STB0210,     0xFFFFFFFF, 401x3),
+#endif
+    /* STB03xx                                                               */
+    POWERPC_DEF("STB03",       CPU_POWERPC_STB03,       0xFFFFFFFF, 405),
+#if defined (TODO)
+    /* STB043x                                                               */
+    POWERPC_DEF("STB043",      CPU_POWERPC_STB043,      0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* STB045x                                                               */
+    POWERPC_DEF("STB045",      CPU_POWERPC_STB045,      0xFFFFFFFF, 405),
+#endif
+    /* STB04xx                                                               */
+    POWERPC_DEF("STB04",       CPU_POWERPC_STB04,       0xFFFF0000, 405),
+    /* STB25xx                                                               */
+    POWERPC_DEF("STB25",       CPU_POWERPC_STB25,       0xFFFFFFFF, 405),
+#if defined (TODO)
+    /* STB130                                                                */
+    POWERPC_DEF("STB130",      CPU_POWERPC_STB130,      0xFFFFFFFF, 405),
+#endif
+    /* Xilinx PowerPC 405 cores                                              */
+    POWERPC_DEF("x2vp4",       CPU_POWERPC_X2VP4,       0xFFFFFFFF, 405),
+    POWERPC_DEF("x2vp7",       CPU_POWERPC_X2VP7,       0xFFFFFFFF, 405),
+    POWERPC_DEF("x2vp20",      CPU_POWERPC_X2VP20,      0xFFFFFFFF, 405),
+    POWERPC_DEF("x2vp50",      CPU_POWERPC_X2VP50,      0xFFFFFFFF, 405),
+#if defined (TODO)
+    /* Zarlink ZL10310                                                       */
+    POWERPC_DEF("zl10310",     CPU_POWERPC_ZL10310,     0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* Zarlink ZL10311                                                       */
+    POWERPC_DEF("zl10311",     CPU_POWERPC_ZL10311,     0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* Zarlink ZL10320                                                       */
+    POWERPC_DEF("zl10320",     CPU_POWERPC_ZL10320,     0xFFFFFFFF, 405),
+#endif
+#if defined (TODO)
+    /* Zarlink ZL10321                                                       */
+    POWERPC_DEF("zl10321",     CPU_POWERPC_ZL10321,     0xFFFFFFFF, 405),
+#endif
+    /* PowerPC 440 family                                                    */
+    /* Generic PowerPC 440                                                   */
+    POWERPC_DEF("440",         CPU_POWERPC_440,         0xFFFFFFFF, 440GP),
+    /* PowerPC 440 cores                                                     */
+#if defined (TODO)
+    /* PowerPC 440 A4                                                        */
+    POWERPC_DEF("440A4",       CPU_POWERPC_440A4,       0xFFFFFFFF, 440x4),
+#endif
+#if defined (TODO)
+    /* PowerPC 440 A5                                                        */
+    POWERPC_DEF("440A5",       CPU_POWERPC_440A5,       0xFFFFFFFF, 440x5),
+#endif
+#if defined (TODO)
+    /* PowerPC 440 B4                                                        */
+    POWERPC_DEF("440B4",       CPU_POWERPC_440B4,       0xFFFFFFFF, 440x4),
+#endif
+#if defined (TODO)
+    /* PowerPC 440 G4                                                        */
+    POWERPC_DEF("440G4",       CPU_POWERPC_440G4,       0xFFFFFFFF, 440x4),
+#endif
+#if defined (TODO)
+    /* PowerPC 440 F5                                                        */
+    POWERPC_DEF("440F5",       CPU_POWERPC_440F5,       0xFFFFFFFF, 440x5),
+#endif
+#if defined (TODO)
+    /* PowerPC 440 G5                                                        */
+    POWERPC_DEF("440G5",       CPU_POWERPC_440G5,       0xFFFFFFFF, 440x5),
+#endif
+#if defined (TODO)
+    /* PowerPC 440H4                                                         */
+    POWERPC_DEF("440H4",       CPU_POWERPC_440H4,       0xFFFFFFFF, 440x4),
+#endif
+#if defined (TODO)
+    /* PowerPC 440H6                                                         */
+    POWERPC_DEF("440H6",       CPU_POWERPC_440H6,       0xFFFFFFFF, 440Gx5),
+#endif
+    /* PowerPC 440 microcontrolers                                           */
+    /* PowerPC 440 EP                                                        */
+    POWERPC_DEF("440EP",       CPU_POWERPC_440EP,       0xFFFFFFFF, 440EP),
+    /* PowerPC 440 EPa                                                       */
+    POWERPC_DEF("440EPa",      CPU_POWERPC_440EPa,      0xFFFFFFFF, 440EP),
+    /* PowerPC 440 EPb                                                       */
+    POWERPC_DEF("440EPb",      CPU_POWERPC_440EPb,      0xFFFFFFFF, 440EP),
+    /* PowerPC 440 EPX                                                       */
+    POWERPC_DEF("440EPX",      CPU_POWERPC_440EPX,      0xFFFFFFFF, 440EP),
+    /* PowerPC 440 GP                                                        */
+    POWERPC_DEF("440GP",       CPU_POWERPC_440GP,       0xFFFFFFFF, 440GP),
+    /* PowerPC 440 GPb                                                       */
+    POWERPC_DEF("440GPb",      CPU_POWERPC_440GPb,      0xFFFFFFFF, 440GP),
+    /* PowerPC 440 GPc                                                       */
+    POWERPC_DEF("440GPc",      CPU_POWERPC_440GPc,      0xFFFFFFFF, 440GP),
+    /* PowerPC 440 GR                                                        */
+    POWERPC_DEF("440GR",       CPU_POWERPC_440GR,       0xFFFFFFFF, 440x5),
+    /* PowerPC 440 GRa                                                       */
+    POWERPC_DEF("440GRa",      CPU_POWERPC_440GRa,      0xFFFFFFFF, 440x5),
+    /* PowerPC 440 GRX                                                       */
+    POWERPC_DEF("440GRX",      CPU_POWERPC_440GRX,      0xFFFFFFFF, 440x5),
+    /* PowerPC 440 GX                                                        */
+    POWERPC_DEF("440GX",       CPU_POWERPC_440GX,       0xFFFFFFFF, 440EP),
+    /* PowerPC 440 GXa                                                       */
+    POWERPC_DEF("440GXa",      CPU_POWERPC_440GXa,      0xFFFFFFFF, 440EP),
+    /* PowerPC 440 GXb                                                       */
+    POWERPC_DEF("440GXb",      CPU_POWERPC_440GXb,      0xFFFFFFFF, 440EP),
+    /* PowerPC 440 GXc                                                       */
+    POWERPC_DEF("440GXc",      CPU_POWERPC_440GXc,      0xFFFFFFFF, 440EP),
+    /* PowerPC 440 GXf                                                       */
+    POWERPC_DEF("440GXf",      CPU_POWERPC_440GXf,      0xFFFFFFFF, 440EP),
+#if defined(TODO)
+    /* PowerPC 440 S                                                         */
+    POWERPC_DEF("440S",        CPU_POWERPC_440S,        0xFFFFFFFF, 440),
+#endif
+    /* PowerPC 440 SP                                                        */
+    POWERPC_DEF("440SP",       CPU_POWERPC_440SP,       0xFFFFFFFF, 440EP),
+    /* PowerPC 440 SP2                                                       */
+    POWERPC_DEF("440SP2",      CPU_POWERPC_440SP2,      0xFFFFFFFF, 440EP),
+    /* PowerPC 440 SPE                                                       */
+    POWERPC_DEF("440SPE",      CPU_POWERPC_440SPE,      0xFFFFFFFF, 440EP),
+    /* PowerPC 460 family                                                    */
+#if defined (TODO)
+    /* Generic PowerPC 464                                                   */
+    POWERPC_DEF("464",         CPU_POWERPC_464,         0xFFFFFFFF, 460),
+#endif
+    /* PowerPC 464 microcontrolers                                           */
+#if defined (TODO)
+    /* PowerPC 464H90                                                        */
+    POWERPC_DEF("464H90",      CPU_POWERPC_464H90,      0xFFFFFFFF, 460),
+#endif
+#if defined (TODO)
+    /* PowerPC 464H90F                                                       */
+    POWERPC_DEF("464H90F",     CPU_POWERPC_464H90F,     0xFFFFFFFF, 460F),
+#endif
+    /* Freescale embedded PowerPC cores                                      */
+    /* e200 family                                                           */
+#if defined (TODO)
+    /* Generic PowerPC e200 core                                             */
+    POWERPC_DEF("e200",        CPU_POWERPC_e200,        0xFFFFFFFF, e200),
+#endif
+#if defined (TODO)
+    /* PowerPC e200z5 core                                                   */
+    POWERPC_DEF("e200z5",      CPU_POWERPC_e200z5,      0xFFFFFFFF, e200),
+#endif
+#if defined (TODO)
+    /* PowerPC e200z6 core                                                   */
+    POWERPC_DEF("e200z6",      CPU_POWERPC_e200z6,      0xFFFFFFFF, e200),
+#endif
+    /* e300 family                                                           */
+#if defined (TODO)
+    /* Generic PowerPC e300 core                                             */
+    POWERPC_DEF("e300",        CPU_POWERPC_e300,        0xFFFFFFFF, e300),
+#endif
+#if defined (TODO)
+    /* PowerPC e300c1 core                                                   */
+    POWERPC_DEF("e300c1",      CPU_POWERPC_e300c1,      0xFFFFFFFF, e300),
+#endif
+#if defined (TODO)
+    /* PowerPC e300c2 core                                                   */
+    POWERPC_DEF("e300c2",      CPU_POWERPC_e300c2,      0xFFFFFFFF, e300),
+#endif
+#if defined (TODO)
+    /* PowerPC e300c3 core                                                   */
+    POWERPC_DEF("e300c3",      CPU_POWERPC_e300c3,      0xFFFFFFFF, e300),
+#endif
+    /* e500 family                                                           */
+#if defined (TODO)
+    /* PowerPC e500 core                                                     */
+    POWERPC_DEF("e500",        CPU_POWERPC_e500,        0xFFFFFFFF, e500),
+#endif
+#if defined (TODO)
+    /* PowerPC e500 v1.1 core                                                */
+    POWERPC_DEF("e500v1.1",    CPU_POWERPC_e500_v11,    0xFFFFFFFF, e500),
+#endif
+#if defined (TODO)
+    /* PowerPC e500 v1.2 core                                                */
+    POWERPC_DEF("e500v1.2",    CPU_POWERPC_e500_v12,    0xFFFFFFFF, e500),
+#endif
+#if defined (TODO)
+    /* PowerPC e500 v2.1 core                                                */
+    POWERPC_DEF("e500v2.1",    CPU_POWERPC_e500_v21,    0xFFFFFFFF, e500),
+#endif
+#if defined (TODO)
+    /* PowerPC e500 v2.2 core                                                */
+    POWERPC_DEF("e500v2.2",    CPU_POWERPC_e500_v22,    0xFFFFFFFF, e500),
+#endif
+    /* e600 family                                                           */
+#if defined (TODO)
+    /* PowerPC e600 core                                                     */
+    POWERPC_DEF("e600",        CPU_POWERPC_e600,        0xFFFFFFFF, e600),
+#endif
+    /* PowerPC MPC 5xx cores                                                 */
+#if defined (TODO)
+    /* PowerPC MPC 5xx                                                       */
+    POWERPC_DEF("mpc5xx",      CPU_POWERPC_5xx,         0xFFFFFFFF, 5xx),
+#endif
+    /* PowerPC MPC 8xx cores                                                 */
+#if defined (TODO)
+    /* PowerPC MPC 8xx                                                       */
+    POWERPC_DEF("mpc8xx",      CPU_POWERPC_8xx,         0xFFFFFFFF, 8xx),
+#endif
+    /* PowerPC MPC 8xxx cores                                                */
+#if defined (TODO)
+    /* PowerPC MPC 82xx HIP3                                                 */
+    POWERPC_DEF("mpc82xxhip3", CPU_POWERPC_82xx_HIP3,   0xFFFFFFFF, 82xx),
+#endif
+#if defined (TODO)
+    /* PowerPC MPC 82xx HIP4                                                 */
+    POWERPC_DEF("mpc82xxhip4", CPU_POWERPC_82xx_HIP4,   0xFFFFFFFF, 82xx),
+#endif
+#if defined (TODO)
+    /* PowerPC MPC 827x                                                      */
+    POWERPC_DEF("mpc827x",     CPU_POWERPC_827x,        0xFFFFFFFF, 827x),
+#endif
 
+    /* 32 bits "classic" PowerPC                                             */
+    /* PowerPC 6xx family                                                    */
+    /* PowerPC 601                                                           */
+    POWERPC_DEF("601",         CPU_POWERPC_601,         0xFFFFFFFF, 601),
+    /* PowerPC 601v2                                                         */
+    POWERPC_DEF("601a",        CPU_POWERPC_601a,        0xFFFFFFFF, 601),
+    /* PowerPC 602                                                           */
+    POWERPC_DEF("602",         CPU_POWERPC_602,         0xFFFFFFFF, 602),
+    /* PowerPC 603                                                           */
+    POWERPC_DEF("603",         CPU_POWERPC_603,         0xFFFFFFFF, 603),
+    /* Code name for PowerPC 603                                             */
+    POWERPC_DEF("Vanilla",     CPU_POWERPC_603,         0xFFFFFFFF, 603),
+    /* PowerPC 603e                                                          */
+    POWERPC_DEF("603e",        CPU_POWERPC_603E,        0xFFFFFFFF, 603E),
+    /* Code name for PowerPC 603e                                            */
+    POWERPC_DEF("Stretch",     CPU_POWERPC_603E,        0xFFFFFFFF, 603E),
+    /* PowerPC 603e v1.1                                                     */
+    POWERPC_DEF("603e1.1",     CPU_POWERPC_603E_v11,    0xFFFFFFFF, 603E),
+    /* PowerPC 603e v1.2                                                     */
+    POWERPC_DEF("603e1.2",     CPU_POWERPC_603E_v12,    0xFFFFFFFF, 603E),
+    /* PowerPC 603e v1.3                                                     */
+    POWERPC_DEF("603e1.3",     CPU_POWERPC_603E_v13,    0xFFFFFFFF, 603E),
+    /* PowerPC 603e v1.4                                                     */
+    POWERPC_DEF("603e1.4",     CPU_POWERPC_603E_v14,    0xFFFFFFFF, 603E),
+    /* PowerPC 603e v2.2                                                     */
+    POWERPC_DEF("603e2.2",     CPU_POWERPC_603E_v22,    0xFFFFFFFF, 603E),
+    /* PowerPC 603e v3                                                       */
+    POWERPC_DEF("603e3",       CPU_POWERPC_603E_v3,     0xFFFFFFFF, 603E),
+    /* PowerPC 603e v4                                                       */
+    POWERPC_DEF("603e4",       CPU_POWERPC_603E_v4,     0xFFFFFFFF, 603E),
+    /* PowerPC 603e v4.1                                                     */
+    POWERPC_DEF("603e4.1",     CPU_POWERPC_603E_v41,    0xFFFFFFFF, 603E),
+    /* PowerPC 603e                                                          */
+    POWERPC_DEF("603e7",       CPU_POWERPC_603E7,       0xFFFFFFFF, 603E),
+    /* PowerPC 603e7t                                                        */
+    POWERPC_DEF("603e7t",      CPU_POWERPC_603E7t,      0xFFFFFFFF, 603E),
+    /* PowerPC 603e7v                                                        */
+    POWERPC_DEF("603e7v",      CPU_POWERPC_603E7v,      0xFFFFFFFF, 603E),
+    /* Code name for PowerPC 603ev                                           */
+    POWERPC_DEF("Vaillant",    CPU_POWERPC_603E7v,      0xFFFFFFFF, 603E),
+    /* PowerPC 603e7v1                                                       */
+    POWERPC_DEF("603e7v1",     CPU_POWERPC_603E7v1,     0xFFFFFFFF, 603E),
+    /* PowerPC 603e7v2                                                       */
+    POWERPC_DEF("603e7v2",     CPU_POWERPC_603E7v2,     0xFFFFFFFF, 603E),
+    /* PowerPC 603p                                                          */
+    /* to be checked */
+    POWERPC_DEF("603p",        CPU_POWERPC_603P,        0xFFFFFFFF, 603),
+    /* PowerPC 603r                                                          */
+    POWERPC_DEF("603r",        CPU_POWERPC_603R,        0xFFFFFFFF, 603E),
+    /* Code name for PowerPC 603r                                            */
+    POWERPC_DEF("Goldeneye",   CPU_POWERPC_603R,        0xFFFFFFFF, 603E),
+    /* PowerPC G2 core                                                       */
+    POWERPC_DEF("G2",          CPU_POWERPC_G2,          0xFFFFFFFF, G2),
+    /* PowerPC G2 H4                                                         */
+    POWERPC_DEF("G2H4",        CPU_POWERPC_G2H4,        0xFFFFFFFF, G2),
+    /* PowerPC G2 GP                                                         */
+    POWERPC_DEF("G2GP",        CPU_POWERPC_G2gp,        0xFFFFFFFF, G2),
+    /* PowerPC G2 LS                                                         */
+    POWERPC_DEF("G2LS",        CPU_POWERPC_G2ls,        0xFFFFFFFF, G2),
+    /* PowerPC G2LE                                                          */
+    /* Same as G2, with little-endian mode support                           */
+    POWERPC_DEF("G2le",        CPU_POWERPC_G2LE,        0xFFFFFFFF, G2LE),
+    /* PowerPC G2LE GP                                                       */
+    POWERPC_DEF("G2leGP",      CPU_POWERPC_G2LEgp,      0xFFFFFFFF, G2LE),
+    /* PowerPC G2LE LS                                                       */
+    POWERPC_DEF("G2leLS",      CPU_POWERPC_G2LEls,      0xFFFFFFFF, G2LE),
+    /* PowerPC 604                                                           */
+    POWERPC_DEF("604",         CPU_POWERPC_604,         0xFFFFFFFF, 604),
+    /* PowerPC 604e                                                          */
+    POWERPC_DEF("604e",        CPU_POWERPC_604E,        0xFFFFFFFF, 604),
+    /* PowerPC 604e v1.0                                                     */
+    POWERPC_DEF("604e1.0",     CPU_POWERPC_604E_v10,    0xFFFFFFFF, 604),
+    /* PowerPC 604e v2.2                                                     */
+    POWERPC_DEF("604e2.2",     CPU_POWERPC_604E_v22,    0xFFFFFFFF, 604),
+    /* PowerPC 604e v2.4                                                     */
+    POWERPC_DEF("604e2.4",     CPU_POWERPC_604E_v24,    0xFFFFFFFF, 604),
+    /* PowerPC 604r                                                          */
+    POWERPC_DEF("604r",        CPU_POWERPC_604R,        0xFFFFFFFF, 604),
+#if defined(TODO)
+    /* PowerPC 604ev                                                         */
+    POWERPC_DEF("604ev",       CPU_POWERPC_604EV,       0xFFFFFFFF, 604),
+#endif
+    /* PowerPC 7xx family                                                    */
+    /* Generic PowerPC 740 (G3)                                              */
+    POWERPC_DEF("740",         CPU_POWERPC_7x0,         0xFFFFFFFF, 7x0),
+    /* Generic PowerPC 750 (G3)                                              */
+    POWERPC_DEF("750",         CPU_POWERPC_7x0,         0xFFFFFFFF, 7x0),
+    /* Code name for generic PowerPC 740/750 (G3)                            */
+    POWERPC_DEF("Arthur",      CPU_POWERPC_7x0,         0xFFFFFFFF, 7x0),
+    /* PowerPC 740/750 is also known as G3                                   */
+    POWERPC_DEF("G3",          CPU_POWERPC_7x0,         0xFFFFFFFF, 7x0),
+    /* PowerPC 740 v2.0 (G3)                                                 */
+    POWERPC_DEF("740v2.0",     CPU_POWERPC_7x0_v20,     0xFFFFFFFF, 7x0),
+    /* PowerPC 750 v2.0 (G3)                                                 */
+    POWERPC_DEF("750v2.0",     CPU_POWERPC_7x0_v20,     0xFFFFFFFF, 7x0),
+    /* PowerPC 740 v2.1 (G3)                                                 */
+    POWERPC_DEF("740v2.1",     CPU_POWERPC_7x0_v21,     0xFFFFFFFF, 7x0),
+    /* PowerPC 750 v2.1 (G3)                                                 */
+    POWERPC_DEF("750v2.1",     CPU_POWERPC_7x0_v21,     0xFFFFFFFF, 7x0),
+    /* PowerPC 740 v2.2 (G3)                                                 */
+    POWERPC_DEF("740v2.2",     CPU_POWERPC_7x0_v22,     0xFFFFFFFF, 7x0),
+    /* PowerPC 750 v2.2 (G3)                                                 */
+    POWERPC_DEF("750v2.2",     CPU_POWERPC_7x0_v22,     0xFFFFFFFF, 7x0),
+    /* PowerPC 740 v3.0 (G3)                                                 */
+    POWERPC_DEF("740v3.0",     CPU_POWERPC_7x0_v30,     0xFFFFFFFF, 7x0),
+    /* PowerPC 750 v3.0 (G3)                                                 */
+    POWERPC_DEF("750v3.0",     CPU_POWERPC_7x0_v30,     0xFFFFFFFF, 7x0),
+    /* PowerPC 740 v3.1 (G3)                                                 */
+    POWERPC_DEF("740v3.1",     CPU_POWERPC_7x0_v31,     0xFFFFFFFF, 7x0),
+    /* PowerPC 750 v3.1 (G3)                                                 */
+    POWERPC_DEF("750v3.1",     CPU_POWERPC_7x0_v31,     0xFFFFFFFF, 7x0),
+    /* PowerPC 740E (G3)                                                     */
+    POWERPC_DEF("740e",        CPU_POWERPC_740E,        0xFFFFFFFF, 7x0),
+    /* PowerPC 740P (G3)                                                     */
+    POWERPC_DEF("740p",        CPU_POWERPC_7x0P,        0xFFFFFFFF, 7x0),
+    /* PowerPC 750P (G3)                                                     */
+    POWERPC_DEF("750p",        CPU_POWERPC_7x0P,        0xFFFFFFFF, 7x0),
+    /* Code name for PowerPC 740P/750P (G3)                                  */
+    POWERPC_DEF("Conan/Doyle", CPU_POWERPC_7x0P,        0xFFFFFFFF, 7x0),
+    /* PowerPC 750CL (G3 embedded)                                           */
+    POWERPC_DEF("750cl",       CPU_POWERPC_750CL,       0xFFFFFFFF, 7x0),
+    /* PowerPC 750CX (G3 embedded)                                           */
+    POWERPC_DEF("750cx",       CPU_POWERPC_750CX,       0xFFFFFFFF, 7x0),
+    /* PowerPC 750CX v2.1 (G3 embedded)                                      */
+    POWERPC_DEF("750cx2.1",    CPU_POWERPC_750CX_v21,   0xFFFFFFFF, 7x0),
+    /* PowerPC 750CX v2.2 (G3 embedded)                                      */
+    POWERPC_DEF("750cx2.2",    CPU_POWERPC_750CX_v22,   0xFFFFFFFF, 7x0),
+    /* PowerPC 750CXe (G3 embedded)                                          */
+    POWERPC_DEF("750cxe",      CPU_POWERPC_750CXE,      0xFFFFFFFF, 7x0),
+    /* PowerPC 750CXe v2.1 (G3 embedded)                                     */
+    POWERPC_DEF("750cxe21",    CPU_POWERPC_750CXE_v21,  0xFFFFFFFF, 7x0),
+    /* PowerPC 750CXe v2.2 (G3 embedded)                                     */
+    POWERPC_DEF("750cxe22",    CPU_POWERPC_750CXE_v22,  0xFFFFFFFF, 7x0),
+    /* PowerPC 750CXe v2.3 (G3 embedded)                                     */
+    POWERPC_DEF("750cxe23",    CPU_POWERPC_750CXE_v23,  0xFFFFFFFF, 7x0),
+    /* PowerPC 750CXe v2.4 (G3 embedded)                                     */
+    POWERPC_DEF("750cxe24",    CPU_POWERPC_750CXE_v24,  0xFFFFFFFF, 7x0),
+    /* PowerPC 750CXe v2.4b (G3 embedded)                                    */
+    POWERPC_DEF("750cxe24b",   CPU_POWERPC_750CXE_v24b, 0xFFFFFFFF, 7x0),
+    /* PowerPC 750CXe v3.1 (G3 embedded)                                     */
+    POWERPC_DEF("750cxe31",    CPU_POWERPC_750CXE_v31,  0xFFFFFFFF, 7x0),
+    /* PowerPC 750CXe v3.1b (G3 embedded)                                    */
+    POWERPC_DEF("750cxe3.1b",  CPU_POWERPC_750CXE_v31b, 0xFFFFFFFF, 7x0),
+    /* PowerPC 750CXr (G3 embedded)                                          */
+    POWERPC_DEF("750cxr",      CPU_POWERPC_750CXR,      0xFFFFFFFF, 7x0),
+    /* PowerPC 750E (G3)                                                     */
+    POWERPC_DEF("750e",        CPU_POWERPC_750E,        0xFFFFFFFF, 7x0),
+    /* PowerPC 750FL (G3 embedded)                                           */
+    POWERPC_DEF("750fl",       CPU_POWERPC_750FL,       0xFFFFFFFF, 750fx),
+    /* PowerPC 750FX (G3 embedded)                                           */
+    POWERPC_DEF("750fx",       CPU_POWERPC_750FX,       0xFFFFFFFF, 750fx),
+    /* PowerPC 750FX v1.0 (G3 embedded)                                      */
+    POWERPC_DEF("750fx1.0",    CPU_POWERPC_750FX_v10,   0xFFFFFFFF, 750fx),
+    /* PowerPC 750FX v2.0 (G3 embedded)                                      */
+    POWERPC_DEF("750fx2.0",    CPU_POWERPC_750FX_v20,   0xFFFFFFFF, 750fx),
+    /* PowerPC 750FX v2.1 (G3 embedded)                                      */
+    POWERPC_DEF("750fx2.1",    CPU_POWERPC_750FX_v21,   0xFFFFFFFF, 750fx),
+    /* PowerPC 750FX v2.2 (G3 embedded)                                      */
+    POWERPC_DEF("750fx2.2",    CPU_POWERPC_750FX_v22,   0xFFFFFFFF, 750fx),
+    /* PowerPC 750FX v2.3 (G3 embedded)                                      */
+    POWERPC_DEF("750fx2.3",    CPU_POWERPC_750FX_v23,   0xFFFFFFFF, 750fx),
+    /* PowerPC 750GL (G3 embedded)                                           */
+    POWERPC_DEF("750gl",       CPU_POWERPC_750GL,       0xFFFFFFFF, 750fx),
+    /* PowerPC 750GX (G3 embedded)                                           */
+    POWERPC_DEF("750gx",       CPU_POWERPC_750GX,       0xFFFFFFFF, 750fx),
+    /* PowerPC 750GX v1.0 (G3 embedded)                                      */
+    POWERPC_DEF("750gx1.0",    CPU_POWERPC_750GX_v10,   0xFFFFFFFF, 750fx),
+    /* PowerPC 750GX v1.1 (G3 embedded)                                      */
+    POWERPC_DEF("750gx1.1",    CPU_POWERPC_750GX_v11,   0xFFFFFFFF, 750fx),
+    /* PowerPC 750GX v1.2 (G3 embedded)                                      */
+    POWERPC_DEF("750gx1.2",    CPU_POWERPC_750GX_v12,   0xFFFFFFFF, 750fx),
+    /* PowerPC 750L (G3 embedded)                                            */
+    POWERPC_DEF("750l",        CPU_POWERPC_750L,        0xFFFFFFFF, 7x0),
+    /* Code name for PowerPC 750L (G3 embedded)                              */
+    POWERPC_DEF("LoneStar",    CPU_POWERPC_750L,        0xFFFFFFFF, 7x0),
+    /* PowerPC 750L v2.2 (G3 embedded)                                       */
+    POWERPC_DEF("750l2.2",     CPU_POWERPC_750L_v22,    0xFFFFFFFF, 7x0),
+    /* PowerPC 750L v3.0 (G3 embedded)                                       */
+    POWERPC_DEF("750l3.0",     CPU_POWERPC_750L_v30,    0xFFFFFFFF, 7x0),
+    /* PowerPC 750L v3.2 (G3 embedded)                                       */
+    POWERPC_DEF("750l3.2",     CPU_POWERPC_750L_v32,    0xFFFFFFFF, 7x0),
+    /* Generic PowerPC 745                                                   */
+    POWERPC_DEF("745",         CPU_POWERPC_7x5,         0xFFFFFFFF, 7x5),
+    /* Generic PowerPC 755                                                   */
+    POWERPC_DEF("755",         CPU_POWERPC_7x5,         0xFFFFFFFF, 7x5),
+    /* Code name for PowerPC 745/755                                         */
+    POWERPC_DEF("Goldfinger",  CPU_POWERPC_7x5,         0xFFFFFFFF, 7x5),
+    /* PowerPC 745 v1.0                                                      */
+    POWERPC_DEF("745v1.0",     CPU_POWERPC_7x5_v10,     0xFFFFFFFF, 7x5),
+    /* PowerPC 755 v1.0                                                      */
+    POWERPC_DEF("755v1.0",     CPU_POWERPC_7x5_v10,     0xFFFFFFFF, 7x5),
+    /* PowerPC 745 v1.1                                                      */
+    POWERPC_DEF("745v1.1",     CPU_POWERPC_7x5_v11,     0xFFFFFFFF, 7x5),
+    /* PowerPC 755 v1.1                                                      */
+    POWERPC_DEF("755v1.1",     CPU_POWERPC_7x5_v11,     0xFFFFFFFF, 7x5),
+    /* PowerPC 745 v2.0                                                      */
+    POWERPC_DEF("745v2.0",     CPU_POWERPC_7x5_v20,     0xFFFFFFFF, 7x5),
+    /* PowerPC 755 v2.0                                                      */
+    POWERPC_DEF("755v2.0",     CPU_POWERPC_7x5_v20,     0xFFFFFFFF, 7x5),
+    /* PowerPC 745 v2.1                                                      */
+    POWERPC_DEF("745v2.1",     CPU_POWERPC_7x5_v21,     0xFFFFFFFF, 7x5),
+    /* PowerPC 755 v2.1                                                      */
+    POWERPC_DEF("755v2.1",     CPU_POWERPC_7x5_v21,     0xFFFFFFFF, 7x5),
+    /* PowerPC 745 v2.2                                                      */
+    POWERPC_DEF("745v2.2",     CPU_POWERPC_7x5_v22,     0xFFFFFFFF, 7x5),
+    /* PowerPC 755 v2.2                                                      */
+    POWERPC_DEF("755v2.2",     CPU_POWERPC_7x5_v22,     0xFFFFFFFF, 7x5),
+    /* PowerPC 745 v2.3                                                      */
+    POWERPC_DEF("745v2.3",     CPU_POWERPC_7x5_v23,     0xFFFFFFFF, 7x5),
+    /* PowerPC 755 v2.3                                                      */
+    POWERPC_DEF("755v2.3",     CPU_POWERPC_7x5_v23,     0xFFFFFFFF, 7x5),
+    /* PowerPC 745 v2.4                                                      */
+    POWERPC_DEF("745v2.4",     CPU_POWERPC_7x5_v24,     0xFFFFFFFF, 7x5),
+    /* PowerPC 755 v2.4                                                      */
+    POWERPC_DEF("755v2.4",     CPU_POWERPC_7x5_v24,     0xFFFFFFFF, 7x5),
+    /* PowerPC 745 v2.5                                                      */
+    POWERPC_DEF("745v2.5",     CPU_POWERPC_7x5_v25,     0xFFFFFFFF, 7x5),
+    /* PowerPC 755 v2.5                                                      */
+    POWERPC_DEF("755v2.5",     CPU_POWERPC_7x5_v25,     0xFFFFFFFF, 7x5),
+    /* PowerPC 745 v2.6                                                      */
+    POWERPC_DEF("745v2.6",     CPU_POWERPC_7x5_v26,     0xFFFFFFFF, 7x5),
+    /* PowerPC 755 v2.6                                                      */
+    POWERPC_DEF("755v2.6",     CPU_POWERPC_7x5_v26,     0xFFFFFFFF, 7x5),
+    /* PowerPC 745 v2.7                                                      */
+    POWERPC_DEF("745v2.7",     CPU_POWERPC_7x5_v27,     0xFFFFFFFF, 7x5),
+    /* PowerPC 755 v2.7                                                      */
+    POWERPC_DEF("755v2.7",     CPU_POWERPC_7x5_v27,     0xFFFFFFFF, 7x5),
+    /* PowerPC 745 v2.8                                                      */
+    POWERPC_DEF("745v2.8",     CPU_POWERPC_7x5_v28,     0xFFFFFFFF, 7x5),
+    /* PowerPC 755 v2.8                                                      */
+    POWERPC_DEF("755v2.8",     CPU_POWERPC_7x5_v28,     0xFFFFFFFF, 7x5),
 #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) */
+    /* PowerPC 745P (G3)                                                     */
+    POWERPC_DEF("745p",        CPU_POWERPC_7x5P,        0xFFFFFFFF, 7x5),
+    /* PowerPC 755P (G3)                                                     */
+    POWERPC_DEF("755p",        CPU_POWERPC_7x5P,        0xFFFFFFFF, 7x5),
 #endif
-        break;
+    /* PowerPC 74xx family                                                   */
+    /* PowerPC 7400 (G4)                                                     */
+    POWERPC_DEF("7400",        CPU_POWERPC_7400,        0xFFFFFFFF, 7400),
+    /* Code name for PowerPC 7400                                            */
+    POWERPC_DEF("Max",         CPU_POWERPC_7400,        0xFFFFFFFF, 7400),
+    /* PowerPC 74xx is also well known as G4                                 */
+    POWERPC_DEF("G4",          CPU_POWERPC_7400,        0xFFFFFFFF, 7400),
+    /* PowerPC 7400 v1.0 (G4)                                                */
+    POWERPC_DEF("7400v1.0",    CPU_POWERPC_7400_v10,    0xFFFFFFFF, 7400),
+    /* PowerPC 7400 v1.1 (G4)                                                */
+    POWERPC_DEF("7400v1.1",    CPU_POWERPC_7400_v11,    0xFFFFFFFF, 7400),
+    /* PowerPC 7400 v2.0 (G4)                                                */
+    POWERPC_DEF("7400v2.0",    CPU_POWERPC_7400_v20,    0xFFFFFFFF, 7400),
+    /* PowerPC 7400 v2.2 (G4)                                                */
+    POWERPC_DEF("7400v2.2",    CPU_POWERPC_7400_v22,    0xFFFFFFFF, 7400),
+    /* PowerPC 7400 v2.6 (G4)                                                */
+    POWERPC_DEF("7400v2.6",    CPU_POWERPC_7400_v26,    0xFFFFFFFF, 7400),
+    /* PowerPC 7400 v2.7 (G4)                                                */
+    POWERPC_DEF("7400v2.7",    CPU_POWERPC_7400_v27,    0xFFFFFFFF, 7400),
+    /* PowerPC 7400 v2.8 (G4)                                                */
+    POWERPC_DEF("7400v2.8",    CPU_POWERPC_7400_v28,    0xFFFFFFFF, 7400),
+    /* PowerPC 7400 v2.9 (G4)                                                */
+    POWERPC_DEF("7400v2.9",    CPU_POWERPC_7400_v29,    0xFFFFFFFF, 7400),
+    /* PowerPC 7410 (G4)                                                     */
+    POWERPC_DEF("7410",        CPU_POWERPC_7410,        0xFFFFFFFF, 7410),
+    /* Code name for PowerPC 7410                                            */
+    POWERPC_DEF("Nitro",       CPU_POWERPC_7410,        0xFFFFFFFF, 7410),
+    /* PowerPC 7410 v1.0 (G4)                                                */
+    POWERPC_DEF("7410v1.0",    CPU_POWERPC_7410_v10,    0xFFFFFFFF, 7410),
+    /* PowerPC 7410 v1.1 (G4)                                                */
+    POWERPC_DEF("7410v1.1",    CPU_POWERPC_7410_v11,    0xFFFFFFFF, 7410),
+    /* PowerPC 7410 v1.2 (G4)                                                */
+    POWERPC_DEF("7410v1.2",    CPU_POWERPC_7410_v12,    0xFFFFFFFF, 7410),
+    /* PowerPC 7410 v1.3 (G4)                                                */
+    POWERPC_DEF("7410v1.3",    CPU_POWERPC_7410_v13,    0xFFFFFFFF, 7410),
+    /* PowerPC 7410 v1.4 (G4)                                                */
+    POWERPC_DEF("7410v1.4",    CPU_POWERPC_7410_v14,    0xFFFFFFFF, 7410),
+    /* PowerPC 7448 (G4)                                                     */
+    POWERPC_DEF("7448",        CPU_POWERPC_7448,        0xFFFFFFFF, 7400),
+    /* PowerPC 7448 v1.0 (G4)                                                */
+    POWERPC_DEF("7448v1.0",    CPU_POWERPC_7448_v10,    0xFFFFFFFF, 7400),
+    /* PowerPC 7448 v1.1 (G4)                                                */
+    POWERPC_DEF("7448v1.1",    CPU_POWERPC_7448_v11,    0xFFFFFFFF, 7400),
+    /* PowerPC 7448 v2.0 (G4)                                                */
+    POWERPC_DEF("7448v2.0",    CPU_POWERPC_7448_v20,    0xFFFFFFFF, 7400),
+    /* PowerPC 7448 v2.1 (G4)                                                */
+    POWERPC_DEF("7448v2.1",    CPU_POWERPC_7448_v21,    0xFFFFFFFF, 7400),
+    /* PowerPC 7450 (G4)                                                     */
+    POWERPC_DEF("7450",        CPU_POWERPC_7450,        0xFFFFFFFF, 7450),
+    /* Code name for PowerPC 7450                                            */
+    POWERPC_DEF("Vger",        CPU_POWERPC_7450,        0xFFFFFFFF, 7450),
+    /* PowerPC 7450 v1.0 (G4)                                                */
+    POWERPC_DEF("7450v1.0",    CPU_POWERPC_7450_v10,    0xFFFFFFFF, 7450),
+    /* PowerPC 7450 v1.1 (G4)                                                */
+    POWERPC_DEF("7450v1.1",    CPU_POWERPC_7450_v11,    0xFFFFFFFF, 7450),
+    /* PowerPC 7450 v1.2 (G4)                                                */
+    POWERPC_DEF("7450v1.2",    CPU_POWERPC_7450_v12,    0xFFFFFFFF, 7450),
+    /* PowerPC 7450 v2.0 (G4)                                                */
+    POWERPC_DEF("7450v2.0",    CPU_POWERPC_7450_v20,    0xFFFFFFFF, 7450),
+    /* PowerPC 7450 v2.1 (G4)                                                */
+    POWERPC_DEF("7450v2.1",    CPU_POWERPC_7450_v21,    0xFFFFFFFF, 7450),
+    /* PowerPC 7441 (G4)                                                     */
+    POWERPC_DEF("7441",        CPU_POWERPC_74x1,        0xFFFFFFFF, 7440),
+    /* PowerPC 7451 (G4)                                                     */
+    POWERPC_DEF("7451",        CPU_POWERPC_74x1,        0xFFFFFFFF, 7450),
+    /* PowerPC 7441g (G4)                                                    */
+    POWERPC_DEF("7441g",       CPU_POWERPC_74x1G,       0xFFFFFFFF, 7440),
+    /* PowerPC 7451g (G4)                                                    */
+    POWERPC_DEF("7451g",       CPU_POWERPC_74x1G,       0xFFFFFFFF, 7450),
+    /* PowerPC 7445 (G4)                                                     */
+    POWERPC_DEF("7445",        CPU_POWERPC_74x5,        0xFFFFFFFF, 7445),
+    /* PowerPC 7455 (G4)                                                     */
+    POWERPC_DEF("7455",        CPU_POWERPC_74x5,        0xFFFFFFFF, 7455),
+    /* Code name for PowerPC 7445/7455                                       */
+    POWERPC_DEF("Apollo6",     CPU_POWERPC_74x5,        0xFFFFFFFF, 7455),
+    /* PowerPC 7445 v1.0 (G4)                                                */
+    POWERPC_DEF("7445v1.0",    CPU_POWERPC_74x5_v10,    0xFFFFFFFF, 7445),
+    /* PowerPC 7455 v1.0 (G4)                                                */
+    POWERPC_DEF("7455v1.0",    CPU_POWERPC_74x5_v10,    0xFFFFFFFF, 7455),
+    /* PowerPC 7445 v2.1 (G4)                                                */
+    POWERPC_DEF("7445v2.1",    CPU_POWERPC_74x5_v21,    0xFFFFFFFF, 7445),
+    /* PowerPC 7455 v2.1 (G4)                                                */
+    POWERPC_DEF("7455v2.1",    CPU_POWERPC_74x5_v21,    0xFFFFFFFF, 7455),
+    /* PowerPC 7445 v3.2 (G4)                                                */
+    POWERPC_DEF("7445v3.2",    CPU_POWERPC_74x5_v32,    0xFFFFFFFF, 7445),
+    /* PowerPC 7455 v3.2 (G4)                                                */
+    POWERPC_DEF("7455v3.2",    CPU_POWERPC_74x5_v32,    0xFFFFFFFF, 7455),
+    /* PowerPC 7445 v3.3 (G4)                                                */
+    POWERPC_DEF("7445v3.3",    CPU_POWERPC_74x5_v33,    0xFFFFFFFF, 7445),
+    /* PowerPC 7455 v3.3 (G4)                                                */
+    POWERPC_DEF("7455v3.3",    CPU_POWERPC_74x5_v33,    0xFFFFFFFF, 7455),
+    /* PowerPC 7445 v3.4 (G4)                                                */
+    POWERPC_DEF("7445v3.4",    CPU_POWERPC_74x5_v34,    0xFFFFFFFF, 7445),
+    /* PowerPC 7455 v3.4 (G4)                                                */
+    POWERPC_DEF("7455v3.4",    CPU_POWERPC_74x5_v34,    0xFFFFFFFF, 7455),
+    /* PowerPC 7447 (G4)                                                     */
+    POWERPC_DEF("7447",        CPU_POWERPC_74x7,        0xFFFFFFFF, 7445),
+    /* PowerPC 7457 (G4)                                                     */
+    POWERPC_DEF("7457",        CPU_POWERPC_74x7,        0xFFFFFFFF, 7455),
+    /* Code name for PowerPC 7447/7457                                       */
+    POWERPC_DEF("Apollo7",     CPU_POWERPC_74x7,        0xFFFFFFFF, 7455),
+    /* PowerPC 7447 v1.0 (G4)                                                */
+    POWERPC_DEF("7447v1.0",    CPU_POWERPC_74x7_v10,    0xFFFFFFFF, 7445),
+    /* PowerPC 7457 v1.0 (G4)                                                */
+    POWERPC_DEF("7457v1.0",    CPU_POWERPC_74x7_v10,    0xFFFFFFFF, 7455),
+    /* Code name for PowerPC 7447A/7457A                                     */
+    POWERPC_DEF("Apollo7PM",   CPU_POWERPC_74x7_v10,    0xFFFFFFFF, 7455),
+    /* PowerPC 7447 v1.1 (G4)                                                */
+    POWERPC_DEF("7447v1.1",    CPU_POWERPC_74x7_v11,    0xFFFFFFFF, 7445),
+    /* PowerPC 7457 v1.1 (G4)                                                */
+    POWERPC_DEF("7457v1.1",    CPU_POWERPC_74x7_v11,    0xFFFFFFFF, 7455),
+    /* PowerPC 7447 v1.2 (G4)                                                */
+    POWERPC_DEF("7447v1.2",    CPU_POWERPC_74x7_v12,    0xFFFFFFFF, 7445),
+    /* PowerPC 7457 v1.2 (G4)                                                */
+    POWERPC_DEF("7457v1.2",    CPU_POWERPC_74x7_v12,    0xFFFFFFFF, 7455),
+    /* 64 bits PowerPC                                                       */
+#if defined (TARGET_PPC64)
+#if defined (TODO)
+    /* PowerPC 620                                                           */
+    POWERPC_DEF("620",         CPU_POWERPC_620,         0xFFFFFFFF, 620),
+#endif
+#if defined (TODO)
+    /* PowerPC 630 (POWER3)                                                  */
+    POWERPC_DEF("630",         CPU_POWERPC_630,         0xFFFFFFFF, 630),
+    POWERPC_DEF("POWER3",      CPU_POWERPC_630,         0xFFFFFFFF, 630),
+#endif
+#if defined (TODO)
+    /* PowerPC 631 (Power 3+)                                                */
+    POWERPC_DEF("631",         CPU_POWERPC_631,         0xFFFFFFFF, 631),
+    POWERPC_DEF("POWER3+",     CPU_POWERPC_631,         0xFFFFFFFF, 631),
+#endif
+#if defined (TODO)
+    /* POWER4                                                                */
+    POWERPC_DEF("POWER4",      CPU_POWERPC_POWER4,      0xFFFFFFFF, POWER4),
+#endif
+#if defined (TODO)
+    /* POWER4p                                                               */
+    POWERPC_DEF("POWER4+",     CPU_POWERPC_POWER4P,     0xFFFFFFFF, POWER4P),
+#endif
+#if defined (TODO)
+    /* POWER5                                                                */
+    POWERPC_DEF("POWER5",      CPU_POWERPC_POWER5,      0xFFFFFFFF, POWER5),
+    /* POWER5GR                                                              */
+    POWERPC_DEF("POWER5gr",    CPU_POWERPC_POWER5GR,    0xFFFFFFFF, POWER5),
+#endif
+#if defined (TODO)
+    /* POWER5+                                                               */
+    POWERPC_DEF("POWER5+",     CPU_POWERPC_POWER5P,     0xFFFFFFFF, POWER5P),
+    /* POWER5GS                                                              */
+    POWERPC_DEF("POWER5gs",    CPU_POWERPC_POWER5GS,    0xFFFFFFFF, POWER5P),
+#endif
+#if defined (TODO)
+    /* POWER6                                                                */
+    POWERPC_DEF("POWER6",      CPU_POWERPC_POWER6,      0xFFFFFFFF, POWER6),
+    /* POWER6 running in POWER5 mode                                         */
+    POWERPC_DEF("POWER6_5",    CPU_POWERPC_POWER6_5,    0xFFFFFFFF, POWER5),
+    /* POWER6A                                                               */
+    POWERPC_DEF("POWER6A",     CPU_POWERPC_POWER6A,     0xFFFFFFFF, POWER6),
+#endif
+    /* PowerPC 970                                                           */
+    POWERPC_DEF("970",         CPU_POWERPC_970,         0xFFFFFFFF, 970),
+    /* PowerPC 970FX (G5)                                                    */
+    POWERPC_DEF("970fx",       CPU_POWERPC_970FX,       0xFFFFFFFF, 970FX),
+    /* PowerPC 970FX v1.0 (G5)                                               */
+    POWERPC_DEF("970fx1.0",    CPU_POWERPC_970FX_v10,   0xFFFFFFFF, 970FX),
+    /* PowerPC 970FX v2.0 (G5)                                               */
+    POWERPC_DEF("970fx2.0",    CPU_POWERPC_970FX_v20,   0xFFFFFFFF, 970FX),
+    /* PowerPC 970FX v2.1 (G5)                                               */
+    POWERPC_DEF("970fx2.1",    CPU_POWERPC_970FX_v21,   0xFFFFFFFF, 970FX),
+    /* PowerPC 970FX v3.0 (G5)                                               */
+    POWERPC_DEF("970fx3.0",    CPU_POWERPC_970FX_v30,   0xFFFFFFFF, 970FX),
+    /* PowerPC 970FX v3.1 (G5)                                               */
+    POWERPC_DEF("970fx3.1",    CPU_POWERPC_970FX_v31,   0xFFFFFFFF, 970FX),
+    /* PowerPC 970GX (G5)                                                    */
+    POWERPC_DEF("970gx",       CPU_POWERPC_970GX,       0xFFFFFFFF, 970GX),
+    /* PowerPC 970MP                                                         */
+    POWERPC_DEF("970mp",       CPU_POWERPC_970MP,       0xFFFFFFFF, 970MP),
+    /* PowerPC 970MP v1.0                                                    */
+    POWERPC_DEF("970mp1.0",    CPU_POWERPC_970MP_v10,   0xFFFFFFFF, 970MP),
+    /* PowerPC 970MP v1.1                                                    */
+    POWERPC_DEF("970mp1.1",    CPU_POWERPC_970MP_v11,   0xFFFFFFFF, 970MP),
+#if defined (TODO)
+    /* PowerPC Cell                                                          */
+    POWERPC_DEF("Cell",        CPU_POWERPC_CELL,        0xFFFFFFFF, 970),
+#endif
+#if defined (TODO)
+    /* PowerPC Cell v1.0                                                     */
+    POWERPC_DEF("Cell1.0",     CPU_POWERPC_CELL_v10,    0xFFFFFFFF, 970),
+#endif
+#if defined (TODO)
+    /* PowerPC Cell v2.0                                                     */
+    POWERPC_DEF("Cell2.0",     CPU_POWERPC_CELL_v20,    0xFFFFFFFF, 970),
+#endif
+#if defined (TODO)
+    /* PowerPC Cell v3.0                                                     */
+    POWERPC_DEF("Cell3.0",     CPU_POWERPC_CELL_v30,    0xFFFFFFFF, 970),
+#endif
+#if defined (TODO)
+    /* PowerPC Cell v3.1                                                     */
+    POWERPC_DEF("Cell3.1",     CPU_POWERPC_CELL_v31,    0xFFFFFFFF, 970),
+#endif
+#if defined (TODO)
+    /* PowerPC Cell v3.2                                                     */
+    POWERPC_DEF("Cell3.2",     CPU_POWERPC_CELL_v32,    0xFFFFFFFF, 970),
+#endif
+#if defined (TODO)
+    /* RS64 (Apache/A35)                                                     */
+    /* This one seems to support the whole POWER2 instruction set
+     * and the PowerPC 64 one.
+     */
+    /* What about A10 & A30 ? */
+    POWERPC_DEF("RS64",        CPU_POWERPC_RS64,        0xFFFFFFFF, RS64),
+    POWERPC_DEF("Apache",      CPU_POWERPC_RS64,        0xFFFFFFFF, RS64),
+    POWERPC_DEF("A35",         CPU_POWERPC_RS64,        0xFFFFFFFF, RS64),
+#endif
+#if defined (TODO)
+    /* RS64-II (NorthStar/A50)                                               */
+    POWERPC_DEF("RS64-II",     CPU_POWERPC_RS64II,      0xFFFFFFFF, RS64),
+    POWERPC_DEF("NorthStar",   CPU_POWERPC_RS64II,      0xFFFFFFFF, RS64),
+    POWERPC_DEF("A50",         CPU_POWERPC_RS64II,      0xFFFFFFFF, RS64),
+#endif
+#if defined (TODO)
+    /* RS64-III (Pulsar)                                                     */
+    POWERPC_DEF("RS64-III",    CPU_POWERPC_RS64III,     0xFFFFFFFF, RS64),
+    POWERPC_DEF("Pulsar",      CPU_POWERPC_RS64III,     0xFFFFFFFF, RS64),
+#endif
+#if defined (TODO)
+    /* RS64-IV (IceStar/IStar/SStar)                                         */
+    POWERPC_DEF("RS64-IV",     CPU_POWERPC_RS64IV,      0xFFFFFFFF, RS64),
+    POWERPC_DEF("IceStar",     CPU_POWERPC_RS64IV,      0xFFFFFFFF, RS64),
+    POWERPC_DEF("IStar",       CPU_POWERPC_RS64IV,      0xFFFFFFFF, RS64),
+    POWERPC_DEF("SStar",       CPU_POWERPC_RS64IV,      0xFFFFFFFF, RS64),
+#endif
 #endif /* defined (TARGET_PPC64) */
-
+    /* POWER                                                                 */
 #if defined (TODO)
-        /* POWER                                               */
-    case CPU_POWER:       /* POWER                         */
-    case CPU_POWER2:      /* POWER2                        */
-        break;
+    /* Original POWER                                                        */
+    POWERPC_DEF("POWER",       CPU_POWERPC_POWER,       0xFFFFFFFF, POWER),
+    POWERPC_DEF("RIOS",        CPU_POWERPC_POWER,       0xFFFFFFFF, POWER),
+    POWERPC_DEF("RSC",         CPU_POWERPC_POWER,       0xFFFFFFFF, POWER),
+    POWERPC_DEF("RSC3308",     CPU_POWERPC_POWER,       0xFFFFFFFF, POWER),
+    POWERPC_DEF("RSC4608",     CPU_POWERPC_POWER,       0xFFFFFFFF, POWER),
 #endif
+#if defined (TODO)
+    /* POWER2                                                                */
+    POWERPC_DEF("POWER2",      CPU_POWERPC_POWER2,      0xFFFFFFFF, POWER),
+    POWERPC_DEF("RSC2",        CPU_POWERPC_POWER2,      0xFFFFFFFF, POWER),
+    POWERPC_DEF("P2SC",        CPU_POWERPC_POWER2,      0xFFFFFFFF, POWER),
+#endif
+    /* PA semi cores                                                         */
+#if defined (TODO)
+    /* PA PA6T */
+    POWERPC_DEF("PA6T",        CPU_POWERPC_PA6T,        0xFFFFFFFF, PA6T),
+#endif
+    /* Generic PowerPCs                                                      */
+#if defined (TARGET_PPC64)
+#if defined (TODO)
+    POWERPC_DEF("ppc64",       CPU_POWERPC_PPC64,       0xFFFFFFFF, PPC64),
+#endif
+#endif
+    POWERPC_DEF("ppc32",       CPU_POWERPC_PPC32,       0xFFFFFFFF, PPC32),
+    POWERPC_DEF("ppc",         CPU_POWERPC_DEFAULT,     0xFFFFFFFF, DEFAULT),
+    /* Fallback                                                              */
+    POWERPC_DEF("default",     CPU_POWERPC_DEFAULT,     0xFFFFFFFF, DEFAULT),
+};
 
-    default:
-        gen_spr_generic(env);
-        /* XXX: TODO: allocate internal IRQ controller */
-        break;
+/*****************************************************************************/
+/* Generic CPU instanciation routine                                         */
+static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
+{
+#if !defined(CONFIG_USER_ONLY)
+    int i;
+
+    env->irq_inputs = NULL;
+    /* Set all exception vectors to an invalid address */
+    for (i = 0; i < POWERPC_EXCP_NB; i++)
+        env->excp_vectors[i] = (target_ulong)(-1ULL);
+    env->excp_prefix = 0x00000000;
+    env->ivor_mask = 0x00000000;
+    env->ivpr_mask = 0x00000000;
+    /* Default MMU definitions */
+    env->nb_BATs = 0;
+    env->nb_tlb = 0;
+    env->nb_ways = 0;
+#endif
+    /* Register SPR common to all PowerPC implementations */
+    gen_spr_generic(env);
+    spr_register(env, SPR_PVR, "PVR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 def->pvr);
+    /* PowerPC implementation specific initialisations (SPRs, timers, ...) */
+    (*def->init_proc)(env);
+    /* MSR bits & flags consistency checks */
+    if (env->msr_mask & (1 << 25)) {
+        switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
+        case POWERPC_FLAG_SPE:
+        case POWERPC_FLAG_VRE:
+            break;
+        default:
+            fprintf(stderr, "PowerPC MSR definition inconsistency\n"
+                    "Should define POWERPC_FLAG_SPE or POWERPC_FLAG_VRE\n");
+            exit(1);
+        }
+    } else if (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
+        fprintf(stderr, "PowerPC MSR definition inconsistency\n"
+                "Should not define POWERPC_FLAG_SPE nor POWERPC_FLAG_VRE\n");
+        exit(1);
     }
-    if (env->nb_BATs == -1)
-        env->nb_BATs = 4;
+    if (env->msr_mask & (1 << 17)) {
+        switch (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE)) {
+        case POWERPC_FLAG_TGPR:
+        case POWERPC_FLAG_CE:
+            break;
+        default:
+            fprintf(stderr, "PowerPC MSR definition inconsistency\n"
+                    "Should define POWERPC_FLAG_TGPR or POWERPC_FLAG_CE\n");
+            exit(1);
+        }
+    } else if (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE)) {
+        fprintf(stderr, "PowerPC MSR definition inconsistency\n"
+                "Should not define POWERPC_FLAG_TGPR nor POWERPC_FLAG_CE\n");
+        exit(1);
+    }
+    if (env->msr_mask & (1 << 10)) {
+        switch (env->flags & (POWERPC_FLAG_SE | POWERPC_FLAG_DWE |
+                              POWERPC_FLAG_UBLE)) {
+        case POWERPC_FLAG_SE:
+        case POWERPC_FLAG_DWE:
+        case POWERPC_FLAG_UBLE:
+            break;
+        default:
+            fprintf(stderr, "PowerPC MSR definition inconsistency\n"
+                    "Should define POWERPC_FLAG_SE or POWERPC_FLAG_DWE or "
+                    "POWERPC_FLAG_UBLE\n");
+            exit(1);
+        }
+    } else if (env->flags & (POWERPC_FLAG_SE | POWERPC_FLAG_DWE |
+                             POWERPC_FLAG_UBLE)) {
+        fprintf(stderr, "PowerPC MSR definition inconsistency\n"
+                "Should not define POWERPC_FLAG_SE nor POWERPC_FLAG_DWE nor "
+                "POWERPC_FLAG_UBLE\n");
+            exit(1);
+    }
+    if (env->msr_mask & (1 << 9)) {
+        switch (env->flags & (POWERPC_FLAG_BE | POWERPC_FLAG_DE)) {
+        case POWERPC_FLAG_BE:
+        case POWERPC_FLAG_DE:
+            break;
+        default:
+            fprintf(stderr, "PowerPC MSR definition inconsistency\n"
+                    "Should define POWERPC_FLAG_BE or POWERPC_FLAG_DE\n");
+            exit(1);
+        }
+    } else if (env->flags & (POWERPC_FLAG_BE | POWERPC_FLAG_DE)) {
+        fprintf(stderr, "PowerPC MSR definition inconsistency\n"
+                "Should not define POWERPC_FLAG_BE nor POWERPC_FLAG_DE\n");
+        exit(1);
+    }
+    if (env->msr_mask & (1 << 2)) {
+        switch (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM)) {
+        case POWERPC_FLAG_PX:
+        case POWERPC_FLAG_PMM:
+            break;
+        default:
+            fprintf(stderr, "PowerPC MSR definition inconsistency\n"
+                    "Should define POWERPC_FLAG_PX or POWERPC_FLAG_PMM\n");
+            exit(1);
+        }
+    } else if (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM)) {
+        fprintf(stderr, "PowerPC MSR definition inconsistency\n"
+                "Should not define POWERPC_FLAG_PX nor POWERPC_FLAG_PMM\n");
+        exit(1);
+    }
     /* Allocate TLBs buffer when needed */
+#if !defined(CONFIG_USER_ONLY)
     if (env->nb_tlb != 0) {
         int nb_tlb = env->nb_tlb;
         if (env->id_tlbs != 0)
@@ -2435,36 +6038,51 @@
         /* Pre-compute some useful values */
         env->tlb_per_way = env->nb_tlb / env->nb_ways;
     }
+    if (env->irq_inputs == NULL) {
+        fprintf(stderr, "WARNING: no internal IRQ controller registered.\n"
+                " Attempt Qemu to crash very soon !\n");
+    }
+#endif
+    if (env->check_pow == NULL) {
+        fprintf(stderr, "WARNING: no power management check handler "
+                "registered.\n"
+                " Attempt Qemu to crash very soon !\n");
+    }
 }
 
 #if defined(PPC_DUMP_CPU)
-static void dump_sprs (CPUPPCState *env)
+static void dump_ppc_sprs (CPUPPCState *env)
 {
     ppc_spr_t *spr;
-    uint32_t pvr = env->spr[SPR_PVR];
-    uint32_t sr, sw, ur, uw;
+#if !defined(CONFIG_USER_ONLY)
+    uint32_t sr, sw;
+#endif
+    uint32_t ur, uw;
     int i, j, n;
 
-    printf("* SPRs for PVR=%08x\n", pvr);
+    printf("Special purpose registers:\n");
     for (i = 0; i < 32; i++) {
         for (j = 0; j < 32; j++) {
             n = (i << 5) | j;
             spr = &env->spr_cb[n];
+            uw = spr->uea_write != NULL && spr->uea_write != SPR_NOACCESS;
+            ur = spr->uea_read != NULL && spr->uea_read != SPR_NOACCESS;
 #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) {
-                printf("%4d (%03x) %8s s%c%c u%c%c\n",
+                printf("SPR: %4d (%03x) %-8s s%c%c u%c%c\n",
                        (i << 5) | j, (i << 5) | j, spr->name,
                        sw ? 'w' : '-', sr ? 'r' : '-',
                        uw ? 'w' : '-', ur ? 'r' : '-');
             }
+#else
+            if (uw || ur) {
+                printf("SPR: %4d (%03x) %-8s u%c%c\n",
+                       (i << 5) | j, (i << 5) | j, spr->name,
+                       uw ? 'w' : '-', ur ? 'r' : '-');
+            }
+#endif
         }
     }
     fflush(stdout);
@@ -2654,11 +6272,6 @@
     opcode_t *opc, *start, *end;
 
     fill_new_table(env->opcodes, 0x40);
-#if defined(PPC_DUMP_CPU)
-    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;
@@ -2674,25 +6287,6 @@
                        opc->opc3);
                 return -1;
             }
-#if defined(PPC_DUMP_CPU)
-            if (opc1 != 0x00) {
-                if (opc->opc3 == 0xFF) {
-                    if (opc->opc2 == 0xFF) {
-                        printf(" %02x -- -- (%2d ----) : %s\n",
-                               opc->opc1, opc->opc1, opc->oname);
-                    } else {
-                        printf(" %02x %02x -- (%2d %4d) : %s\n",
-                               opc->opc1, opc->opc2, opc->opc1, opc->opc2,
-                               opc->oname);
-                    }
-                } else {
-                    printf(" %02x %02x %02x (%2d %4d) : %s\n",
-                           opc->opc1, opc->opc2, opc->opc3,
-                           opc->opc1, (opc->opc3 << 5) | opc->opc2,
-                           opc->oname);
-                }
-            }
-#endif
         }
     }
     fix_opcode_tables(env->opcodes);
@@ -2702,1202 +6296,223 @@
     return 0;
 }
 
+#if defined(PPC_DUMP_CPU)
+static void dump_ppc_insns (CPUPPCState *env)
+{
+    opc_handler_t **table, *handler;
+    uint8_t opc1, opc2, opc3;
+
+    printf("Instructions set:\n");
+    /* opc1 is 6 bits long */
+    for (opc1 = 0x00; opc1 < 0x40; opc1++) {
+        table = env->opcodes;
+        handler = table[opc1];
+        if (is_indirect_opcode(handler)) {
+            /* opc2 is 5 bits long */
+            for (opc2 = 0; opc2 < 0x20; opc2++) {
+                table = env->opcodes;
+                handler = env->opcodes[opc1];
+                table = ind_table(handler);
+                handler = table[opc2];
+                if (is_indirect_opcode(handler)) {
+                    table = ind_table(handler);
+                    /* opc3 is 5 bits long */
+                    for (opc3 = 0; opc3 < 0x20; opc3++) {
+                        handler = table[opc3];
+                        if (handler->handler != &gen_invalid) {
+                            printf("INSN: %02x %02x %02x (%02d %04d) : %s\n",
+                                   opc1, opc2, opc3, opc1, (opc3 << 5) | opc2,
+                                   handler->oname);
+                        }
+                    }
+                } else {
+                    if (handler->handler != &gen_invalid) {
+                        printf("INSN: %02x %02x -- (%02d %04d) : %s\n",
+                               opc1, opc2, opc1, opc2, handler->oname);
+                    }
+                }
+            }
+        } else {
+            if (handler->handler != &gen_invalid) {
+                printf("INSN: %02x -- -- (%02d ----) : %s\n",
+                       opc1, opc1, handler->oname);
+            }
+        }
+    }
+}
+#endif
+
 int cpu_ppc_register (CPUPPCState *env, ppc_def_t *def)
 {
     env->msr_mask = def->msr_mask;
+    env->mmu_model = def->mmu_model;
+    env->excp_model = def->excp_model;
+    env->bus_model = def->bus_model;
     env->flags = def->flags;
+    env->bfd_mach = def->bfd_mach;
+    env->check_pow = def->check_pow;
     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
-
-    return 0;
-}
-
-/*****************************************************************************/
-/* PowerPC CPU definitions */
-static ppc_def_t ppc_defs[] = {
-    /* Embedded PowerPC */
-#if defined (TODO)
-    /* PowerPC 401 */
     {
-        .name        = "401",
-        .pvr         = CPU_PPC_401,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_401,
-        .flags       = PPC_FLAGS_401,
-        .msr_mask    = xxx,
-    },
+        const unsigned char *mmu_model, *excp_model, *bus_model;
+        switch (env->mmu_model) {
+        case POWERPC_MMU_32B:
+            mmu_model = "PowerPC 32";
+            break;
+        case POWERPC_MMU_SOFT_6xx:
+            mmu_model = "PowerPC 6xx/7xx with software driven TLBs";
+            break;
+        case POWERPC_MMU_SOFT_74xx:
+            mmu_model = "PowerPC 74xx with software driven TLBs";
+            break;
+        case POWERPC_MMU_SOFT_4xx:
+            mmu_model = "PowerPC 4xx with software driven TLBs";
+            break;
+        case POWERPC_MMU_SOFT_4xx_Z:
+            mmu_model = "PowerPC 4xx with software driven TLBs "
+                "and zones protections";
+            break;
+        case POWERPC_MMU_REAL_4xx:
+            mmu_model = "PowerPC 4xx real mode only";
+            break;
+        case POWERPC_MMU_BOOKE:
+            mmu_model = "PowerPC BookE";
+            break;
+        case POWERPC_MMU_BOOKE_FSL:
+            mmu_model = "PowerPC BookE FSL";
+            break;
+#if defined (TARGET_PPC64)
+        case POWERPC_MMU_64B:
+            mmu_model = "PowerPC 64";
+            break;
 #endif
-#if defined (TODO)
-    /* IOP480 (401 microcontroler) */
-    {
-        .name        = "iop480",
-        .pvr         = CPU_PPC_IOP480,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_401,
-        .flags       = PPC_FLAGS_401,
-        .msr_mask    = xxx,
-    },
+        default:
+            mmu_model = "Unknown or invalid";
+            break;
+        }
+        switch (env->excp_model) {
+        case POWERPC_EXCP_STD:
+            excp_model = "PowerPC";
+            break;
+        case POWERPC_EXCP_40x:
+            excp_model = "PowerPC 40x";
+            break;
+        case POWERPC_EXCP_601:
+            excp_model = "PowerPC 601";
+            break;
+        case POWERPC_EXCP_602:
+            excp_model = "PowerPC 602";
+            break;
+        case POWERPC_EXCP_603:
+            excp_model = "PowerPC 603";
+            break;
+        case POWERPC_EXCP_603E:
+            excp_model = "PowerPC 603e";
+            break;
+        case POWERPC_EXCP_604:
+            excp_model = "PowerPC 604";
+            break;
+        case POWERPC_EXCP_7x0:
+            excp_model = "PowerPC 740/750";
+            break;
+        case POWERPC_EXCP_7x5:
+            excp_model = "PowerPC 745/755";
+            break;
+        case POWERPC_EXCP_74xx:
+            excp_model = "PowerPC 74xx";
+            break;
+        case POWERPC_EXCP_BOOKE:
+            excp_model = "PowerPC BookE";
+            break;
+#if defined (TARGET_PPC64)
+        case POWERPC_EXCP_970:
+            excp_model = "PowerPC 970";
+            break;
 #endif
-#if defined (TODO)
-    /* 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,
-    },
+        default:
+            excp_model = "Unknown or invalid";
+            break;
+        }
+        switch (env->bus_model) {
+        case PPC_FLAGS_INPUT_6xx:
+            bus_model = "PowerPC 6xx";
+            break;
+        case PPC_FLAGS_INPUT_BookE:
+            bus_model = "PowerPC BookE";
+            break;
+        case PPC_FLAGS_INPUT_405:
+            bus_model = "PowerPC 405";
+            break;
+        case PPC_FLAGS_INPUT_401:
+            bus_model = "PowerPC 401/403";
+            break;
+#if defined (TARGET_PPC64)
+        case PPC_FLAGS_INPUT_970:
+            bus_model = "PowerPC 970";
+            break;
 #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,
-    },
+        default:
+            bus_model = "Unknown or invalid";
+            break;
+        }
+        printf("PowerPC %-12s : PVR %08x MSR %016" PRIx64 "\n"
+               "    MMU model        : %s\n",
+               def->name, def->pvr, def->msr_mask, mmu_model);
+#if !defined(CONFIG_USER_ONLY)
+        if (env->tlb != NULL) {
+            printf("                       %d %s TLB in %d ways\n",
+                   env->nb_tlb, env->id_tlbs ? "splitted" : "merged",
+                   env->nb_ways);
+        }
 #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    = 0x000000000007D23DULL,
-    },
-#endif
-#if defined (TODO)
-    /* PowerPC 403 GB */
-    {
-        .name        = "403gb",
-        .pvr         = CPU_PPC_403GB,
-        .pvr_mask    = 0xFFFFFF00,
-        .insns_flags = PPC_INSNS_403,
-        .flags       = PPC_FLAGS_403,
-        .msr_mask    = 0x000000000007D23DULL,
-    },
-#endif
-#if defined (TODO)
-    /* PowerPC 403 GC */
-    {
-        .name        = "403gc",
-        .pvr         = CPU_PPC_403GC,
-        .pvr_mask    = 0xFFFFFF00,
-        .insns_flags = PPC_INSNS_403,
-        .flags       = PPC_FLAGS_403,
-        .msr_mask    = 0x000000000007D23DULL,
-    },
-#endif
-#if defined (TODO)
-    /* PowerPC 403 GCX */
-    {
-        .name        = "403gcx",
-        .pvr         = CPU_PPC_403GCX,
-        .pvr_mask    = 0xFFFFFF00,
-        .insns_flags = PPC_INSNS_403,
-        .flags       = PPC_FLAGS_403,
-        .msr_mask    = 0x000000000007D23DULL,
-    },
-#endif
-    /* Generic PowerPC 405 */
-    {
-        .name        = "405",
-        .pvr         = CPU_PPC_405,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_405,
-        .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30ULL,
-    },
-    /* 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)
-    /* PowerPC 405 GP */
-    {
-        .name        = "405gp",
-        .pvr         = CPU_PPC_405,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_405,
-        .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30ULL,
-    },
-#endif
-    /* PowerPC 405 EP */
-    {
-        .name        = "405ep",
-        .pvr         = CPU_PPC_405EP,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_405,
-        .flags       = PPC_FLAGS_405,
-        .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)
-    /* PowerPC 405 GPR */
-    {
-        .name        = "405gpr",
-        .pvr         = CPU_PPC_405GPR,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_405,
-        .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30ULL,
-    },
-#endif
-    /* PowerPC 405 D2 */
-    {
-        .name        = "405d2",
-        .pvr         = CPU_PPC_405D2,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_405,
-        .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30ULL,
-    },
-    /* PowerPC 405 D4 */
-    {
-        .name        = "405d4",
-        .pvr         = CPU_PPC_405D4,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_405,
-        .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30ULL,
-    },
-#if defined (TODO)
-    /* Npe405 H */
-    {
-        .name        = "Npe405H",
-        .pvr         = CPU_PPC_NPE405H,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_405,
-        .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30ULL,
-    },
-#endif
-#if defined (TODO)
-    /* Npe405 L */
-    {
-        .name        = "Npe405L",
-        .pvr         = CPU_PPC_NPE405L,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_405,
-        .flags       = PPC_FLAGS_405,
-        .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    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_405,
-        .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30ULL,
-    },
-#endif
-#if defined (TODO)
-    /* STB043x */
-    {
-        .name        = "STB043",
-        .pvr         = CPU_PPC_STB043,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_405,
-        .flags       = PPC_FLAGS_405,
-        .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    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_405,
-        .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30ULL,
-    },
-#endif
-#if defined (TODO)
-    /* 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    = 0x000000000006D630ULL,
-    },
-#endif
-#if defined (TODO)
-    /* 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    = 0x000000000006D630ULL,
-    },
-#endif
-#if defined (TODO)
-    /* PowerPC 440 GX */
-    {
-        .name        = "440gx",
-        .pvr         = CPU_PPC_440GX,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_405,
-        .flags       = PPC_FLAGS_440,
-        .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 */
-#if defined (TODO)
-    /* PowerPC 601 */
-    {
-        .name        = "601",
-        .pvr         = CPU_PPC_601,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_601,
-        .flags       = PPC_FLAGS_601,
-        .msr_mask    = 0x000000000000FD70ULL,
-    },
-#endif
-#if defined (TODO)
-    /* PowerPC 602 */
-    {
-        .name        = "602",
-        .pvr         = CPU_PPC_602,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_602,
-        .flags       = PPC_FLAGS_602,
-        .msr_mask    = 0x0000000000C7FF73ULL,
-    },
-#endif
-    /* PowerPC 603 */
-    {
-        .name        = "603",
-        .pvr         = CPU_PPC_603,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_603,
-        .flags       = PPC_FLAGS_603,
-        .msr_mask    = 0x000000000007FF73ULL,
-    },
-    /* PowerPC 603e */
-    {
-        .name        = "603e",
-        .pvr         = CPU_PPC_603E,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_603,
-        .flags       = PPC_FLAGS_603,
-        .msr_mask    = 0x000000000007FF73ULL,
-    },
-    {
-        .name        = "Stretch",
-        .pvr         = CPU_PPC_603E,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_603,
-        .flags       = PPC_FLAGS_603,
-        .msr_mask    = 0x000000000007FF73ULL,
-    },
-    /* PowerPC 603p */
-    {
-        .name        = "603p",
-        .pvr         = CPU_PPC_603P,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_603,
-        .flags       = PPC_FLAGS_603,
-        .msr_mask    = 0x000000000007FF73ULL,
-    },
-    /* 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    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_603,
-        .flags       = PPC_FLAGS_603,
-        .msr_mask    = 0x000000000007FF73ULL,
-    },
-    {
-        .name        = "Goldeneye",
-        .pvr         = CPU_PPC_603R,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_603,
-        .flags       = PPC_FLAGS_603,
-        .msr_mask    = 0x000000000007FF73ULL,
-    },
-#if defined (TODO)
-    /* XXX: TODO: according to Motorola UM, this is a derivative to 603e */
-    {
-        .name        = "G2",
-        .pvr         = CPU_PPC_G2,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_G2,
-        .flags       = PPC_FLAGS_G2,
-        .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    = 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
-    /* PowerPC 604 */
-    {
-        .name        = "604",
-        .pvr         = CPU_PPC_604,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_604,
-        .flags       = PPC_FLAGS_604,
-        .msr_mask    = 0x000000000005FF77ULL,
-    },
-    /* PowerPC 604e */
-    {
-        .name        = "604e",
-        .pvr         = CPU_PPC_604E,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_604,
-        .flags       = PPC_FLAGS_604,
-        .msr_mask    = 0x000000000005FF77ULL,
-    },
-    /* PowerPC 604r */
-    {
-        .name        = "604r",
-        .pvr         = CPU_PPC_604R,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_604,
-        .flags       = PPC_FLAGS_604,
-        .msr_mask    = 0x000000000005FF77ULL,
-    },
-    /* generic G3 */
-    {
-        .name        = "G3",
-        .pvr         = CPU_PPC_74x,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_7x0,
-        .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-    /* MPC740 (G3) */
-    {
-        .name        = "740",
-        .pvr         = CPU_PPC_74x,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_7x0,
-        .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-    {
-        .name        = "Arthur",
-        .pvr         = CPU_PPC_74x,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_7x0,
-        .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-#if defined (TODO)
-    /* MPC745 (G3) */
-    {
-        .name        = "745",
-        .pvr         = CPU_PPC_74x,
-        .pvr_mask    = 0xFFFFF000,
-        .insns_flags = PPC_INSNS_7x5,
-        .flags       = PPC_FLAGS_7x5,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-    {
-        .name        = "Goldfinger",
-        .pvr         = CPU_PPC_74x,
-        .pvr_mask    = 0xFFFFF000,
-        .insns_flags = PPC_INSNS_7x5,
-        .flags       = PPC_FLAGS_7x5,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-#endif
-    /* MPC750 (G3) */
-    {
-        .name        = "750",
-        .pvr         = CPU_PPC_74x,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_7x0,
-        .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-#if defined (TODO)
-    /* MPC755 (G3) */
-    {
-        .name        = "755",
-        .pvr         = CPU_PPC_755,
-        .pvr_mask    = 0xFFFFF000,
-        .insns_flags = PPC_INSNS_7x5,
-        .flags       = PPC_FLAGS_7x5,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-#endif
-    /* MPC740P (G3) */
-    {
-        .name        = "740p",
-        .pvr         = CPU_PPC_74xP,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_7x0,
-        .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-    {
-        .name        = "Conan/Doyle",
-        .pvr         = CPU_PPC_74xP,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_7x0,
-        .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-#if defined (TODO)
-    /* MPC745P (G3) */
-    {
-        .name        = "745p",
-        .pvr         = CPU_PPC_74xP,
-        .pvr_mask    = 0xFFFFF000,
-        .insns_flags = PPC_INSNS_7x5,
-        .flags       = PPC_FLAGS_7x5,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-#endif
-    /* MPC750P (G3) */
-    {
-        .name        = "750p",
-        .pvr         = CPU_PPC_74xP,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_7x0,
-        .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-#if defined (TODO)
-    /* MPC755P (G3) */
-    {
-        .name        = "755p",
-        .pvr         = CPU_PPC_74xP,
-        .pvr_mask    = 0xFFFFF000,
-        .insns_flags = PPC_INSNS_7x5,
-        .flags       = PPC_FLAGS_7x5,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-#endif
-    /* IBM 750CXe (G3 embedded) */
-    {
-        .name        = "750cxe",
-        .pvr         = CPU_PPC_750CXE,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_7x0,
-        .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-    /* IBM 750FX (G3 embedded) */
-    {
-        .name        = "750fx",
-        .pvr         = CPU_PPC_750FX,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_7x0,
-        .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-    /* IBM 750GX (G3 embedded) */
-    {
-        .name        = "750gx",
-        .pvr         = CPU_PPC_750GX,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_7x0,
-        .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77ULL,
-    },
-#if defined (TODO)
-    /* generic G4 */
-    {
-        .name        = "G4",
-        .pvr         = CPU_PPC_7400,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_74xx,
-        .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77ULL,
-    },
-#endif
-#if defined (TODO)
-    /* PowerPC 7400 (G4) */
-    {
-        .name        = "7400",
-        .pvr         = CPU_PPC_7400,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_74xx,
-        .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77ULL,
-    },
-    {
-        .name        = "Max",
-        .pvr         = CPU_PPC_7400,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_74xx,
-        .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77ULL,
-    },
-#endif
-#if defined (TODO)
-    /* PowerPC 7410 (G4) */
-    {
-        .name        = "7410",
-        .pvr         = CPU_PPC_7410,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_74xx,
-        .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77ULL,
-    },
-    {
-        .name        = "Nitro",
-        .pvr         = CPU_PPC_7410,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_74xx,
-        .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77ULL,
-    },
-#endif
-    /* XXX: 7441 */
-    /* XXX: 7445 */
-    /* XXX: 7447 */
-    /* XXX: 7447A */
-#if defined (TODO)
-    /* PowerPC 7450 (G4) */
-    {
-        .name        = "7450",
-        .pvr         = CPU_PPC_7450,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_74xx,
-        .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77ULL,
-    },
-    {
-        .name        = "Vger",
-        .pvr         = CPU_PPC_7450,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_74xx,
-        .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77ULL,
-    },
-#endif
-    /* XXX: 7451 */
-#if defined (TODO)
-    /* PowerPC 7455 (G4) */
-    {
-        .name        = "7455",
-        .pvr         = CPU_PPC_7455,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_74xx,
-        .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77ULL,
-    },
-    {
-        .name        = "Apollo 6",
-        .pvr         = CPU_PPC_7455,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_74xx,
-        .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77ULL,
-    },
-#endif
-#if defined (TODO)
-    /* PowerPC 7457 (G4) */
-    {
-        .name        = "7457",
-        .pvr         = CPU_PPC_7457,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_74xx,
-        .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77ULL,
-    },
-    {
-        .name        = "Apollo 7",
-        .pvr         = CPU_PPC_7457,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_74xx,
-        .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77ULL,
-    },
-#endif
-#if defined (TODO)
-    /* PowerPC 7457A (G4) */
-    {
-        .name        = "7457A",
-        .pvr         = CPU_PPC_7457A,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_74xx,
-        .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77ULL,
-    },
-    {
-        .name        = "Apollo 7 PM",
-        .pvr         = CPU_PPC_7457A,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_74xx,
-        .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77ULL,
-    },
-#endif
-    /* 64 bits PowerPC */
-#if defined (TARGET_PPC64)
-#if defined (TODO)
-    /* PowerPC 620 */
-    {
-        .name        = "620",
-        .pvr         = CPU_PPC_620,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_620,
-        .flags       = PPC_FLAGS_620,
-        .msr_mask    = 0x800000000005FF73ULL,
-    },
-#endif
-#if defined (TODO)
-    /* PowerPC 630 (POWER3) */
-    {
-        .name        = "630",
-        .pvr         = CPU_PPC_630,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_630,
-        .flags       = PPC_FLAGS_630,
-        .msr_mask    = xxx,
+        printf("    Exceptions model : %s\n"
+               "    Bus model        : %s\n",
+               excp_model, bus_model);
+        printf("    MSR features     :\n");
+        if (env->flags & POWERPC_FLAG_SPE)
+            printf("                        signal processing engine enable"
+                   "\n");
+        else if (env->flags & POWERPC_FLAG_VRE)
+            printf("                        vector processor enable\n");
+        if (env->flags & POWERPC_FLAG_TGPR)
+            printf("                        temporary GPRs\n");
+        else if (env->flags & POWERPC_FLAG_CE)
+            printf("                        critical input enable\n");
+        if (env->flags & POWERPC_FLAG_SE)
+            printf("                        single-step trace mode\n");
+        else if (env->flags & POWERPC_FLAG_DWE)
+            printf("                        debug wait enable\n");
+        else if (env->flags & POWERPC_FLAG_UBLE)
+            printf("                        user BTB lock enable\n");
+        if (env->flags & POWERPC_FLAG_BE)
+            printf("                        branch-step trace mode\n");
+        else if (env->flags & POWERPC_FLAG_DE)
+            printf("                        debug interrupt enable\n");
+        if (env->flags & POWERPC_FLAG_PX)
+            printf("                        inclusive protection\n");
+        else if (env->flags & POWERPC_FLAG_PMM)
+            printf("                        performance monitor mark\n");
+        if (env->flags == POWERPC_FLAG_NONE)
+            printf("                        none\n");
     }
-    {
-        .name        = "POWER3",
-        .pvr         = CPU_PPC_630,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_630,
-        .flags       = PPC_FLAGS_630,
-        .msr_mask    = xxx,
-    }
+    dump_ppc_insns(env);
+    dump_ppc_sprs(env);
+    fflush(stdout);
 #endif
-#if defined (TODO)
-    /* PowerPC 631 (Power 3+)*/
-    {
-        .name        = "631",
-        .pvr         = CPU_PPC_631,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_631,
-        .flags       = PPC_FLAGS_631,
-        .msr_mask    = xxx,
-    },
-    {
-        .name        = "POWER3+",
-        .pvr         = CPU_PPC_631,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_631,
-        .flags       = PPC_FLAGS_631,
-        .msr_mask    = xxx,
-    },
-#endif
-#if defined (TODO)
-    /* POWER4 */
-    {
-        .name        = "POWER4",
-        .pvr         = CPU_PPC_POWER4,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_POWER4,
-        .flags       = PPC_FLAGS_POWER4,
-        .msr_mask    = xxx,
-    },
-#endif
-#if defined (TODO)
-    /* POWER4p */
-    {
-        .name        = "POWER4+",
-        .pvr         = CPU_PPC_POWER4P,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_POWER4,
-        .flags       = PPC_FLAGS_POWER4,
-        .msr_mask    = xxx,
-    },
-#endif
-#if defined (TODO)
-    /* POWER5 */
-    {
-        .name        = "POWER5",
-        .pvr         = CPU_PPC_POWER5,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_POWER5,
-        .flags       = PPC_FLAGS_POWER5,
-        .msr_mask    = xxx,
-    },
-#endif
-#if defined (TODO)
-    /* POWER5+ */
-    {
-        .name        = "POWER5+",
-        .pvr         = CPU_PPC_POWER5P,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_POWER5,
-        .flags       = PPC_FLAGS_POWER5,
-        .msr_mask    = xxx,
-    },
-#endif
-#if defined (TODO)
-    /* PowerPC 970 */
-    {
-        .name        = "970",
-        .pvr         = CPU_PPC_970,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_970,
-        .flags       = PPC_FLAGS_970,
-        .msr_mask    = 0x900000000204FF36ULL,
-    },
-#endif
-#if defined (TODO)
-    /* PowerPC 970FX (G5) */
-    {
-        .name        = "970fx",
-        .pvr         = CPU_PPC_970FX,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_970FX,
-        .flags       = PPC_FLAGS_970FX,
-        .msr_mask    = 0x800000000204FF36ULL,
-    },
-#endif
-#if defined (TODO)
-    /* RS64 (Apache/A35) */
-    /* This one seems to support the whole POWER2 instruction set
-     * and the PowerPC 64 one.
-     */
-    {
-        .name        = "RS64",
-        .pvr         = CPU_PPC_RS64,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_RS64,
-        .flags       = PPC_FLAGS_RS64,
-        .msr_mask    = xxx,
-    },
-    {
-        .name        = "Apache",
-        .pvr         = CPU_PPC_RS64,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_RS64,
-        .flags       = PPC_FLAGS_RS64,
-        .msr_mask    = xxx,
-    },
-    {
-        .name        = "A35",
-        .pvr         = CPU_PPC_RS64,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_RS64,
-        .flags       = PPC_FLAGS_RS64,
-        .msr_mask    = xxx,
-    },
-#endif
-#if defined (TODO)
-    /* RS64-II (NorthStar/A50) */
-    {
-        .name        = "RS64-II",
-        .pvr         = CPU_PPC_RS64II,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_RS64,
-        .flags       = PPC_FLAGS_RS64,
-        .msr_mask    = xxx,
-    },
-    {
-        .name        = "NortStar",
-        .pvr         = CPU_PPC_RS64II,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_RS64,
-        .flags       = PPC_FLAGS_RS64,
-        .msr_mask    = xxx,
-    },
-    {
-        .name        = "A50",
-        .pvr         = CPU_PPC_RS64II,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_RS64,
-        .flags       = PPC_FLAGS_RS64,
-        .msr_mask    = xxx,
-    },
-#endif
-#if defined (TODO)
-    /* RS64-III (Pulsar) */
-    {
-        .name        = "RS64-III",
-        .pvr         = CPU_PPC_RS64III,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_RS64,
-        .flags       = PPC_FLAGS_RS64,
-        .msr_mask    = xxx,
-    },
-    {
-        .name        = "Pulsar",
-        .pvr         = CPU_PPC_RS64III,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_RS64,
-        .flags       = PPC_FLAGS_RS64,
-        .msr_mask    = xxx,
-    },
-#endif
-#if defined (TODO)
-    /* RS64-IV (IceStar/IStar/SStar) */
-    {
-        .name        = "RS64-IV",
-        .pvr         = CPU_PPC_RS64IV,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_RS64,
-        .flags       = PPC_FLAGS_RS64,
-        .msr_mask    = xxx,
-    },
-    {
-        .name        = "IceStar",
-        .pvr         = CPU_PPC_RS64IV,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_RS64,
-        .flags       = PPC_FLAGS_RS64,
-        .msr_mask    = xxx,
-    },
-    {
-        .name        = "IStar",
-        .pvr         = CPU_PPC_RS64IV,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_RS64,
-        .flags       = PPC_FLAGS_RS64,
-        .msr_mask    = xxx,
-    },
-    {
-        .name        = "SStar",
-        .pvr         = CPU_PPC_RS64IV,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_RS64,
-        .flags       = PPC_FLAGS_RS64,
-        .msr_mask    = xxx,
-    },
-#endif
-    /* POWER */
-#if defined (TODO)
-    /* Original POWER */
-    {
-        .name        = "POWER",
-        .pvr         = CPU_POWER,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_POWER,
-        .flags       = PPC_FLAGS_POWER,
-        .msr_mask    = xxx,
-    },
-#endif
-#endif /* defined (TARGET_PPC64) */
-#if defined (TODO)
-    /* POWER2 */
-    {
-        .name        = "POWER2",
-        .pvr         = CPU_POWER2,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_POWER,
-        .flags       = PPC_FLAGS_POWER,
-        .msr_mask    = xxx,
-    },
-#endif
-    /* Generic PowerPCs */
-#if defined (TODO)
-    {
-        .name        = "ppc64",
-        .pvr         = CPU_PPC_970,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_PPC64,
-        .flags       = PPC_FLAGS_PPC64,
-        .msr_mask    = 0xA00000000204FF36ULL,
-    },
-#endif
-    {
-        .name        = "ppc32",
-        .pvr         = CPU_PPC_604,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_PPC32,
-        .flags       = PPC_FLAGS_PPC32,
-        .msr_mask    = 0x000000000005FF77ULL,
-    },
-    /* Fallback */
-    {
-        .name        = "ppc",
-        .pvr         = CPU_PPC_604,
-        .pvr_mask    = 0xFFFFFFFF,
-        .insns_flags = PPC_INSNS_PPC32,
-        .flags       = PPC_FLAGS_PPC32,
-        .msr_mask    = 0x000000000005FF77ULL,
-    },
-};
 
+    return 0;
+}
+
 int ppc_find_by_name (const unsigned char *name, ppc_def_t **def)
 {
-    int i, ret;
+    int i, max, ret;
 
     ret = -1;
     *def = NULL;
-    for (i = 0; strcmp(ppc_defs[i].name, "ppc") != 0; i++) {
+    max = sizeof(ppc_defs) / sizeof(ppc_def_t);
+    for (i = 0; i < max; i++) {
         if (strcasecmp(name, ppc_defs[i].name) == 0) {
             *def = &ppc_defs[i];
             ret = 0;
@@ -3910,11 +6525,12 @@
 
 int ppc_find_by_pvr (uint32_t pvr, ppc_def_t **def)
 {
-    int i, ret;
+    int i, max, ret;
 
     ret = -1;
     *def = NULL;
-    for (i = 0; ppc_defs[i].name != NULL; i++) {
+    max = sizeof(ppc_defs) / sizeof(ppc_def_t);
+    for (i = 0; i < max; i++) {
         if ((pvr & ppc_defs[i].pvr_mask) ==
             (ppc_defs[i].pvr & ppc_defs[i].pvr_mask)) {
             *def = &ppc_defs[i];
@@ -3928,13 +6544,11 @@
 
 void ppc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
 {
-    int i;
+    int i, max;
 
-    for (i = 0; ; i++) {
-        (*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)
-            break;
+    max = sizeof(ppc_defs) / sizeof(ppc_def_t);
+    for (i = 0; i < max; i++) {
+        (*cpu_fprintf)(f, "PowerPC %-16s PVR %08x\n",
+                       ppc_defs[i].name, ppc_defs[i].pvr);
     }
 }

Modified: trunk/src/host/qemu-neo1973/target-sh4/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-sh4/cpu.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-sh4/cpu.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -77,6 +77,8 @@
 #define UTLB_SIZE 64
 #define ITLB_SIZE 4
 
+#define NB_MMU_MODES 2
+
 typedef struct CPUSH4State {
     uint32_t flags;		/* general execution flags */
     uint32_t gregs[24];		/* general registers */
@@ -134,6 +136,15 @@
 #define cpu_gen_code cpu_sh4_gen_code
 #define cpu_signal_handler cpu_sh4_signal_handler
 
+/* MMU modes definitions */
+#define MMU_MODE0_SUFFIX _kernel
+#define MMU_MODE1_SUFFIX _user
+#define MMU_USER_IDX 1
+static inline int cpu_mmu_index (CPUState *env)
+{
+    return (env->sr & SR_MD) == 0 ? 1 : 0;
+}
+
 #include "cpu-all.h"
 
 /* Memory access type */

Modified: trunk/src/host/qemu-neo1973/target-sh4/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-sh4/exec.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-sh4/exec.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -63,7 +63,7 @@
 }
 
 int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
-			     int is_user, int is_softmmu);
+			     int mmu_idx, int is_softmmu);
 
 int find_itlb_entry(CPUState * env, target_ulong address,
 		    int use_asid, int update);

Modified: trunk/src/host/qemu-neo1973/target-sh4/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sh4/helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-sh4/helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -36,7 +36,7 @@
 }
 
 int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
-			     int is_user, int is_softmmu)
+			     int mmu_idx, int is_softmmu)
 {
     env->tea = address;
     switch (rw) {
@@ -372,15 +372,15 @@
 }
 
 int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
-			     int is_user, int is_softmmu)
+			     int mmu_idx, int is_softmmu)
 {
     target_ulong physical, page_offset, page_size;
     int prot, ret, access_type;
 
     /* XXXXX */
 #if 0
-    fprintf(stderr, "%s pc %08x ad %08x rw %d is_user %d smmu %d\n",
-	    __func__, env->pc, address, rw, is_user, is_softmmu);
+    fprintf(stderr, "%s pc %08x ad %08x rw %d mmu_idx %d smmu %d\n",
+	    __func__, env->pc, address, rw, mmu_idx, is_softmmu);
 #endif
 
     access_type = ACCESS_INT;
@@ -426,7 +426,7 @@
     address = (address & TARGET_PAGE_MASK) + page_offset;
     physical = (physical & TARGET_PAGE_MASK) + page_offset;
 
-    return tlb_set_page(env, address, physical, prot, is_user, is_softmmu);
+    return tlb_set_page(env, address, physical, prot, mmu_idx, is_softmmu);
 }
 
 target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)

Modified: trunk/src/host/qemu-neo1973/target-sh4/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sh4/op_helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-sh4/op_helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -28,7 +28,11 @@
 #ifndef CONFIG_USER_ONLY
 
 #define MMUSUFFIX _mmu
-#define GETPC() (__builtin_return_address(0))
+#ifdef __s390__
+# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
+#else
+# define GETPC() (__builtin_return_address(0))
+#endif
 
 #define SHIFT 0
 #include "softmmu_template.h"
@@ -42,7 +46,7 @@
 #define SHIFT 3
 #include "softmmu_template.h"
 
-void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
+void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 {
     TranslationBlock *tb;
     CPUState *saved_env;
@@ -53,7 +57,7 @@
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, is_user, 1);
+    ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
     if (ret) {
 	if (retaddr) {
 	    /* now we have a real cpu fault */

Modified: trunk/src/host/qemu-neo1973/target-sh4/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sh4/translate.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-sh4/translate.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -277,7 +277,7 @@
     case 0x0038:		/* ldtlb */
 	assert(0);		/* XXXXX */
 	return;
-    case 0x004b:		/* rte */
+    case 0x002b:		/* rte */
 	CHECK_NOT_DELAY_SLOT gen_op_rte();
 	ctx->flags |= DELAY_SLOT;
 	ctx->delayed_pc = (uint32_t) - 1;

Modified: trunk/src/host/qemu-neo1973/target-sparc/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/cpu.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-sparc/cpu.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -22,9 +22,9 @@
 #define TARGET_HAS_ICE 1
 
 #if !defined(TARGET_SPARC64)
-#define ELF_MACHINE	EM_SPARC
+#define ELF_MACHINE     EM_SPARC
 #else
-#define ELF_MACHINE	EM_SPARCV9
+#define ELF_MACHINE     EM_SPARCV9
 #endif
 
 /*#define EXCP_INTERRUPT 0x100*/
@@ -98,6 +98,8 @@
 #define PS_AG    (1<<0)
 
 #define FPRS_FEF (1<<2)
+
+#define HS_PRIV  (1<<2)
 #endif
 
 /* Fcc */
@@ -143,8 +145,9 @@
 #define FSR_FCC0  (1<<10)
 
 /* MMU */
-#define MMU_E	  (1<<0)
-#define MMU_NF	  (1<<1)
+#define MMU_E     (1<<0)
+#define MMU_NF    (1<<1)
+#define MMU_BM    (1<<14)
 
 #define PTE_ENTRYTYPE_MASK 3
 #define PTE_ACCESS_MASK    0x1c
@@ -152,8 +155,8 @@
 #define PTE_PPN_SHIFT      7
 #define PTE_ADDR_MASK      0xffffff00
 
-#define PG_ACCESSED_BIT	5
-#define PG_MODIFIED_BIT	6
+#define PG_ACCESSED_BIT 5
+#define PG_MODIFIED_BIT 6
 #define PG_CACHE_BIT    7
 
 #define PG_ACCESSED_MASK (1 << PG_ACCESSED_BIT)
@@ -165,6 +168,12 @@
 
 typedef struct sparc_def_t sparc_def_t;
 
+#if !defined(TARGET_SPARC64)
+#define NB_MMU_MODES 2
+#else
+#define NB_MMU_MODES 3
+#endif
+
 typedef struct CPUSPARCState {
     target_ulong gregs[8]; /* general registers */
     target_ulong *regwptr; /* pointer to current register window */
@@ -209,6 +218,8 @@
     uint64_t dtlb_tte[64];
 #else
     uint32_t mmuregs[16];
+    uint64_t mxccdata[4];
+    uint64_t mxccregs[8];
 #endif
     /* temporary float registers */
     float32 ft0, ft1;
@@ -221,7 +232,7 @@
     uint64_t tnpc[MAXTL];
     uint64_t tstate[MAXTL];
     uint32_t tt[MAXTL];
-    uint32_t xcc;		/* Extended integer condition codes */
+    uint32_t xcc;               /* Extended integer condition codes */
     uint32_t asi;
     uint32_t pstate;
     uint32_t tl;
@@ -245,12 +256,12 @@
 } CPUSPARCState;
 #if defined(TARGET_SPARC64)
 #define GET_FSR32(env) (env->fsr & 0xcfc1ffff)
-#define PUT_FSR32(env, val) do { uint32_t _tmp = val;			\
-	env->fsr = (_tmp & 0xcfc1c3ff) | (env->fsr & 0x3f00000000ULL);	\
+#define PUT_FSR32(env, val) do { uint32_t _tmp = val;                   \
+        env->fsr = (_tmp & 0xcfc1c3ff) | (env->fsr & 0x3f00000000ULL);  \
     } while (0)
 #define GET_FSR64(env) (env->fsr & 0x3fcfc1ffffULL)
-#define PUT_FSR64(env, val) do { uint64_t _tmp = val;	\
-	env->fsr = _tmp & 0x3fcfc1c3ffULL;		\
+#define PUT_FSR64(env, val) do { uint64_t _tmp = val;   \
+        env->fsr = _tmp & 0x3fcfc1c3ffULL;              \
     } while (0)
 #else
 #define GET_FSR32(env) (env->fsr)
@@ -265,34 +276,35 @@
 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);
+int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def,
+                        unsigned int cpu);
 
 #define GET_PSR(env) (env->version | (env->psr & PSR_ICC) |             \
-		      (env->psref? PSR_EF : 0) |			\
-		      (env->psrpil << 8) |				\
-		      (env->psrs? PSR_S : 0) |				\
-		      (env->psrps? PSR_PS : 0) |			\
-		      (env->psret? PSR_ET : 0) | env->cwp)
+                      (env->psref? PSR_EF : 0) |                        \
+                      (env->psrpil << 8) |                              \
+                      (env->psrs? PSR_S : 0) |                          \
+                      (env->psrps? PSR_PS : 0) |                        \
+                      (env->psret? PSR_ET : 0) | env->cwp)
 
 #ifndef NO_CPU_IO_DEFS
 void cpu_set_cwp(CPUSPARCState *env1, int new_cwp);
 #endif
 
-#define PUT_PSR(env, val) do { int _tmp = val;				\
-	env->psr = _tmp & PSR_ICC;					\
-	env->psref = (_tmp & PSR_EF)? 1 : 0;				\
-	env->psrpil = (_tmp & PSR_PIL) >> 8;				\
-	env->psrs = (_tmp & PSR_S)? 1 : 0;				\
-	env->psrps = (_tmp & PSR_PS)? 1 : 0;				\
-	env->psret = (_tmp & PSR_ET)? 1 : 0;				\
+#define PUT_PSR(env, val) do { int _tmp = val;                          \
+        env->psr = _tmp & PSR_ICC;                                      \
+        env->psref = (_tmp & PSR_EF)? 1 : 0;                            \
+        env->psrpil = (_tmp & PSR_PIL) >> 8;                            \
+        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);                               \
     } while (0)
 
 #ifdef TARGET_SPARC64
 #define GET_CCR(env) (((env->xcc >> 20) << 4) | ((env->psr & PSR_ICC) >> 20))
-#define PUT_CCR(env, val) do { int _tmp = val;				\
-	env->xcc = (_tmp >> 4) << 20;						\
-	env->psr = (_tmp & 0xf) << 20;					\
+#define PUT_CCR(env, val) do { int _tmp = val;                          \
+        env->xcc = (_tmp >> 4) << 20;                                           \
+        env->psr = (_tmp & 0xf) << 20;                                  \
     } while (0)
 #define GET_CWP64(env) (NWINDOWS - 1 - (env)->cwp)
 #define PUT_CWP64(env, val) \
@@ -314,7 +326,42 @@
 #define cpu_exec cpu_sparc_exec
 #define cpu_gen_code cpu_sparc_gen_code
 #define cpu_signal_handler cpu_sparc_signal_handler
+#define cpu_list sparc_cpu_list
 
+/* MMU modes definitions */
+#define MMU_MODE0_SUFFIX _user
+#define MMU_MODE1_SUFFIX _kernel
+#ifdef TARGET_SPARC64
+#define MMU_MODE2_SUFFIX _hypv
+#endif
+#define MMU_USER_IDX 0
+static inline int cpu_mmu_index (CPUState *env)
+{
+#if defined(CONFIG_USER_ONLY)
+    return 0;
+#elif !defined(TARGET_SPARC64)
+    return env->psrs;
+#else
+    if (!env->psrs)
+        return 0;
+    else if ((env->hpstate & HS_PRIV) == 0)
+        return 1;
+    else
+        return 2;
+#endif
+}
+
+static inline int cpu_fpu_enabled(CPUState *env)
+{
+#if defined(CONFIG_USER_ONLY)
+    return 1;
+#elif !defined(TARGET_SPARC64)
+    return env->psref;
+#else
+    return ((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0);
+#endif
+}
+
 #include "cpu-all.h"
 
 #endif

Modified: trunk/src/host/qemu-neo1973/target-sparc/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/exec.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-sparc/exec.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -50,7 +50,9 @@
 void cpu_loop_exit(void);
 void helper_flush(target_ulong addr);
 void helper_ld_asi(int asi, int size, int sign);
-void helper_st_asi(int asi, int size, int sign);
+void helper_st_asi(int asi, int size);
+void helper_ldf_asi(int asi, int size, int rd);
+void helper_stf_asi(int asi, int size, int rd);
 void helper_rett(void);
 void helper_ldfsr(void);
 void set_cwp(int new_cwp);
@@ -113,7 +115,7 @@
 }
 
 int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
-                               int is_user, int is_softmmu);
+                               int mmu_idx, int is_softmmu);
 
 static inline int cpu_halted(CPUState *env) {
     if (!env->halted)

Modified: trunk/src/host/qemu-neo1973/target-sparc/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-sparc/helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -49,7 +49,7 @@
 #if defined(CONFIG_USER_ONLY)
 
 int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
-                               int is_user, int is_softmmu)
+                               int mmu_idx, int is_softmmu)
 {
     if (rw & 2)
         env->exception_index = TT_TFAULT;
@@ -99,19 +99,27 @@
 };
 
 int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
-			  int *access_index, target_ulong address, int rw,
-			  int is_user)
+                          int *access_index, target_ulong address, int rw,
+                          int mmu_idx)
 {
     int access_perms = 0;
     target_phys_addr_t pde_ptr;
     uint32_t pde;
     target_ulong virt_addr;
-    int error_code = 0, is_dirty;
+    int error_code = 0, is_dirty, is_user;
     unsigned long page_offset;
 
+    is_user = mmu_idx == MMU_USER_IDX;
     virt_addr = address & TARGET_PAGE_MASK;
+
     if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
-	*physical = address;
+        // Boot mode: instruction fetches are taken from PROM
+        if (rw == 2 && (env->mmuregs[0] & MMU_BM)) {
+            *physical = 0xff0000000ULL | (address & 0x3ffffULL);
+            *prot = PAGE_READ | PAGE_EXEC;
+            return 0;
+        }
+        *physical = address;
         *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
         return 0;
     }
@@ -128,70 +136,70 @@
     switch (pde & PTE_ENTRYTYPE_MASK) {
     default:
     case 0: /* Invalid */
-	return 1 << 2;
+        return 1 << 2;
     case 2: /* L0 PTE, maybe should not happen? */
     case 3: /* Reserved */
         return 4 << 2;
     case 1: /* L0 PDE */
-	pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
+        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
         pde = ldl_phys(pde_ptr);
 
-	switch (pde & PTE_ENTRYTYPE_MASK) {
-	default:
-	case 0: /* Invalid */
-	    return (1 << 8) | (1 << 2);
-	case 3: /* Reserved */
-	    return (1 << 8) | (4 << 2);
-	case 1: /* L1 PDE */
-	    pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
+        switch (pde & PTE_ENTRYTYPE_MASK) {
+        default:
+        case 0: /* Invalid */
+            return (1 << 8) | (1 << 2);
+        case 3: /* Reserved */
+            return (1 << 8) | (4 << 2);
+        case 1: /* L1 PDE */
+            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
             pde = ldl_phys(pde_ptr);
 
-	    switch (pde & PTE_ENTRYTYPE_MASK) {
-	    default:
-	    case 0: /* Invalid */
-		return (2 << 8) | (1 << 2);
-	    case 3: /* Reserved */
-		return (2 << 8) | (4 << 2);
-	    case 1: /* L2 PDE */
-		pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
+            switch (pde & PTE_ENTRYTYPE_MASK) {
+            default:
+            case 0: /* Invalid */
+                return (2 << 8) | (1 << 2);
+            case 3: /* Reserved */
+                return (2 << 8) | (4 << 2);
+            case 1: /* L2 PDE */
+                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
                 pde = ldl_phys(pde_ptr);
 
-		switch (pde & PTE_ENTRYTYPE_MASK) {
-		default:
-		case 0: /* Invalid */
-		    return (3 << 8) | (1 << 2);
-		case 1: /* PDE, should not happen */
-		case 3: /* Reserved */
-		    return (3 << 8) | (4 << 2);
-		case 2: /* L3 PTE */
-		    virt_addr = address & TARGET_PAGE_MASK;
-		    page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
-		}
-		break;
-	    case 2: /* L2 PTE */
-		virt_addr = address & ~0x3ffff;
-		page_offset = address & 0x3ffff;
-	    }
-	    break;
-	case 2: /* L1 PTE */
-	    virt_addr = address & ~0xffffff;
-	    page_offset = address & 0xffffff;
-	}
+                switch (pde & PTE_ENTRYTYPE_MASK) {
+                default:
+                case 0: /* Invalid */
+                    return (3 << 8) | (1 << 2);
+                case 1: /* PDE, should not happen */
+                case 3: /* Reserved */
+                    return (3 << 8) | (4 << 2);
+                case 2: /* L3 PTE */
+                    virt_addr = address & TARGET_PAGE_MASK;
+                    page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
+                }
+                break;
+            case 2: /* L2 PTE */
+                virt_addr = address & ~0x3ffff;
+                page_offset = address & 0x3ffff;
+            }
+            break;
+        case 2: /* L1 PTE */
+            virt_addr = address & ~0xffffff;
+            page_offset = address & 0xffffff;
+        }
     }
 
     /* update page modified and dirty bits */
     is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
     if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
-	pde |= PG_ACCESSED_MASK;
-	if (is_dirty)
-	    pde |= PG_MODIFIED_MASK;
+        pde |= PG_ACCESSED_MASK;
+        if (is_dirty)
+            pde |= PG_MODIFIED_MASK;
         stl_phys_notdirty(pde_ptr, pde);
     }
     /* check access */
     access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
     error_code = access_table[*access_index][access_perms];
     if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
-	return error_code;
+        return error_code;
 
     /* the page can be put in the TLB */
     *prot = perm_table[is_user][access_perms];
@@ -209,26 +217,26 @@
 
 /* Perform address translation */
 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                              int is_user, int is_softmmu)
+                              int mmu_idx, int is_softmmu)
 {
     target_phys_addr_t paddr;
     target_ulong vaddr;
     int error_code = 0, prot, ret = 0, access_index;
 
-    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
+    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, mmu_idx);
     if (error_code == 0) {
-	vaddr = address & TARGET_PAGE_MASK;
-	paddr &= TARGET_PAGE_MASK;
+        vaddr = address & TARGET_PAGE_MASK;
+        paddr &= TARGET_PAGE_MASK;
 #ifdef DEBUG_MMU
-	printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
+        printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
                TARGET_FMT_lx "\n", address, paddr, vaddr);
 #endif
-	ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
-	return ret;
+        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
+        return ret;
     }
 
     if (env->mmuregs[3]) /* Fault status register */
-	env->mmuregs[3] = 1; /* overflow (not read before another fault) */
+        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
     env->mmuregs[3] |= (access_index << 5) | error_code | 2;
     env->mmuregs[4] = address; /* Fault address register */
 
@@ -237,10 +245,10 @@
         // permissions. If no mapping is available, redirect accesses to
         // neverland. Fake/overridden mappings will be flushed when
         // switching to normal mode.
-	vaddr = address & TARGET_PAGE_MASK;
+        vaddr = address & TARGET_PAGE_MASK;
         prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-        ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
-	return ret;
+        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
+        return ret;
     } else {
         if (rw & 2)
             env->exception_index = TT_TFAULT;
@@ -265,50 +273,50 @@
     case 0: /* Invalid */
     case 2: /* PTE, maybe should not happen? */
     case 3: /* Reserved */
-	return 0;
+        return 0;
     case 1: /* L1 PDE */
-	if (mmulev == 3)
-	    return pde;
-	pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
+        if (mmulev == 3)
+            return pde;
+        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
         pde = ldl_phys(pde_ptr);
 
-	switch (pde & PTE_ENTRYTYPE_MASK) {
-	default:
-	case 0: /* Invalid */
-	case 3: /* Reserved */
-	    return 0;
-	case 2: /* L1 PTE */
-	    return pde;
-	case 1: /* L2 PDE */
-	    if (mmulev == 2)
-		return pde;
-	    pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
+        switch (pde & PTE_ENTRYTYPE_MASK) {
+        default:
+        case 0: /* Invalid */
+        case 3: /* Reserved */
+            return 0;
+        case 2: /* L1 PTE */
+            return pde;
+        case 1: /* L2 PDE */
+            if (mmulev == 2)
+                return pde;
+            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
             pde = ldl_phys(pde_ptr);
 
-	    switch (pde & PTE_ENTRYTYPE_MASK) {
-	    default:
-	    case 0: /* Invalid */
-	    case 3: /* Reserved */
-		return 0;
-	    case 2: /* L2 PTE */
-		return pde;
-	    case 1: /* L3 PDE */
-		if (mmulev == 1)
-		    return pde;
-		pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
+            switch (pde & PTE_ENTRYTYPE_MASK) {
+            default:
+            case 0: /* Invalid */
+            case 3: /* Reserved */
+                return 0;
+            case 2: /* L2 PTE */
+                return pde;
+            case 1: /* L3 PDE */
+                if (mmulev == 1)
+                    return pde;
+                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
                 pde = ldl_phys(pde_ptr);
 
-		switch (pde & PTE_ENTRYTYPE_MASK) {
-		default:
-		case 0: /* Invalid */
-		case 1: /* PDE, should not happen */
-		case 3: /* Reserved */
-		    return 0;
-		case 2: /* L3 PTE */
-		    return pde;
-		}
-	    }
-	}
+                switch (pde & PTE_ENTRYTYPE_MASK) {
+                default:
+                case 0: /* Invalid */
+                case 1: /* PDE, should not happen */
+                case 3: /* Reserved */
+                    return 0;
+                case 2: /* L3 PTE */
+                    return pde;
+                }
+            }
+        }
     }
     return 0;
 }
@@ -327,29 +335,29 @@
     printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
            (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
     for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
-	pde = mmu_probe(env, va, 2);
-	if (pde) {
-	    pa = cpu_get_phys_page_debug(env, va);
- 	    printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
+        pde = mmu_probe(env, va, 2);
+        if (pde) {
+            pa = cpu_get_phys_page_debug(env, va);
+            printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
                    " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
-	    for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
-		pde = mmu_probe(env, va1, 1);
-		if (pde) {
-		    pa = cpu_get_phys_page_debug(env, va1);
- 		    printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
+            for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
+                pde = mmu_probe(env, va1, 1);
+                if (pde) {
+                    pa = cpu_get_phys_page_debug(env, va1);
+                    printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
                            " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
-		    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
-			pde = mmu_probe(env, va2, 0);
-			if (pde) {
-			    pa = cpu_get_phys_page_debug(env, va2);
- 			    printf("  VA: " TARGET_FMT_lx ", PA: "
+                    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
+                        pde = mmu_probe(env, va2, 0);
+                        if (pde) {
+                            pa = cpu_get_phys_page_debug(env, va2);
+                            printf("  VA: " TARGET_FMT_lx ", PA: "
                                    TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
                                    va2, pa, pde);
-			}
-		    }
-		}
-	    }
-	}
+                        }
+                    }
+                }
+            }
+        }
     }
     printf("MMU dump ends\n");
 }
@@ -360,57 +368,57 @@
  * UltraSparc IIi I/DMMUs
  */
 static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot,
-			  int *access_index, target_ulong address, int rw,
-			  int is_user)
+                          int *access_index, target_ulong address, int rw,
+                          int is_user)
 {
     target_ulong mask;
     unsigned int i;
 
     if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
-	*physical = address;
-	*prot = PAGE_READ | PAGE_WRITE;
+        *physical = address;
+        *prot = PAGE_READ | PAGE_WRITE;
         return 0;
     }
 
     for (i = 0; i < 64; i++) {
-	switch ((env->dtlb_tte[i] >> 61) & 3) {
-	default:
-	case 0x0: // 8k
-	    mask = 0xffffffffffffe000ULL;
-	    break;
-	case 0x1: // 64k
-	    mask = 0xffffffffffff0000ULL;
-	    break;
-	case 0x2: // 512k
-	    mask = 0xfffffffffff80000ULL;
-	    break;
-	case 0x3: // 4M
-	    mask = 0xffffffffffc00000ULL;
-	    break;
-	}
-	// ctx match, vaddr match?
-	if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
-	    (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
-	    // valid, access ok?
-	    if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
-		((env->dtlb_tte[i] & 0x4) && is_user) ||
-		(!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
-		if (env->dmmuregs[3]) /* Fault status register */
-		    env->dmmuregs[3] = 2; /* overflow (not read before another fault) */
-		env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
-		env->dmmuregs[4] = address; /* Fault address register */
-		env->exception_index = TT_DFAULT;
+        switch ((env->dtlb_tte[i] >> 61) & 3) {
+        default:
+        case 0x0: // 8k
+            mask = 0xffffffffffffe000ULL;
+            break;
+        case 0x1: // 64k
+            mask = 0xffffffffffff0000ULL;
+            break;
+        case 0x2: // 512k
+            mask = 0xfffffffffff80000ULL;
+            break;
+        case 0x3: // 4M
+            mask = 0xffffffffffc00000ULL;
+            break;
+        }
+        // ctx match, vaddr match?
+        if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
+            (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
+            // valid, access ok?
+            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
+                ((env->dtlb_tte[i] & 0x4) && is_user) ||
+                (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
+                if (env->dmmuregs[3]) /* Fault status register */
+                    env->dmmuregs[3] = 2; /* overflow (not read before another fault) */
+                env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
+                env->dmmuregs[4] = address; /* Fault address register */
+                env->exception_index = TT_DFAULT;
 #ifdef DEBUG_MMU
-		printf("DFAULT at 0x%" PRIx64 "\n", address);
+                printf("DFAULT at 0x%" PRIx64 "\n", address);
 #endif
-		return 1;
-	    }
-	    *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
-	    *prot = PAGE_READ;
-	    if (env->dtlb_tte[i] & 0x2)
-		*prot |= PAGE_WRITE;
-	    return 0;
-	}
+                return 1;
+            }
+            *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
+            *prot = PAGE_READ;
+            if (env->dtlb_tte[i] & 0x2)
+                *prot |= PAGE_WRITE;
+            return 0;
+        }
     }
 #ifdef DEBUG_MMU
     printf("DMISS at 0x%" PRIx64 "\n", address);
@@ -420,53 +428,53 @@
 }
 
 static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical, int *prot,
-			  int *access_index, target_ulong address, int rw,
-			  int is_user)
+                          int *access_index, target_ulong address, int rw,
+                          int is_user)
 {
     target_ulong mask;
     unsigned int i;
 
     if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
-	*physical = address;
-	*prot = PAGE_EXEC;
+        *physical = address;
+        *prot = PAGE_EXEC;
         return 0;
     }
 
     for (i = 0; i < 64; i++) {
-	switch ((env->itlb_tte[i] >> 61) & 3) {
-	default:
-	case 0x0: // 8k
-	    mask = 0xffffffffffffe000ULL;
-	    break;
-	case 0x1: // 64k
-	    mask = 0xffffffffffff0000ULL;
-	    break;
-	case 0x2: // 512k
-	    mask = 0xfffffffffff80000ULL;
-	    break;
-	case 0x3: // 4M
-	    mask = 0xffffffffffc00000ULL;
-		break;
-	}
-	// ctx match, vaddr match?
-	if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
-	    (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
-	    // valid, access ok?
-	    if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
-		((env->itlb_tte[i] & 0x4) && is_user)) {
-		if (env->immuregs[3]) /* Fault status register */
-		    env->immuregs[3] = 2; /* overflow (not read before another fault) */
-		env->immuregs[3] |= (is_user << 3) | 1;
-		env->exception_index = TT_TFAULT;
+        switch ((env->itlb_tte[i] >> 61) & 3) {
+        default:
+        case 0x0: // 8k
+            mask = 0xffffffffffffe000ULL;
+            break;
+        case 0x1: // 64k
+            mask = 0xffffffffffff0000ULL;
+            break;
+        case 0x2: // 512k
+            mask = 0xfffffffffff80000ULL;
+            break;
+        case 0x3: // 4M
+            mask = 0xffffffffffc00000ULL;
+                break;
+        }
+        // ctx match, vaddr match?
+        if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
+            (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
+            // valid, access ok?
+            if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
+                ((env->itlb_tte[i] & 0x4) && is_user)) {
+                if (env->immuregs[3]) /* Fault status register */
+                    env->immuregs[3] = 2; /* overflow (not read before another fault) */
+                env->immuregs[3] |= (is_user << 3) | 1;
+                env->exception_index = TT_TFAULT;
 #ifdef DEBUG_MMU
-		printf("TFAULT at 0x%" PRIx64 "\n", address);
+                printf("TFAULT at 0x%" PRIx64 "\n", address);
 #endif
-		return 1;
-	    }
-	    *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
-	    *prot = PAGE_EXEC;
-	    return 0;
-	}
+                return 1;
+            }
+            *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
+            *prot = PAGE_EXEC;
+            return 0;
+        }
     }
 #ifdef DEBUG_MMU
     printf("TMISS at 0x%" PRIx64 "\n", address);
@@ -476,32 +484,34 @@
 }
 
 int get_physical_address(CPUState *env, target_phys_addr_t *physical, int *prot,
-			  int *access_index, target_ulong address, int rw,
-			  int is_user)
+                          int *access_index, target_ulong address, int rw,
+                          int mmu_idx)
 {
+    int is_user = mmu_idx == MMU_USER_IDX;
+
     if (rw == 2)
-	return get_physical_address_code(env, physical, prot, access_index, address, rw, is_user);
+        return get_physical_address_code(env, physical, prot, access_index, address, rw, is_user);
     else
-	return get_physical_address_data(env, physical, prot, access_index, address, rw, is_user);
+        return get_physical_address_data(env, physical, prot, access_index, address, rw, is_user);
 }
 
 /* Perform address translation */
 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                              int is_user, int is_softmmu)
+                              int mmu_idx, int is_softmmu)
 {
     target_ulong virt_addr, vaddr;
     target_phys_addr_t paddr;
     int error_code = 0, prot, ret = 0, access_index;
 
-    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
+    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, mmu_idx);
     if (error_code == 0) {
-	virt_addr = address & TARGET_PAGE_MASK;
-	vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
+        virt_addr = address & TARGET_PAGE_MASK;
+        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
 #ifdef DEBUG_MMU
-	printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64 "\n", address, paddr, vaddr);
+        printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64 "\n", address, paddr, vaddr);
 #endif
-	ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
-	return ret;
+        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
+        return ret;
     }
     // XXX
     return 1;
@@ -515,67 +525,67 @@
 
     printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n", env->dmmuregs[1], env->dmmuregs[2]);
     if ((env->lsu & DMMU_E) == 0) {
-	printf("DMMU disabled\n");
+        printf("DMMU disabled\n");
     } else {
-	printf("DMMU dump:\n");
-	for (i = 0; i < 64; i++) {
-	    switch ((env->dtlb_tte[i] >> 61) & 3) {
-	    default:
-	    case 0x0:
-		mask = "  8k";
-		break;
-	    case 0x1:
-		mask = " 64k";
-		break;
-	    case 0x2:
-		mask = "512k";
-		break;
-	    case 0x3:
-		mask = "  4M";
-		break;
-	    }
-	    if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
-		printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, %s, ctx %" PRId64 "\n",
-		       env->dtlb_tag[i] & ~0x1fffULL,
-		       env->dtlb_tte[i] & 0x1ffffffe000ULL,
-		       mask,
-		       env->dtlb_tte[i] & 0x4? "priv": "user",
-		       env->dtlb_tte[i] & 0x2? "RW": "RO",
-		       env->dtlb_tte[i] & 0x40? "locked": "unlocked",
-		       env->dtlb_tag[i] & 0x1fffULL);
-	    }
-	}
+        printf("DMMU dump:\n");
+        for (i = 0; i < 64; i++) {
+            switch ((env->dtlb_tte[i] >> 61) & 3) {
+            default:
+            case 0x0:
+                mask = "  8k";
+                break;
+            case 0x1:
+                mask = " 64k";
+                break;
+            case 0x2:
+                mask = "512k";
+                break;
+            case 0x3:
+                mask = "  4M";
+                break;
+            }
+            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
+                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, %s, ctx %" PRId64 "\n",
+                       env->dtlb_tag[i] & ~0x1fffULL,
+                       env->dtlb_tte[i] & 0x1ffffffe000ULL,
+                       mask,
+                       env->dtlb_tte[i] & 0x4? "priv": "user",
+                       env->dtlb_tte[i] & 0x2? "RW": "RO",
+                       env->dtlb_tte[i] & 0x40? "locked": "unlocked",
+                       env->dtlb_tag[i] & 0x1fffULL);
+            }
+        }
     }
     if ((env->lsu & IMMU_E) == 0) {
-	printf("IMMU disabled\n");
+        printf("IMMU disabled\n");
     } else {
-	printf("IMMU dump:\n");
-	for (i = 0; i < 64; i++) {
-	    switch ((env->itlb_tte[i] >> 61) & 3) {
-	    default:
-	    case 0x0:
-		mask = "  8k";
-		break;
-	    case 0x1:
-		mask = " 64k";
-		break;
-	    case 0x2:
-		mask = "512k";
-		break;
-	    case 0x3:
-		mask = "  4M";
-		break;
-	    }
-	    if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
-		printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, ctx %" PRId64 "\n",
-		       env->itlb_tag[i] & ~0x1fffULL,
-		       env->itlb_tte[i] & 0x1ffffffe000ULL,
-		       mask,
-		       env->itlb_tte[i] & 0x4? "priv": "user",
-		       env->itlb_tte[i] & 0x40? "locked": "unlocked",
-		       env->itlb_tag[i] & 0x1fffULL);
-	    }
-	}
+        printf("IMMU dump:\n");
+        for (i = 0; i < 64; i++) {
+            switch ((env->itlb_tte[i] >> 61) & 3) {
+            default:
+            case 0x0:
+                mask = "  8k";
+                break;
+            case 0x1:
+                mask = " 64k";
+                break;
+            case 0x2:
+                mask = "512k";
+                break;
+            case 0x3:
+                mask = "  4M";
+                break;
+            }
+            if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
+                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, ctx %" PRId64 "\n",
+                       env->itlb_tag[i] & ~0x1fffULL,
+                       env->itlb_tte[i] & 0x1ffffffe000ULL,
+                       mask,
+                       env->itlb_tte[i] & 0x4? "priv": "user",
+                       env->itlb_tte[i] & 0x40? "locked": "unlocked",
+                       env->itlb_tag[i] & 0x1fffULL);
+            }
+        }
     }
 }
 #endif /* DEBUG_MMU */

Modified: trunk/src/host/qemu-neo1973/target-sparc/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/op.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-sparc/op.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -376,33 +376,33 @@
     env->psr = 0;
 #ifdef TARGET_SPARC64
     if (!(T0 & 0xffffffff))
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
-	env->psr |= PSR_CARRY;
+        env->psr |= PSR_CARRY;
     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
-	 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
-	env->psr |= PSR_OVF;
+         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
+        env->psr |= PSR_OVF;
 
     env->xcc = 0;
     if (!T0)
-	env->xcc |= PSR_ZERO;
+        env->xcc |= PSR_ZERO;
     if ((int64_t) T0 < 0)
-	env->xcc |= PSR_NEG;
+        env->xcc |= PSR_NEG;
     if (T0 < src1)
-	env->xcc |= PSR_CARRY;
+        env->xcc |= PSR_CARRY;
     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63))
-	env->xcc |= PSR_OVF;
+        env->xcc |= PSR_OVF;
 #else
     if (!T0)
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if (T0 < src1)
-	env->psr |= PSR_CARRY;
+        env->psr |= PSR_CARRY;
     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
-	env->psr |= PSR_OVF;
+        env->psr |= PSR_OVF;
 #endif
     FORCE_RET();
 }
@@ -448,26 +448,26 @@
     }
 #ifdef TARGET_SPARC64
     if (!(T0 & 0xffffffff))
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
-	 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
-	env->psr |= PSR_OVF;
+         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
+        env->psr |= PSR_OVF;
 
     if (!T0)
-	env->xcc |= PSR_ZERO;
+        env->xcc |= PSR_ZERO;
     if ((int64_t) T0 < 0)
-	env->xcc |= PSR_NEG;
+        env->xcc |= PSR_NEG;
     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63))
-	env->xcc |= PSR_OVF;
+        env->xcc |= PSR_OVF;
 #else
     if (!T0)
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
-	env->psr |= PSR_OVF;
+        env->psr |= PSR_OVF;
 #endif
     FORCE_RET();
 }
@@ -481,37 +481,37 @@
     env->psr = 0;
 #ifdef TARGET_SPARC64
     if (!(T0 & 0xffffffff))
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
-	env->psr |= PSR_CARRY;
+        env->psr |= PSR_CARRY;
     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
-	 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
-	env->psr |= PSR_OVF;
+         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
+        env->psr |= PSR_OVF;
     if ((src1 & 0x03) || (T1 & 0x03))
-	env->psr |= PSR_OVF;
+        env->psr |= PSR_OVF;
 
     env->xcc = 0;
     if (!T0)
-	env->xcc |= PSR_ZERO;
+        env->xcc |= PSR_ZERO;
     if ((int64_t) T0 < 0)
-	env->xcc |= PSR_NEG;
+        env->xcc |= PSR_NEG;
     if (T0 < src1)
-	env->xcc |= PSR_CARRY;
+        env->xcc |= PSR_CARRY;
     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63))
-	env->xcc |= PSR_OVF;
+        env->xcc |= PSR_OVF;
 #else
     if (!T0)
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if (T0 < src1)
-	env->psr |= PSR_CARRY;
+        env->psr |= PSR_CARRY;
     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
-	env->psr |= PSR_OVF;
+        env->psr |= PSR_OVF;
     if ((src1 & 0x03) || (T1 & 0x03))
-	env->psr |= PSR_OVF;
+        env->psr |= PSR_OVF;
 #endif
     FORCE_RET();
 }
@@ -520,44 +520,47 @@
 {
     target_ulong src1;
 
-    if ((T0 & 0x03) || (T1 & 0x03))
+    if ((T0 & 0x03) || (T1 & 0x03)) {
         raise_exception(TT_TOVF);
+        FORCE_RET();
+        return;
+    }
 
     src1 = T0;
     T0 += T1;
 
 #ifdef TARGET_SPARC64
     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
-	 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
+         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
         raise_exception(TT_TOVF);
 #else
-    if ((src1 & 0x03) || (T1 & 0x03))
+    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
         raise_exception(TT_TOVF);
 #endif
 
     env->psr = 0;
 #ifdef TARGET_SPARC64
     if (!(T0 & 0xffffffff))
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
-	env->psr |= PSR_CARRY;
+        env->psr |= PSR_CARRY;
 
     env->xcc = 0;
     if (!T0)
-	env->xcc |= PSR_ZERO;
+        env->xcc |= PSR_ZERO;
     if ((int64_t) T0 < 0)
-	env->xcc |= PSR_NEG;
+        env->xcc |= PSR_NEG;
     if (T0 < src1)
-	env->xcc |= PSR_CARRY;
+        env->xcc |= PSR_CARRY;
 #else
     if (!T0)
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if (T0 < src1)
-	env->psr |= PSR_CARRY;
+        env->psr |= PSR_CARRY;
 #endif
     FORCE_RET();
 }
@@ -576,33 +579,33 @@
     env->psr = 0;
 #ifdef TARGET_SPARC64
     if (!(T0 & 0xffffffff))
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
-	env->psr |= PSR_CARRY;
+        env->psr |= PSR_CARRY;
     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
-	 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
-	env->psr |= PSR_OVF;
+         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
+        env->psr |= PSR_OVF;
 
     env->xcc = 0;
     if (!T0)
-	env->xcc |= PSR_ZERO;
+        env->xcc |= PSR_ZERO;
     if ((int64_t) T0 < 0)
-	env->xcc |= PSR_NEG;
+        env->xcc |= PSR_NEG;
     if (src1 < T1)
-	env->xcc |= PSR_CARRY;
+        env->xcc |= PSR_CARRY;
     if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63))
-	env->xcc |= PSR_OVF;
+        env->xcc |= PSR_OVF;
 #else
     if (!T0)
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if (src1 < T1)
-	env->psr |= PSR_CARRY;
+        env->psr |= PSR_CARRY;
     if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
-	env->psr |= PSR_OVF;
+        env->psr |= PSR_OVF;
 #endif
     FORCE_RET();
 }
@@ -648,26 +651,26 @@
     }
 #ifdef TARGET_SPARC64
     if (!(T0 & 0xffffffff))
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
-	 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
-	env->psr |= PSR_OVF;
+         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
+        env->psr |= PSR_OVF;
 
     if (!T0)
-	env->xcc |= PSR_ZERO;
+        env->xcc |= PSR_ZERO;
     if ((int64_t) T0 < 0)
-	env->xcc |= PSR_NEG;
+        env->xcc |= PSR_NEG;
     if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63))
-	env->xcc |= PSR_OVF;
+        env->xcc |= PSR_OVF;
 #else
     if (!T0)
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
-	env->psr |= PSR_OVF;
+        env->psr |= PSR_OVF;
 #endif
     FORCE_RET();
 }
@@ -681,37 +684,37 @@
     env->psr = 0;
 #ifdef TARGET_SPARC64
     if (!(T0 & 0xffffffff))
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
-	env->psr |= PSR_CARRY;
+        env->psr |= PSR_CARRY;
     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
-	 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
-	env->psr |= PSR_OVF;
+         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
+        env->psr |= PSR_OVF;
     if ((src1 & 0x03) || (T1 & 0x03))
-	env->psr |= PSR_OVF;
+        env->psr |= PSR_OVF;
 
     env->xcc = 0;
     if (!T0)
-	env->xcc |= PSR_ZERO;
+        env->xcc |= PSR_ZERO;
     if ((int64_t) T0 < 0)
-	env->xcc |= PSR_NEG;
+        env->xcc |= PSR_NEG;
     if (src1 < T1)
-	env->xcc |= PSR_CARRY;
+        env->xcc |= PSR_CARRY;
     if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63))
-	env->xcc |= PSR_OVF;
+        env->xcc |= PSR_OVF;
 #else
     if (!T0)
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if (src1 < T1)
-	env->psr |= PSR_CARRY;
+        env->psr |= PSR_CARRY;
     if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
-	env->psr |= PSR_OVF;
+        env->psr |= PSR_OVF;
     if ((src1 & 0x03) || (T1 & 0x03))
-	env->psr |= PSR_OVF;
+        env->psr |= PSR_OVF;
 #endif
     FORCE_RET();
 }
@@ -728,7 +731,7 @@
 
 #ifdef TARGET_SPARC64
     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
-	 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
+         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
         raise_exception(TT_TOVF);
 #else
     if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
@@ -738,26 +741,26 @@
     env->psr = 0;
 #ifdef TARGET_SPARC64
     if (!(T0 & 0xffffffff))
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
-	env->psr |= PSR_CARRY;
+        env->psr |= PSR_CARRY;
 
     env->xcc = 0;
     if (!T0)
-	env->xcc |= PSR_ZERO;
+        env->xcc |= PSR_ZERO;
     if ((int64_t) T0 < 0)
-	env->xcc |= PSR_NEG;
+        env->xcc |= PSR_NEG;
     if (src1 < T1)
-	env->xcc |= PSR_CARRY;
+        env->xcc |= PSR_CARRY;
 #else
     if (!T0)
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if (src1 < T1)
-	env->psr |= PSR_CARRY;
+        env->psr |= PSR_CARRY;
 #endif
     FORCE_RET();
 }
@@ -833,13 +836,13 @@
     T0 += T1;
     env->psr = 0;
     if (!T0)
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if (T0 < src1)
-	env->psr |= PSR_CARRY;
+        env->psr |= PSR_CARRY;
     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
-	env->psr |= PSR_OVF;
+        env->psr |= PSR_OVF;
     env->y = (b2 << 31) | (env->y >> 1);
     FORCE_RET();
 }
@@ -858,11 +861,11 @@
 
     x0 = x0 / x1;
     if (x0 > 0xffffffff) {
-	T0 = 0xffffffff;
-	T1 = 1;
+        T0 = 0xffffffff;
+        T1 = 1;
     } else {
-	T0 = x0;
-	T1 = 0;
+        T0 = x0;
+        T1 = 0;
     }
     FORCE_RET();
 }
@@ -881,11 +884,11 @@
 
     x0 = x0 / x1;
     if ((int32_t) x0 != x0) {
-	T0 = x0 < 0? 0x80000000: 0x7fffffff;
-	T1 = 1;
+        T0 = x0 < 0? 0x80000000: 0x7fffffff;
+        T1 = 1;
     } else {
-	T0 = x0;
-	T1 = 0;
+        T0 = x0;
+        T1 = 0;
     }
     FORCE_RET();
 }
@@ -895,24 +898,24 @@
     env->psr = 0;
 #ifdef TARGET_SPARC64
     if (!T0)
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if (T1)
-	env->psr |= PSR_OVF;
+        env->psr |= PSR_OVF;
 
     env->xcc = 0;
     if (!T0)
-	env->xcc |= PSR_ZERO;
+        env->xcc |= PSR_ZERO;
     if ((int64_t) T0 < 0)
-	env->xcc |= PSR_NEG;
+        env->xcc |= PSR_NEG;
 #else
     if (!T0)
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
     if (T1)
-	env->psr |= PSR_OVF;
+        env->psr |= PSR_OVF;
 #endif
     FORCE_RET();
 }
@@ -939,9 +942,9 @@
         raise_exception(TT_DIV_ZERO);
     }
     if (T0 == INT64_MIN && T1 == -1)
-	T0 = INT64_MIN;
+        T0 = INT64_MIN;
     else
-	T0 /= (target_long) T1;
+        T0 /= (target_long) T1;
     FORCE_RET();
 }
 #endif
@@ -951,20 +954,20 @@
     env->psr = 0;
 #ifdef TARGET_SPARC64
     if (!(T0 & 0xffffffff))
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
 
     env->xcc = 0;
     if (!T0)
-	env->xcc |= PSR_ZERO;
+        env->xcc |= PSR_ZERO;
     if ((int64_t) T0 < 0)
-	env->xcc |= PSR_NEG;
+        env->xcc |= PSR_NEG;
 #else
     if (!T0)
-	env->psr |= PSR_ZERO;
+        env->psr |= PSR_ZERO;
     if ((int32_t) T0 < 0)
-	env->psr |= PSR_NEG;
+        env->psr |= PSR_NEG;
 #endif
     FORCE_RET();
 }
@@ -1020,7 +1023,12 @@
 
 #define MEMSUFFIX _kernel
 #include "op_mem.h"
+
+#ifdef TARGET_SPARC64
+#define MEMSUFFIX _hypv
+#include "op_mem.h"
 #endif
+#endif
 
 void OPPROTO op_ldfsr(void)
 {
@@ -1200,17 +1208,17 @@
     cwp = (env->cwp - 1) & (NWINDOWS - 1);
     if (env->cansave == 0) {
         raise_exception(TT_SPILL | (env->otherwin != 0 ?
-				    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
-				    ((env->wstate & 0x7) << 2)));
+                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
+                                    ((env->wstate & 0x7) << 2)));
     } else {
-	if (env->cleanwin - env->canrestore == 0) {
-	    // XXX Clean windows without trap
-	    raise_exception(TT_CLRWIN);
-	} else {
-	    env->cansave--;
-	    env->canrestore++;
-	    set_cwp(cwp);
-	}
+        if (env->cleanwin - env->canrestore == 0) {
+            // XXX Clean windows without trap
+            raise_exception(TT_CLRWIN);
+        } else {
+            env->cansave--;
+            env->canrestore++;
+            set_cwp(cwp);
+        }
     }
     FORCE_RET();
 }
@@ -1221,12 +1229,12 @@
     cwp = (env->cwp + 1) & (NWINDOWS - 1);
     if (env->canrestore == 0) {
         raise_exception(TT_FILL | (env->otherwin != 0 ?
-				   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
-				   ((env->wstate & 0x7) << 2)));
+                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
+                                   ((env->wstate & 0x7) << 2)));
     } else {
-	env->cansave++;
-	env->canrestore--;
-	set_cwp(cwp);
+        env->cansave++;
+        env->canrestore--;
+        set_cwp(cwp);
     }
     FORCE_RET();
 }
@@ -1576,15 +1584,15 @@
 #define F_BINOP(name)                                           \
     F_OP(name, s)                                               \
     {                                                           \
-	set_float_exception_flags(0, &env->fp_status);		\
+        set_float_exception_flags(0, &env->fp_status);          \
         FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
-	check_ieee_exceptions();				\
+        check_ieee_exceptions();                                \
     }                                                           \
     F_OP(name, d)                                               \
     {                                                           \
-	set_float_exception_flags(0, &env->fp_status);		\
+        set_float_exception_flags(0, &env->fp_status);          \
         DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
-	check_ieee_exceptions();				\
+        check_ieee_exceptions();                                \
     }
 
 F_BINOP(add);
@@ -1703,6 +1711,9 @@
 /* Integer to float conversion.  */
 #ifdef USE_INT_TO_FLOAT_HELPERS
 F_HELPER(ito);
+#ifdef TARGET_SPARC64
+F_HELPER(xto);
+#endif
 #else
 F_OP(ito, s)
 {
@@ -1784,27 +1795,27 @@
 void OPPROTO op_fmovs_cc(void)
 {
     if (T2)
-	FT0 = FT1;
+        FT0 = FT1;
 }
 
 void OPPROTO op_fmovd_cc(void)
 {
     if (T2)
-	DT0 = DT1;
+        DT0 = DT1;
 }
 
 void OPPROTO op_mov_cc(void)
 {
     if (T2)
-	T0 = T1;
+        T0 = T1;
 }
 
 void OPPROTO op_flushw(void)
 {
     if (env->cansave != NWINDOWS - 2) {
         raise_exception(TT_SPILL | (env->otherwin != 0 ?
-				    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
-				    ((env->wstate & 0x7) << 2)));
+                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
+                                    ((env->wstate & 0x7) << 2)));
     }
 }
 
@@ -1812,9 +1823,9 @@
 {
     env->cansave++;
     if (env->otherwin == 0)
-	env->canrestore--;
+        env->canrestore--;
     else
-	env->otherwin--;
+        env->otherwin--;
     FORCE_RET();
 }
 
@@ -1822,11 +1833,11 @@
 {
     env->canrestore++;
     if (env->cleanwin < NWINDOWS - 1)
-	env->cleanwin++;
+        env->cleanwin++;
     if (env->otherwin == 0)
-	env->cansave--;
+        env->cansave--;
     else
-	env->otherwin--;
+        env->otherwin--;
     FORCE_RET();
 }
 
@@ -1859,10 +1870,148 @@
 void OPPROTO op_st_asi_reg()
 {
     T0 += PARAM1;
-    helper_st_asi(env->asi, PARAM2, PARAM3);
+    helper_st_asi(env->asi, PARAM2);
 }
+
+void OPPROTO op_ldf_asi_reg()
+{
+    T0 += PARAM1;
+    helper_ldf_asi(env->asi, PARAM2, PARAM3);
+}
+
+void OPPROTO op_stf_asi_reg()
+{
+    T0 += PARAM1;
+    helper_stf_asi(env->asi, PARAM2, PARAM3);
+}
+
+void OPPROTO op_ldf_asi()
+{
+    helper_ldf_asi(PARAM1, PARAM2, PARAM3);
+}
+
+void OPPROTO op_stf_asi()
+{
+    helper_stf_asi(PARAM1, PARAM2, PARAM3);
+}
+
+void OPPROTO op_ldstub_asi_reg()             /* XXX: should be atomically */
+{
+    target_ulong tmp;
+
+    T0 += PARAM1;
+    helper_ld_asi(env->asi, 1, 0);
+    tmp = T1;
+    T1 = 0xff;
+    helper_st_asi(env->asi, 1);
+    T1 = tmp;
+}
+
+void OPPROTO op_swap_asi_reg()               /* XXX: should be atomically */
+{
+    target_ulong tmp1, tmp2;
+
+    T0 += PARAM1;
+    tmp1 = T1;
+    helper_ld_asi(env->asi, 4, 0);
+    tmp2 = T1;
+    T1 = tmp1;
+    helper_st_asi(env->asi, 4);
+    T1 = tmp2;
+}
+
+void OPPROTO op_ldda_asi()
+{
+    helper_ld_asi(PARAM1, 8, 0);
+    T0 = T1 & 0xffffffffUL;
+    T1 >>= 32;
+}
+
+void OPPROTO op_ldda_asi_reg()
+{
+    T0 += PARAM1;
+    helper_ld_asi(env->asi, 8, 0);
+    T0 = T1 & 0xffffffffUL;
+    T1 >>= 32;
+}
+
+void OPPROTO op_stda_asi()
+{
+    T1 <<= 32;
+    T1 += T2 & 0xffffffffUL;
+    helper_st_asi(PARAM1, 8);
+}
+
+void OPPROTO op_stda_asi_reg()
+{
+    T0 += PARAM1;
+    T1 <<= 32;
+    T1 += T2 & 0xffffffffUL;
+    helper_st_asi(env->asi, 8);
+}
+
+void OPPROTO op_cas_asi()                    /* XXX: should be atomically */
+{
+    target_ulong tmp;
+
+    tmp = T1 & 0xffffffffUL;
+    helper_ld_asi(PARAM1, 4, 0);
+    if (tmp == T1) {
+        tmp = T1;
+        T1 = T2 & 0xffffffffUL;
+        helper_st_asi(PARAM1, 4);
+        T1 = tmp;
+    }
+    T1 &= 0xffffffffUL;
+}
+
+void OPPROTO op_cas_asi_reg()                /* XXX: should be atomically */
+{
+    target_ulong tmp;
+
+    T0 += PARAM1;
+    tmp = T1 & 0xffffffffUL;
+    helper_ld_asi(env->asi, 4, 0);
+    if (tmp == T1) {
+        tmp = T1;
+        T1 = T2 & 0xffffffffUL;
+        helper_st_asi(env->asi, 4);
+        T1 = tmp;
+    }
+    T1 &= 0xffffffffUL;
+}
+
+void OPPROTO op_casx_asi()                   /* XXX: should be atomically */
+{
+    target_ulong tmp;
+
+    tmp = T1;
+    helper_ld_asi(PARAM1, 8, 0);
+    if (tmp == T1) {
+        tmp = T1;
+        T1 = T2;
+        helper_st_asi(PARAM1, 8);
+        T1 = tmp;
+    }
+}
+
+void OPPROTO op_casx_asi_reg()               /* XXX: should be atomically */
+{
+    target_ulong tmp;
+
+    T0 += PARAM1;
+    tmp = T1;
+    helper_ld_asi(env->asi, 8, 0);
+    if (tmp == T1) {
+        tmp = T1;
+        T1 = T2;
+        helper_st_asi(env->asi, 8);
+        T1 = tmp;
+    }
+}
 #endif
 
+#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
 void OPPROTO op_ld_asi()
 {
     helper_ld_asi(PARAM1, PARAM2, PARAM3);
@@ -1870,9 +2019,33 @@
 
 void OPPROTO op_st_asi()
 {
-    helper_st_asi(PARAM1, PARAM2, PARAM3);
+    helper_st_asi(PARAM1, PARAM2);
 }
 
+void OPPROTO op_ldstub_asi()                 /* XXX: should be atomically */
+{
+    target_ulong tmp;
+
+    helper_ld_asi(PARAM1, 1, 0);
+    tmp = T1;
+    T1 = 0xff;
+    helper_st_asi(PARAM1, 1);
+    T1 = tmp;
+}
+
+void OPPROTO op_swap_asi()                   /* XXX: should be atomically */
+{
+    target_ulong tmp1, tmp2;
+
+    tmp1 = T1;
+    helper_ld_asi(PARAM1, 4, 0);
+    tmp2 = T1;
+    T1 = tmp1;
+    helper_st_asi(PARAM1, 4);
+    T1 = tmp2;
+}
+#endif
+
 #ifdef TARGET_SPARC64
 // This function uses non-native bit order
 #define GET_FIELD(X, FROM, TO)                                  \

Modified: trunk/src/host/qemu-neo1973/target-sparc/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/op_helper.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-sparc/op_helper.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,10 +1,26 @@
 #include "exec.h"
+#include "host-utils.h"
 
 //#define DEBUG_PCALL
 //#define DEBUG_MMU
+//#define DEBUG_MXCC
 //#define DEBUG_UNALIGNED
 //#define DEBUG_UNASSIGNED
 
+#ifdef DEBUG_MMU
+#define DPRINTF_MMU(fmt, args...) \
+do { printf("MMU: " fmt , ##args); } while (0)
+#else
+#define DPRINTF_MMU(fmt, args...)
+#endif
+
+#ifdef DEBUG_MXCC
+#define DPRINTF_MXCC(fmt, args...) \
+do { printf("MXCC: " fmt , ##args); } while (0)
+#else
+#define DPRINTF_MXCC(fmt, args...)
+#endif
+
 void raise_exception(int tt)
 {
     env->exception_index = tt;
@@ -16,29 +32,29 @@
      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;
+        /* 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;
-	}
+        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;
+        }
      }
 }
 
@@ -54,7 +70,22 @@
 {
     DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
 }
+#ifdef TARGET_SPARC64
+void do_fxtos(void)
+{
+    set_float_exception_flags(0, &env->fp_status);
+    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
+    check_ieee_exceptions();
+}
+
+void do_fxtod(void)
+{
+    set_float_exception_flags(0, &env->fp_status);
+    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
+    check_ieee_exceptions();
+}
 #endif
+#endif
 
 void do_fabss(void)
 {
@@ -137,51 +168,86 @@
 GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
 #endif
 
-#if defined(CONFIG_USER_ONLY)
-void helper_ld_asi(int asi, int size, int sign)
+#ifndef TARGET_SPARC64
+#ifndef CONFIG_USER_ONLY
+
+#ifdef DEBUG_MXCC
+static void dump_mxcc(CPUState *env)
 {
+    printf("mxccdata: %016llx %016llx %016llx %016llx\n",
+        env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]);
+    printf("mxccregs: %016llx %016llx %016llx %016llx\n"
+           "          %016llx %016llx %016llx %016llx\n",
+        env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3],
+        env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]);
 }
+#endif
 
-void helper_st_asi(int asi, int size, int sign)
-{
-}
-#else
-#ifndef TARGET_SPARC64
 void helper_ld_asi(int asi, int size, int sign)
 {
     uint32_t ret = 0;
+    uint64_t tmp;
+#ifdef DEBUG_MXCC
+    uint32_t last_T0 = T0;
+#endif
 
     switch (asi) {
     case 2: /* SuperSparc MXCC registers */
+        switch (T0) {
+        case 0x01c00a00: /* MXCC control register */
+            if (size == 8) {
+                ret = env->mxccregs[3];
+                T0 = env->mxccregs[3] >> 32;
+            } else
+                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
+            break;
+        case 0x01c00a04: /* MXCC control register */
+            if (size == 4)
+                ret = env->mxccregs[3];
+            else
+                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
+            break;
+        case 0x01c00f00: /* MBus port address register */
+            if (size == 8) {
+                ret = env->mxccregs[7];
+                T0 = env->mxccregs[7] >> 32;
+            } else
+                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
+            break;
+        default:
+            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
+            break;
+        }
+        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x,"
+                     "T0 = %08x\n", asi, size, sign, last_T0, ret, T0);
+#ifdef DEBUG_MXCC
+        dump_mxcc(env);
+#endif
         break;
     case 3: /* MMU probe */
-	{
-	    int mmulev;
+        {
+            int mmulev;
 
-	    mmulev = (T0 >> 8) & 15;
-	    if (mmulev > 4)
-		ret = 0;
-	    else {
-		ret = mmu_probe(env, T0, mmulev);
-		//bswap32s(&ret);
-	    }
-#ifdef DEBUG_MMU
-	    printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
-#endif
-	}
-	break;
+            mmulev = (T0 >> 8) & 15;
+            if (mmulev > 4)
+                ret = 0;
+            else {
+                ret = mmu_probe(env, T0, mmulev);
+                //bswap32s(&ret);
+            }
+            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
+        }
+        break;
     case 4: /* read MMU regs */
-	{
-	    int reg = (T0 >> 8) & 0xf;
+        {
+            int reg = (T0 >> 8) & 0xf;
 
-	    ret = env->mmuregs[reg];
-	    if (reg == 3) /* Fault status cleared on read */
-		env->mmuregs[reg] = 0;
-#ifdef DEBUG_MMU
-	    printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
-#endif
-	}
-	break;
+            ret = env->mmuregs[reg];
+            if (reg == 3) /* Fault status cleared on read */
+                env->mmuregs[reg] = 0;
+            DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
+        }
+        break;
     case 9: /* Supervisor code access */
         switch(size) {
         case 1:
@@ -195,11 +261,50 @@
             ret = ldl_code(T0 & ~3);
             break;
         case 8:
-            ret = ldl_code(T0 & ~3);
-            T0 = ldl_code((T0 + 4) & ~3);
+            tmp = ldq_code(T0 & ~7);
+            ret = tmp >> 32;
+            T0 = tmp & 0xffffffff;
             break;
         }
         break;
+    case 0xa: /* User data access */
+        switch(size) {
+        case 1:
+            ret = ldub_user(T0);
+            break;
+        case 2:
+            ret = lduw_user(T0 & ~1);
+            break;
+        default:
+        case 4:
+            ret = ldl_user(T0 & ~3);
+            break;
+        case 8:
+            tmp = ldq_user(T0 & ~7);
+            ret = tmp >> 32;
+            T0 = tmp & 0xffffffff;
+            break;
+        }
+        break;
+    case 0xb: /* Supervisor data access */
+        switch(size) {
+        case 1:
+            ret = ldub_kernel(T0);
+            break;
+        case 2:
+            ret = lduw_kernel(T0 & ~1);
+            break;
+        default:
+        case 4:
+            ret = ldl_kernel(T0 & ~3);
+            break;
+        case 8:
+            tmp = ldq_kernel(T0 & ~7);
+            ret = tmp >> 32;
+            T0 = tmp & 0xffffffff;
+            break;
+        }
+        break;
     case 0xc: /* I-cache tag */
     case 0xd: /* I-cache data */
     case 0xe: /* D-cache tag */
@@ -218,11 +323,12 @@
             ret = ldl_phys(T0 & ~3);
             break;
         case 8:
-	    ret = ldl_phys(T0 & ~3);
-	    T0 = ldl_phys((T0 + 4) & ~3);
-	    break;
+            tmp = ldq_phys(T0 & ~7);
+            ret = tmp >> 32;
+            T0 = tmp & 0xffffffff;
+            break;
         }
-	break;
+        break;
     case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
     case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
         switch(size) {
@@ -240,70 +346,162 @@
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
             break;
         case 8:
-            ret = ldl_phys((target_phys_addr_t)(T0 & ~3)
+            tmp = ldq_phys((target_phys_addr_t)(T0 & ~7)
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
-            T0 = ldl_phys((target_phys_addr_t)((T0 + 4) & ~3)
-                           | ((target_phys_addr_t)(asi & 0xf) << 32));
-	    break;
+            ret = tmp >> 32;
+            T0 = tmp & 0xffffffff;
+            break;
         }
-	break;
+        break;
     case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
     default:
         do_unassigned_access(T0, 0, 0, 1);
-	ret = 0;
-	break;
+        ret = 0;
+        break;
     }
-    T1 = ret;
+    if (sign) {
+        switch(size) {
+        case 1:
+            T1 = (int8_t) ret;
+            break;
+        case 2:
+            T1 = (int16_t) ret;
+            break;
+        default:
+            T1 = ret;
+            break;
+        }
+    }
+    else
+        T1 = ret;
 }
 
-void helper_st_asi(int asi, int size, int sign)
+void helper_st_asi(int asi, int size)
 {
     switch(asi) {
     case 2: /* SuperSparc MXCC registers */
+        switch (T0) {
+        case 0x01c00000: /* MXCC stream data register 0 */
+            if (size == 8)
+                env->mxccdata[0] = ((uint64_t)T1 << 32) | T2;
+            else
+                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
+            break;
+        case 0x01c00008: /* MXCC stream data register 1 */
+            if (size == 8)
+                env->mxccdata[1] = ((uint64_t)T1 << 32) | T2;
+            else
+                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
+            break;
+        case 0x01c00010: /* MXCC stream data register 2 */
+            if (size == 8)
+                env->mxccdata[2] = ((uint64_t)T1 << 32) | T2;
+            else
+                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
+            break;
+        case 0x01c00018: /* MXCC stream data register 3 */
+            if (size == 8)
+                env->mxccdata[3] = ((uint64_t)T1 << 32) | T2;
+            else
+                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
+            break;
+        case 0x01c00100: /* MXCC stream source */
+            if (size == 8)
+                env->mxccregs[0] = ((uint64_t)T1 << 32) | T2;
+            else
+                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
+            env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  0);
+            env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  8);
+            env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16);
+            env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24);
+            break;
+        case 0x01c00200: /* MXCC stream destination */
+            if (size == 8)
+                env->mxccregs[1] = ((uint64_t)T1 << 32) | T2;
+            else
+                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
+            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0, env->mxccdata[0]);
+            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8, env->mxccdata[1]);
+            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]);
+            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]);
+            break;
+        case 0x01c00a00: /* MXCC control register */
+            if (size == 8)
+                env->mxccregs[3] = ((uint64_t)T1 << 32) | T2;
+            else
+                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
+            break;
+        case 0x01c00a04: /* MXCC control register */
+            if (size == 4)
+                env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000) | T1;
+            else
+                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
+            break;
+        case 0x01c00e00: /* MXCC error register  */
+            if (size == 8)
+                env->mxccregs[6] = ((uint64_t)T1 << 32) | T2;
+            else
+                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
+            if (env->mxccregs[6] == 0xffffffffffffffffULL) {
+                // this is probably a reset
+            }
+            break;
+        case 0x01c00f00: /* MBus port address register */
+            if (size == 8)
+                env->mxccregs[7] = ((uint64_t)T1 << 32) | T2;
+            else
+                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
+            break;
+        default:
+            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
+            break;
+        }
+        DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi, size, T0, T1);
+#ifdef DEBUG_MXCC
+        dump_mxcc(env);
+#endif
         break;
     case 3: /* MMU flush */
-	{
-	    int mmulev;
+        {
+            int mmulev;
 
-	    mmulev = (T0 >> 8) & 15;
+            mmulev = (T0 >> 8) & 15;
+            DPRINTF_MMU("mmu flush level %d\n", mmulev);
+            switch (mmulev) {
+            case 0: // flush page
+                tlb_flush_page(env, T0 & 0xfffff000);
+                break;
+            case 1: // flush segment (256k)
+            case 2: // flush region (16M)
+            case 3: // flush context (4G)
+            case 4: // flush entire
+                tlb_flush(env, 1);
+                break;
+            default:
+                break;
+            }
 #ifdef DEBUG_MMU
-	    printf("mmu flush level %d\n", mmulev);
+            dump_mmu(env);
 #endif
-	    switch (mmulev) {
-	    case 0: // flush page
-		tlb_flush_page(env, T0 & 0xfffff000);
-		break;
-	    case 1: // flush segment (256k)
-	    case 2: // flush region (16M)
-	    case 3: // flush context (4G)
-	    case 4: // flush entire
-		tlb_flush(env, 1);
-		break;
-	    default:
-		break;
-	    }
-#ifdef DEBUG_MMU
-	    dump_mmu(env);
-#endif
-	    return;
-	}
+            return;
+        }
     case 4: /* write MMU regs */
-	{
-	    int reg = (T0 >> 8) & 0xf;
-	    uint32_t oldreg;
+        {
+            int reg = (T0 >> 8) & 0xf;
+            uint32_t oldreg;
 
-	    oldreg = env->mmuregs[reg];
+            oldreg = env->mmuregs[reg];
             switch(reg) {
             case 0:
-		env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
-		env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
-		// Mappings generated during no-fault mode or MMU
-		// disabled mode are invalid in normal mode
+                env->mmuregs[reg] &= ~(MMU_E | MMU_NF | MMU_BM);
+                env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF | MMU_BM);
+                // Mappings generated during no-fault mode or MMU
+                // disabled mode are invalid in normal mode
                 if (oldreg != env->mmuregs[reg])
                     tlb_flush(env, 1);
                 break;
             case 2:
-		env->mmuregs[reg] = T1;
+                env->mmuregs[reg] = T1;
                 if (oldreg != env->mmuregs[reg]) {
                     /* we flush when the MMU context changes because
                        QEMU has no MMU context support */
@@ -314,17 +512,51 @@
             case 4:
                 break;
             default:
-		env->mmuregs[reg] = T1;
+                env->mmuregs[reg] = T1;
                 break;
             }
-#ifdef DEBUG_MMU
             if (oldreg != env->mmuregs[reg]) {
-                printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
+                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
             }
-	    dump_mmu(env);
+#ifdef DEBUG_MMU
+            dump_mmu(env);
 #endif
-	    return;
-	}
+            return;
+        }
+    case 0xa: /* User data access */
+        switch(size) {
+        case 1:
+            stb_user(T0, T1);
+            break;
+        case 2:
+            stw_user(T0 & ~1, T1);
+            break;
+        default:
+        case 4:
+            stl_user(T0 & ~3, T1);
+            break;
+        case 8:
+            stq_user(T0 & ~7, ((uint64_t)T1 << 32) | T2);
+            break;
+        }
+        break;
+    case 0xb: /* Supervisor data access */
+        switch(size) {
+        case 1:
+            stb_kernel(T0, T1);
+            break;
+        case 2:
+            stw_kernel(T0 & ~1, T1);
+            break;
+        default:
+        case 4:
+            stl_kernel(T0 & ~3, T1);
+            break;
+        case 8:
+            stq_kernel(T0 & ~7, ((uint64_t)T1 << 32) | T2);
+            break;
+        }
+        break;
     case 0xc: /* I-cache tag */
     case 0xd: /* I-cache data */
     case 0xe: /* D-cache tag */
@@ -336,10 +568,10 @@
     case 0x14: /* I/D-cache flush user */
         break;
     case 0x17: /* Block copy, sta access */
-	{
-	    // value (T1) = src
-	    // address (T0) = dst
-	    // copy 32 bytes
+        {
+            // value (T1) = src
+            // address (T0) = dst
+            // copy 32 bytes
             unsigned int i;
             uint32_t src = T1 & ~3, dst = T0 & ~3, temp;
 
@@ -347,13 +579,13 @@
                 temp = ldl_kernel(src);
                 stl_kernel(dst, temp);
             }
-	}
-	return;
+        }
+        return;
     case 0x1f: /* Block fill, stda access */
-	{
-	    // value (T1, T2)
-	    // address (T0) = dst
-	    // fill 32 bytes
+        {
+            // value (T1, T2)
+            // address (T0) = dst
+            // fill 32 bytes
             unsigned int i;
             uint32_t dst = T0 & 7;
             uint64_t val;
@@ -362,10 +594,10 @@
 
             for (i = 0; i < 32; i += 8, dst += 8)
                 stq_kernel(dst, val);
-	}
-	return;
+        }
+        return;
     case 0x20: /* MMU passthrough */
-	{
+        {
             switch(size) {
             case 1:
                 stb_phys(T0, T1);
@@ -378,15 +610,14 @@
                 stl_phys(T0 & ~3, T1);
                 break;
             case 8:
-                stl_phys(T0 & ~3, T1);
-                stl_phys((T0 + 4) & ~3, T2);
+                stq_phys(T0 & ~7, ((uint64_t)T1 << 32) | T2);
                 break;
             }
-	}
-	return;
+        }
+        return;
     case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
     case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
-	{
+        {
             switch(size) {
             case 1:
                 stb_phys((target_phys_addr_t)T0
@@ -402,14 +633,13 @@
                            | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
                 break;
             case 8:
-                stl_phys((target_phys_addr_t)(T0 & ~3)
-                           | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
-                stl_phys((target_phys_addr_t)((T0 + 4) & ~3)
-                           | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
+                stq_phys((target_phys_addr_t)(T0 & ~7)
+                           | ((target_phys_addr_t)(asi & 0xf) << 32),
+                         ((uint64_t)T1 << 32) | T2);
                 break;
             }
-	}
-	return;
+        }
+        return;
     case 0x31: /* Ross RT620 I-cache flush */
     case 0x36: /* I-cache flash clear */
     case 0x37: /* D-cache flash clear */
@@ -418,23 +648,232 @@
     case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
     default:
         do_unassigned_access(T0, 1, 0, 1);
-	return;
+        return;
     }
 }
 
-#else
+#endif /* CONFIG_USER_ONLY */
+#else /* TARGET_SPARC64 */
 
+#ifdef CONFIG_USER_ONLY
 void helper_ld_asi(int asi, int size, int sign)
 {
     uint64_t ret = 0;
 
-    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
-	raise_exception(TT_PRIV_ACT);
+    if (asi < 0x80)
+        raise_exception(TT_PRIV_ACT);
 
     switch (asi) {
+    case 0x80: // Primary
+    case 0x82: // Primary no-fault
+    case 0x88: // Primary LE
+    case 0x8a: // Primary no-fault LE
+        {
+            switch(size) {
+            case 1:
+                ret = ldub_raw(T0);
+                break;
+            case 2:
+                ret = lduw_raw(T0 & ~1);
+                break;
+            case 4:
+                ret = ldl_raw(T0 & ~3);
+                break;
+            default:
+            case 8:
+                ret = ldq_raw(T0 & ~7);
+                break;
+            }
+        }
+        break;
+    case 0x81: // Secondary
+    case 0x83: // Secondary no-fault
+    case 0x89: // Secondary LE
+    case 0x8b: // Secondary no-fault LE
+        // XXX
+        break;
+    default:
+        break;
+    }
+
+    /* Convert from little endian */
+    switch (asi) {
+    case 0x88: // Primary LE
+    case 0x89: // Secondary LE
+    case 0x8a: // Primary no-fault LE
+    case 0x8b: // Secondary no-fault LE
+        switch(size) {
+        case 2:
+            ret = bswap16(ret);
+            break;
+        case 4:
+            ret = bswap32(ret);
+            break;
+        case 8:
+            ret = bswap64(ret);
+            break;
+        default:
+            break;
+        }
+    default:
+        break;
+    }
+
+    /* Convert to signed number */
+    if (sign) {
+        switch(size) {
+        case 1:
+            ret = (int8_t) ret;
+            break;
+        case 2:
+            ret = (int16_t) ret;
+            break;
+        case 4:
+            ret = (int32_t) ret;
+            break;
+        default:
+            break;
+        }
+    }
+    T1 = ret;
+}
+
+void helper_st_asi(int asi, int size)
+{
+    if (asi < 0x80)
+        raise_exception(TT_PRIV_ACT);
+
+    /* Convert to little endian */
+    switch (asi) {
+    case 0x88: // Primary LE
+    case 0x89: // Secondary LE
+        switch(size) {
+        case 2:
+            T0 = bswap16(T0);
+            break;
+        case 4:
+            T0 = bswap32(T0);
+            break;
+        case 8:
+            T0 = bswap64(T0);
+            break;
+        default:
+            break;
+        }
+    default:
+        break;
+    }
+
+    switch(asi) {
+    case 0x80: // Primary
+    case 0x88: // Primary LE
+        {
+            switch(size) {
+            case 1:
+                stb_raw(T0, T1);
+                break;
+            case 2:
+                stw_raw(T0 & ~1, T1);
+                break;
+            case 4:
+                stl_raw(T0 & ~3, T1);
+                break;
+            case 8:
+            default:
+                stq_raw(T0 & ~7, T1);
+                break;
+            }
+        }
+        break;
+    case 0x81: // Secondary
+    case 0x89: // Secondary LE
+        // XXX
+        return;
+
+    case 0x82: // Primary no-fault, RO
+    case 0x83: // Secondary no-fault, RO
+    case 0x8a: // Primary no-fault LE, RO
+    case 0x8b: // Secondary no-fault LE, RO
+    default:
+        do_unassigned_access(T0, 1, 0, 1);
+        return;
+    }
+}
+
+#else /* CONFIG_USER_ONLY */
+
+void helper_ld_asi(int asi, int size, int sign)
+{
+    uint64_t ret = 0;
+
+    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
+        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
+        raise_exception(TT_PRIV_ACT);
+
+    switch (asi) {
+    case 0x10: // As if user primary
+    case 0x18: // As if user primary LE
+    case 0x80: // Primary
+    case 0x82: // Primary no-fault
+    case 0x88: // Primary LE
+    case 0x8a: // Primary no-fault LE
+        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
+            if (env->hpstate & HS_PRIV) {
+                switch(size) {
+                case 1:
+                    ret = ldub_hypv(T0);
+                    break;
+                case 2:
+                    ret = lduw_hypv(T0 & ~1);
+                    break;
+                case 4:
+                    ret = ldl_hypv(T0 & ~3);
+                    break;
+                default:
+                case 8:
+                    ret = ldq_hypv(T0 & ~7);
+                    break;
+                }
+            } else {
+                switch(size) {
+                case 1:
+                    ret = ldub_kernel(T0);
+                    break;
+                case 2:
+                    ret = lduw_kernel(T0 & ~1);
+                    break;
+                case 4:
+                    ret = ldl_kernel(T0 & ~3);
+                    break;
+                default:
+                case 8:
+                    ret = ldq_kernel(T0 & ~7);
+                    break;
+                }
+            }
+        } else {
+            switch(size) {
+            case 1:
+                ret = ldub_user(T0);
+                break;
+            case 2:
+                ret = lduw_user(T0 & ~1);
+                break;
+            case 4:
+                ret = ldl_user(T0 & ~3);
+                break;
+            default:
+            case 8:
+                ret = ldq_user(T0 & ~7);
+                break;
+            }
+        }
+        break;
     case 0x14: // Bypass
     case 0x15: // Bypass, non-cacheable
-	{
+    case 0x1c: // Bypass LE
+    case 0x1d: // Bypass, non-cacheable LE
+        {
             switch(size) {
             case 1:
                 ret = ldub_phys(T0);
@@ -450,77 +889,71 @@
                 ret = ldq_phys(T0 & ~7);
                 break;
             }
-	    break;
-	}
+            break;
+        }
     case 0x04: // Nucleus
     case 0x0c: // Nucleus Little Endian (LE)
-    case 0x10: // As if user primary
     case 0x11: // As if user secondary
-    case 0x18: // As if user primary LE
     case 0x19: // As if user secondary LE
-    case 0x1c: // Bypass LE
-    case 0x1d: // Bypass, non-cacheable LE
     case 0x24: // Nucleus quad LDD 128 bit atomic
     case 0x2c: // Nucleus quad LDD 128 bit atomic
     case 0x4a: // UPA config
-    case 0x82: // Primary no-fault
+    case 0x81: // Secondary
     case 0x83: // Secondary no-fault
-    case 0x88: // Primary LE
     case 0x89: // Secondary LE
-    case 0x8a: // Primary no-fault LE
     case 0x8b: // Secondary no-fault LE
-	// XXX
-	break;
+        // XXX
+        break;
     case 0x45: // LSU
-	ret = env->lsu;
-	break;
+        ret = env->lsu;
+        break;
     case 0x50: // I-MMU regs
-	{
-	    int reg = (T0 >> 3) & 0xf;
+        {
+            int reg = (T0 >> 3) & 0xf;
 
-	    ret = env->immuregs[reg];
-	    break;
-	}
+            ret = env->immuregs[reg];
+            break;
+        }
     case 0x51: // I-MMU 8k TSB pointer
     case 0x52: // I-MMU 64k TSB pointer
     case 0x55: // I-MMU data access
-	// XXX
-	break;
+        // XXX
+        break;
     case 0x56: // I-MMU tag read
-	{
-	    unsigned int i;
+        {
+            unsigned int i;
 
-	    for (i = 0; i < 64; i++) {
-		// Valid, ctx match, vaddr match
-		if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
-		    env->itlb_tag[i] == T0) {
-		    ret = env->itlb_tag[i];
-		    break;
-		}
-	    }
-	    break;
-	}
+            for (i = 0; i < 64; i++) {
+                // Valid, ctx match, vaddr match
+                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
+                    env->itlb_tag[i] == T0) {
+                    ret = env->itlb_tag[i];
+                    break;
+                }
+            }
+            break;
+        }
     case 0x58: // D-MMU regs
-	{
-	    int reg = (T0 >> 3) & 0xf;
+        {
+            int reg = (T0 >> 3) & 0xf;
 
-	    ret = env->dmmuregs[reg];
-	    break;
-	}
+            ret = env->dmmuregs[reg];
+            break;
+        }
     case 0x5e: // D-MMU tag read
-	{
-	    unsigned int i;
+        {
+            unsigned int i;
 
-	    for (i = 0; i < 64; i++) {
-		// Valid, ctx match, vaddr match
-		if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
-		    env->dtlb_tag[i] == T0) {
-		    ret = env->dtlb_tag[i];
-		    break;
-		}
-	    }
-	    break;
-	}
+            for (i = 0; i < 64; i++) {
+                // Valid, ctx match, vaddr match
+                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
+                    env->dtlb_tag[i] == T0) {
+                    ret = env->dtlb_tag[i];
+                    break;
+                }
+            }
+            break;
+        }
     case 0x59: // D-MMU 8k TSB pointer
     case 0x5a: // D-MMU 64k TSB pointer
     case 0x5b: // D-MMU data pointer
@@ -528,8 +961,8 @@
     case 0x48: // Interrupt dispatch, RO
     case 0x49: // Interrupt data receive
     case 0x7f: // Incoming interrupt vector, RO
-	// XXX
-	break;
+        // XXX
+        break;
     case 0x54: // I-MMU data in, WO
     case 0x57: // I-MMU demap, WO
     case 0x5c: // D-MMU data in, WO
@@ -537,21 +970,151 @@
     case 0x77: // Interrupt vector, WO
     default:
         do_unassigned_access(T0, 0, 0, 1);
-	ret = 0;
-	break;
+        ret = 0;
+        break;
     }
+
+    /* Convert from little endian */
+    switch (asi) {
+    case 0x0c: // Nucleus Little Endian (LE)
+    case 0x18: // As if user primary LE
+    case 0x19: // As if user secondary LE
+    case 0x1c: // Bypass LE
+    case 0x1d: // Bypass, non-cacheable LE
+    case 0x88: // Primary LE
+    case 0x89: // Secondary LE
+    case 0x8a: // Primary no-fault LE
+    case 0x8b: // Secondary no-fault LE
+        switch(size) {
+        case 2:
+            ret = bswap16(ret);
+            break;
+        case 4:
+            ret = bswap32(ret);
+            break;
+        case 8:
+            ret = bswap64(ret);
+            break;
+        default:
+            break;
+        }
+    default:
+        break;
+    }
+
+    /* Convert to signed number */
+    if (sign) {
+        switch(size) {
+        case 1:
+            ret = (int8_t) ret;
+            break;
+        case 2:
+            ret = (int16_t) ret;
+            break;
+        case 4:
+            ret = (int32_t) ret;
+            break;
+        default:
+            break;
+        }
+    }
     T1 = ret;
 }
 
-void helper_st_asi(int asi, int size, int sign)
+void helper_st_asi(int asi, int size)
 {
-    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
-	raise_exception(TT_PRIV_ACT);
+    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
+        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
+        raise_exception(TT_PRIV_ACT);
 
+    /* Convert to little endian */
+    switch (asi) {
+    case 0x0c: // Nucleus Little Endian (LE)
+    case 0x18: // As if user primary LE
+    case 0x19: // As if user secondary LE
+    case 0x1c: // Bypass LE
+    case 0x1d: // Bypass, non-cacheable LE
+    case 0x88: // Primary LE
+    case 0x89: // Secondary LE
+        switch(size) {
+        case 2:
+            T0 = bswap16(T0);
+            break;
+        case 4:
+            T0 = bswap32(T0);
+            break;
+        case 8:
+            T0 = bswap64(T0);
+            break;
+        default:
+            break;
+        }
+    default:
+        break;
+    }
+
     switch(asi) {
+    case 0x10: // As if user primary
+    case 0x18: // As if user primary LE
+    case 0x80: // Primary
+    case 0x88: // Primary LE
+        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
+            if (env->hpstate & HS_PRIV) {
+                switch(size) {
+                case 1:
+                    stb_hypv(T0, T1);
+                    break;
+                case 2:
+                    stw_hypv(T0 & ~1, T1);
+                    break;
+                case 4:
+                    stl_hypv(T0 & ~3, T1);
+                    break;
+                case 8:
+                default:
+                    stq_hypv(T0 & ~7, T1);
+                    break;
+                }
+            } else {
+                switch(size) {
+                case 1:
+                    stb_kernel(T0, T1);
+                    break;
+                case 2:
+                    stw_kernel(T0 & ~1, T1);
+                    break;
+                case 4:
+                    stl_kernel(T0 & ~3, T1);
+                    break;
+                case 8:
+                default:
+                    stq_kernel(T0 & ~7, T1);
+                    break;
+                }
+            }
+        } else {
+            switch(size) {
+            case 1:
+                stb_user(T0, T1);
+                break;
+            case 2:
+                stw_user(T0 & ~1, T1);
+                break;
+            case 4:
+                stl_user(T0 & ~3, T1);
+                break;
+            case 8:
+            default:
+                stq_user(T0 & ~7, T1);
+                break;
+            }
+        }
+        break;
     case 0x14: // Bypass
     case 0x15: // Bypass, non-cacheable
-	{
+    case 0x1c: // Bypass LE
+    case 0x1d: // Bypass, non-cacheable LE
+        {
             switch(size) {
             case 1:
                 stb_phys(T0, T1);
@@ -567,46 +1130,42 @@
                 stq_phys(T0 & ~7, T1);
                 break;
             }
-	}
-	return;
+        }
+        return;
     case 0x04: // Nucleus
     case 0x0c: // Nucleus Little Endian (LE)
-    case 0x10: // As if user primary
     case 0x11: // As if user secondary
-    case 0x18: // As if user primary LE
     case 0x19: // As if user secondary LE
-    case 0x1c: // Bypass LE
-    case 0x1d: // Bypass, non-cacheable LE
     case 0x24: // Nucleus quad LDD 128 bit atomic
     case 0x2c: // Nucleus quad LDD 128 bit atomic
     case 0x4a: // UPA config
-    case 0x88: // Primary LE
+    case 0x81: // Secondary
     case 0x89: // Secondary LE
-	// XXX
-	return;
+        // XXX
+        return;
     case 0x45: // LSU
-	{
-	    uint64_t oldreg;
+        {
+            uint64_t oldreg;
 
-	    oldreg = env->lsu;
-	    env->lsu = T1 & (DMMU_E | IMMU_E);
-	    // Mappings generated during D/I MMU disabled mode are
-	    // invalid in normal mode
-	    if (oldreg != env->lsu) {
+            oldreg = env->lsu;
+            env->lsu = T1 & (DMMU_E | IMMU_E);
+            // Mappings generated during D/I MMU disabled mode are
+            // invalid in normal mode
+            if (oldreg != env->lsu) {
+                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
 #ifdef DEBUG_MMU
-                printf("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
-		dump_mmu(env);
+                dump_mmu(env);
 #endif
-		tlb_flush(env, 1);
-	    }
-	    return;
-	}
+                tlb_flush(env, 1);
+            }
+            return;
+        }
     case 0x50: // I-MMU regs
-	{
-	    int reg = (T0 >> 3) & 0xf;
-	    uint64_t oldreg;
+        {
+            int reg = (T0 >> 3) & 0xf;
+            uint64_t oldreg;
 
-	    oldreg = env->immuregs[reg];
+            oldreg = env->immuregs[reg];
             switch(reg) {
             case 0: // RO
             case 4:
@@ -617,73 +1176,73 @@
             case 8:
                 return;
             case 3: // SFSR
-		if ((T1 & 1) == 0)
-		    T1 = 0; // Clear SFSR
+                if ((T1 & 1) == 0)
+                    T1 = 0; // Clear SFSR
                 break;
             case 5: // TSB access
             case 6: // Tag access
             default:
                 break;
             }
-	    env->immuregs[reg] = T1;
-#ifdef DEBUG_MMU
+            env->immuregs[reg] = T1;
             if (oldreg != env->immuregs[reg]) {
-                printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
+                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
             }
-	    dump_mmu(env);
+#ifdef DEBUG_MMU
+            dump_mmu(env);
 #endif
-	    return;
-	}
+            return;
+        }
     case 0x54: // I-MMU data in
-	{
-	    unsigned int i;
+        {
+            unsigned int i;
 
-	    // Try finding an invalid entry
-	    for (i = 0; i < 64; i++) {
-		if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
-		    env->itlb_tag[i] = env->immuregs[6];
-		    env->itlb_tte[i] = T1;
-		    return;
-		}
-	    }
-	    // Try finding an unlocked entry
-	    for (i = 0; i < 64; i++) {
-		if ((env->itlb_tte[i] & 0x40) == 0) {
-		    env->itlb_tag[i] = env->immuregs[6];
-		    env->itlb_tte[i] = T1;
-		    return;
-		}
-	    }
-	    // error state?
-	    return;
-	}
+            // Try finding an invalid entry
+            for (i = 0; i < 64; i++) {
+                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
+                    env->itlb_tag[i] = env->immuregs[6];
+                    env->itlb_tte[i] = T1;
+                    return;
+                }
+            }
+            // Try finding an unlocked entry
+            for (i = 0; i < 64; i++) {
+                if ((env->itlb_tte[i] & 0x40) == 0) {
+                    env->itlb_tag[i] = env->immuregs[6];
+                    env->itlb_tte[i] = T1;
+                    return;
+                }
+            }
+            // error state?
+            return;
+        }
     case 0x55: // I-MMU data access
-	{
-	    unsigned int i = (T0 >> 3) & 0x3f;
+        {
+            unsigned int i = (T0 >> 3) & 0x3f;
 
-	    env->itlb_tag[i] = env->immuregs[6];
-	    env->itlb_tte[i] = T1;
-	    return;
-	}
+            env->itlb_tag[i] = env->immuregs[6];
+            env->itlb_tte[i] = T1;
+            return;
+        }
     case 0x57: // I-MMU demap
-	// XXX
-	return;
+        // XXX
+        return;
     case 0x58: // D-MMU regs
-	{
-	    int reg = (T0 >> 3) & 0xf;
-	    uint64_t oldreg;
+        {
+            int reg = (T0 >> 3) & 0xf;
+            uint64_t oldreg;
 
-	    oldreg = env->dmmuregs[reg];
+            oldreg = env->dmmuregs[reg];
             switch(reg) {
             case 0: // RO
             case 4:
                 return;
             case 3: // SFSR
-		if ((T1 & 1) == 0) {
-		    T1 = 0; // Clear SFSR, Fault address
-		    env->dmmuregs[4] = 0;
-		}
-		env->dmmuregs[reg] = T1;
+                if ((T1 & 1) == 0) {
+                    T1 = 0; // Clear SFSR, Fault address
+                    env->dmmuregs[4] = 0;
+                }
+                env->dmmuregs[reg] = T1;
                 break;
             case 1: // Primary context
             case 2: // Secondary context
@@ -694,50 +1253,50 @@
             default:
                 break;
             }
-	    env->dmmuregs[reg] = T1;
-#ifdef DEBUG_MMU
+            env->dmmuregs[reg] = T1;
             if (oldreg != env->dmmuregs[reg]) {
-                printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
+                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
             }
-	    dump_mmu(env);
+#ifdef DEBUG_MMU
+            dump_mmu(env);
 #endif
-	    return;
-	}
+            return;
+        }
     case 0x5c: // D-MMU data in
-	{
-	    unsigned int i;
+        {
+            unsigned int i;
 
-	    // Try finding an invalid entry
-	    for (i = 0; i < 64; i++) {
-		if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
-		    env->dtlb_tag[i] = env->dmmuregs[6];
-		    env->dtlb_tte[i] = T1;
-		    return;
-		}
-	    }
-	    // Try finding an unlocked entry
-	    for (i = 0; i < 64; i++) {
-		if ((env->dtlb_tte[i] & 0x40) == 0) {
-		    env->dtlb_tag[i] = env->dmmuregs[6];
-		    env->dtlb_tte[i] = T1;
-		    return;
-		}
-	    }
-	    // error state?
-	    return;
-	}
+            // Try finding an invalid entry
+            for (i = 0; i < 64; i++) {
+                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
+                    env->dtlb_tag[i] = env->dmmuregs[6];
+                    env->dtlb_tte[i] = T1;
+                    return;
+                }
+            }
+            // Try finding an unlocked entry
+            for (i = 0; i < 64; i++) {
+                if ((env->dtlb_tte[i] & 0x40) == 0) {
+                    env->dtlb_tag[i] = env->dmmuregs[6];
+                    env->dtlb_tte[i] = T1;
+                    return;
+                }
+            }
+            // error state?
+            return;
+        }
     case 0x5d: // D-MMU data access
-	{
-	    unsigned int i = (T0 >> 3) & 0x3f;
+        {
+            unsigned int i = (T0 >> 3) & 0x3f;
 
-	    env->dtlb_tag[i] = env->dmmuregs[6];
-	    env->dtlb_tte[i] = T1;
-	    return;
-	}
+            env->dtlb_tag[i] = env->dmmuregs[6];
+            env->dtlb_tte[i] = T1;
+            return;
+        }
     case 0x5f: // D-MMU demap
     case 0x49: // Interrupt data receive
-	// XXX
-	return;
+        // XXX
+        return;
     case 0x51: // I-MMU 8k TSB pointer, RO
     case 0x52: // I-MMU 64k TSB pointer, RO
     case 0x56: // I-MMU tag read, RO
@@ -753,12 +1312,101 @@
     case 0x8b: // Secondary no-fault LE, RO
     default:
         do_unassigned_access(T0, 1, 0, 1);
-	return;
+        return;
     }
 }
-#endif
-#endif /* !CONFIG_USER_ONLY */
+#endif /* CONFIG_USER_ONLY */
 
+void helper_ldf_asi(int asi, int size, int rd)
+{
+    target_ulong tmp_T0 = T0, tmp_T1 = T1;
+    unsigned int i;
+
+    switch (asi) {
+    case 0xf0: // Block load primary
+    case 0xf1: // Block load secondary
+    case 0xf8: // Block load primary LE
+    case 0xf9: // Block load secondary LE
+        if (rd & 7) {
+            raise_exception(TT_ILL_INSN);
+            return;
+        }
+        if (T0 & 0x3f) {
+            raise_exception(TT_UNALIGNED);
+            return;
+        }
+        for (i = 0; i < 16; i++) {
+            helper_ld_asi(asi & 0x8f, 4, 0);
+            *(uint32_t *)&env->fpr[rd++] = T1;
+            T0 += 4;
+        }
+        T0 = tmp_T0;
+        T1 = tmp_T1;
+
+        return;
+    default:
+        break;
+    }
+
+    helper_ld_asi(asi, size, 0);
+    switch(size) {
+    default:
+    case 4:
+        *((uint32_t *)&FT0) = T1;
+        break;
+    case 8:
+        *((int64_t *)&DT0) = T1;
+        break;
+    }
+    T1 = tmp_T1;
+}
+
+void helper_stf_asi(int asi, int size, int rd)
+{
+    target_ulong tmp_T0 = T0, tmp_T1 = T1;
+    unsigned int i;
+
+    switch (asi) {
+    case 0xf0: // Block store primary
+    case 0xf1: // Block store secondary
+    case 0xf8: // Block store primary LE
+    case 0xf9: // Block store secondary LE
+        if (rd & 7) {
+            raise_exception(TT_ILL_INSN);
+            return;
+        }
+        if (T0 & 0x3f) {
+            raise_exception(TT_UNALIGNED);
+            return;
+        }
+        for (i = 0; i < 16; i++) {
+            T1 = *(uint32_t *)&env->fpr[rd++];
+            helper_st_asi(asi & 0x8f, 4);
+            T0 += 4;
+        }
+        T0 = tmp_T0;
+        T1 = tmp_T1;
+
+        return;
+    default:
+        break;
+    }
+
+    switch(size) {
+    default:
+    case 4:
+        T1 = *((uint32_t *)&FT0);
+        break;
+    case 8:
+        T1 = *((int64_t *)&DT0);
+        break;
+    }
+    helper_st_asi(asi, size);
+    T1 = tmp_T1;
+}
+
+#endif /* TARGET_SPARC64 */
+
 #ifndef TARGET_SPARC64
 void helper_rett()
 {
@@ -783,17 +1431,17 @@
     switch (env->fsr & FSR_RD_MASK) {
     case FSR_RD_NEAREST:
         rnd_mode = float_round_nearest_even;
-	break;
+        break;
     default:
     case FSR_RD_ZERO:
         rnd_mode = float_round_to_zero;
-	break;
+        break;
     case FSR_RD_POS:
         rnd_mode = float_round_up;
-	break;
+        break;
     case FSR_RD_NEG:
         rnd_mode = float_round_down;
-	break;
+        break;
     }
     set_float_rounding_mode(rnd_mode, &env->fp_status);
 }
@@ -822,12 +1470,7 @@
 
 void do_popc()
 {
-    T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL);
-    T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL);
-    T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL);
-    T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL);
-    T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
-    T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
+    T0 = ctpop64(T1);
 }
 
 static inline uint64_t *get_gregset(uint64_t pstate)
@@ -835,13 +1478,13 @@
     switch (pstate) {
     default:
     case 0:
-	return env->bgregs;
+        return env->bgregs;
     case PS_AG:
-	return env->agregs;
+        return env->agregs;
     case PS_MG:
-	return env->mgregs;
+        return env->mgregs;
     case PS_IG:
-	return env->igregs;
+        return env->igregs;
     }
 }
 
@@ -853,11 +1496,11 @@
     pstate_regs = env->pstate & 0xc01;
     new_pstate_regs = new_pstate & 0xc01;
     if (new_pstate_regs != pstate_regs) {
-	// Switch global register bank
-	src = get_gregset(new_pstate_regs);
-	dst = get_gregset(pstate_regs);
-	memcpy32(dst, env->gregs);
-	memcpy32(env->gregs, src);
+        // Switch global register bank
+        src = get_gregset(new_pstate_regs);
+        dst = get_gregset(pstate_regs);
+        memcpy32(dst, env->gregs);
+        memcpy32(env->gregs, src);
     }
     env->pstate = new_pstate;
 }
@@ -927,36 +1570,36 @@
 {
 #ifdef DEBUG_PCALL
     if (loglevel & CPU_LOG_INT) {
-	static int count;
-	fprintf(logfile, "%6d: v=%04x pc=%016" PRIx64 " npc=%016" PRIx64 " SP=%016" PRIx64 "\n",
+        static int count;
+        fprintf(logfile, "%6d: v=%04x pc=%016" PRIx64 " npc=%016" PRIx64 " SP=%016" PRIx64 "\n",
                 count, intno,
                 env->pc,
                 env->npc, env->regwptr[6]);
-	cpu_dump_state(env, logfile, fprintf, 0);
+        cpu_dump_state(env, logfile, fprintf, 0);
 #if 0
-	{
-	    int i;
-	    uint8_t *ptr;
+        {
+            int i;
+            uint8_t *ptr;
 
-	    fprintf(logfile, "       code=");
-	    ptr = (uint8_t *)env->pc;
-	    for(i = 0; i < 16; i++) {
-		fprintf(logfile, " %02x", ldub(ptr + i));
-	    }
-	    fprintf(logfile, "\n");
-	}
+            fprintf(logfile, "       code=");
+            ptr = (uint8_t *)env->pc;
+            for(i = 0; i < 16; i++) {
+                fprintf(logfile, " %02x", ldub(ptr + i));
+            }
+            fprintf(logfile, "\n");
+        }
 #endif
-	count++;
+        count++;
     }
 #endif
 #if !defined(CONFIG_USER_ONLY)
     if (env->tl == MAXTL) {
         cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
-	return;
+        return;
     }
 #endif
     env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
-	((env->pstate & 0xf3f) << 8) | GET_CWP64(env);
+        ((env->pstate & 0xf3f) << 8) | GET_CWP64(env);
     env->tpc[env->tl] = env->pc;
     env->tnpc[env->tl] = env->npc;
     env->tt[env->tl] = intno;
@@ -971,11 +1614,11 @@
     env->tbr &= ~0x7fffULL;
     env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
     if (env->tl < MAXTL - 1) {
-	env->tl++;
+        env->tl++;
     } else {
-	env->pstate |= PS_RED;
-	if (env->tl != MAXTL)
-	    env->tl++;
+        env->pstate |= PS_RED;
+        if (env->tl != MAXTL)
+            env->tl++;
     }
     env->pc = env->tbr;
     env->npc = env->pc + 4;
@@ -988,32 +1631,32 @@
 
 #ifdef DEBUG_PCALL
     if (loglevel & CPU_LOG_INT) {
-	static int count;
-	fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
+        static int count;
+        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
                 count, intno,
                 env->pc,
                 env->npc, env->regwptr[6]);
-	cpu_dump_state(env, logfile, fprintf, 0);
+        cpu_dump_state(env, logfile, fprintf, 0);
 #if 0
-	{
-	    int i;
-	    uint8_t *ptr;
+        {
+            int i;
+            uint8_t *ptr;
 
-	    fprintf(logfile, "       code=");
-	    ptr = (uint8_t *)env->pc;
-	    for(i = 0; i < 16; i++) {
-		fprintf(logfile, " %02x", ldub(ptr + i));
-	    }
-	    fprintf(logfile, "\n");
-	}
+            fprintf(logfile, "       code=");
+            ptr = (uint8_t *)env->pc;
+            for(i = 0; i < 16; i++) {
+                fprintf(logfile, " %02x", ldub(ptr + i));
+            }
+            fprintf(logfile, "\n");
+        }
 #endif
-	count++;
+        count++;
     }
 #endif
 #if !defined(CONFIG_USER_ONLY)
     if (env->psret == 0) {
         cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
-	return;
+        return;
     }
 #endif
     env->psret = 0;
@@ -1037,7 +1680,11 @@
 
 #define MMUSUFFIX _mmu
 #define ALIGNED_ONLY
-#define GETPC() (__builtin_return_address(0))
+#ifdef __s390__
+# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
+#else
+# define GETPC() (__builtin_return_address(0))
+#endif
 
 #define SHIFT 0
 #include "softmmu_template.h"
@@ -1064,7 +1711,7 @@
    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)
+void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 {
     TranslationBlock *tb;
     int ret;
@@ -1076,7 +1723,7 @@
     saved_env = env;
     env = cpu_single_env;
 
-    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
+    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
     if (ret) {
         if (retaddr) {
             /* now we have a real cpu fault */
@@ -1106,7 +1753,7 @@
     saved_env = env;
     env = cpu_single_env;
     if (env->mmuregs[3]) /* Fault status register */
-	env->mmuregs[3] = 1; /* overflow (not read before another fault) */
+        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
     if (is_asi)
         env->mmuregs[3] |= 1 << 16;
     if (env->psrs)

Modified: trunk/src/host/qemu-neo1973/target-sparc/op_mem.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/op_mem.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-sparc/op_mem.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1,3 +1,9 @@
+#ifdef TARGET_ABI32
+#define ADDR(x) ((x) & 0xffffffff)
+#else
+#define ADDR(x) (x)
+#endif
+
 /***                             Integer load                              ***/
 #define SPARC_LD_OP(name, qp)                                                 \
 void OPPROTO glue(glue(op_, name), MEMSUFFIX)(void)                           \
@@ -2,9 +8,9 @@
 {                                                                             \
-    T1 = (target_ulong)glue(qp, MEMSUFFIX)(T0);				\
+    T1 = (target_ulong)glue(qp, MEMSUFFIX)(ADDR(T0));                         \
 }
 
-#define SPARC_LD_OP_S(name, qp)						\
-    void OPPROTO glue(glue(op_, name), MEMSUFFIX)(void)			\
-    {									\
-	T1 = (target_long)glue(qp, MEMSUFFIX)(T0);			\
+#define SPARC_LD_OP_S(name, qp)                                         \
+    void OPPROTO glue(glue(op_, name), MEMSUFFIX)(void)                 \
+    {                                                                   \
+        T1 = (target_long)glue(qp, MEMSUFFIX)(ADDR(T0));                      \
     }
@@ -14,7 +20,7 @@
 #define SPARC_ST_OP(name, op)                                                 \
 void OPPROTO glue(glue(op_, name), MEMSUFFIX)(void)                           \
 {                                                                             \
-    glue(op, MEMSUFFIX)(T0, T1);                                      \
+    glue(op, MEMSUFFIX)(ADDR(T0), T1);                                      \
 }
 
 SPARC_LD_OP(ld, ldl);
@@ -30,87 +36,64 @@
 
 void OPPROTO glue(op_std, MEMSUFFIX)(void)
 {
-    glue(stl, MEMSUFFIX)(T0, T1);
-    glue(stl, MEMSUFFIX)((T0 + 4), T2);
+    uint64_t tmp = ((uint64_t)T1 << 32) | (uint64_t)(T2 & 0xffffffff);
+
+    glue(stq, MEMSUFFIX)(ADDR(T0), tmp);
 }
 
 void OPPROTO glue(op_ldstub, MEMSUFFIX)(void)
 {
-    T1 = glue(ldub, MEMSUFFIX)(T0);
-    glue(stb, MEMSUFFIX)(T0, 0xff);     /* XXX: Should be Atomically */
+    T1 = glue(ldub, MEMSUFFIX)(ADDR(T0));
+    glue(stb, MEMSUFFIX)(ADDR(T0), 0xff);     /* XXX: Should be Atomically */
 }
 
 void OPPROTO glue(op_swap, MEMSUFFIX)(void)
 {
-    target_ulong tmp = glue(ldl, MEMSUFFIX)(T0);
-    glue(stl, MEMSUFFIX)(T0, T1);       /* XXX: Should be Atomically */
+    target_ulong tmp = glue(ldl, MEMSUFFIX)(ADDR(T0));
+    glue(stl, MEMSUFFIX)(ADDR(T0), T1);       /* XXX: Should be Atomically */
     T1 = tmp;
 }
 
 void OPPROTO glue(op_ldd, MEMSUFFIX)(void)
 {
-    T1 = glue(ldl, MEMSUFFIX)(T0);
-    T0 = glue(ldl, MEMSUFFIX)((T0 + 4));
+    uint64_t tmp;
+
+    tmp = glue(ldq, MEMSUFFIX)(ADDR(T0));
+    T1 = tmp >> 32;
+    T0 = tmp & 0xffffffff;
 }
 
 /***                         Floating-point store                          ***/
 void OPPROTO glue(op_stf, MEMSUFFIX) (void)
 {
-    glue(stfl, MEMSUFFIX)(T0, FT0);
+    glue(stfl, MEMSUFFIX)(ADDR(T0), FT0);
 }
 
 void OPPROTO glue(op_stdf, MEMSUFFIX) (void)
 {
-    glue(stfq, MEMSUFFIX)(T0, DT0);
+    glue(stfq, MEMSUFFIX)(ADDR(T0), DT0);
 }
 
 /***                         Floating-point load                           ***/
 void OPPROTO glue(op_ldf, MEMSUFFIX) (void)
 {
-    FT0 = glue(ldfl, MEMSUFFIX)(T0);
+    FT0 = glue(ldfl, MEMSUFFIX)(ADDR(T0));
 }
 
 void OPPROTO glue(op_lddf, MEMSUFFIX) (void)
 {
-    DT0 = glue(ldfq, MEMSUFFIX)(T0);
+    DT0 = glue(ldfq, MEMSUFFIX)(ADDR(T0));
 }
 
 #ifdef TARGET_SPARC64
-/* XXX: Should be Atomically */
-/* XXX: There are no cas[x] instructions, only cas[x]a */
-void OPPROTO glue(op_cas, MEMSUFFIX)(void)
-{
-    uint32_t tmp;
-
-    tmp = glue(ldl, MEMSUFFIX)(T0);
-    T2 &=  0xffffffffULL;
-    if (tmp == (T1 & 0xffffffffULL)) {
-	glue(stl, MEMSUFFIX)(T0, T2);
-    }
-    T2 = tmp;
-}
-
-void OPPROTO glue(op_casx, MEMSUFFIX)(void)
-{
-    uint64_t tmp;
-
-    // XXX
-    tmp = (uint64_t)glue(ldl, MEMSUFFIX)(T0) << 32;
-    tmp |= glue(ldl, MEMSUFFIX)(T0);
-    if (tmp == T1) {
-	glue(stq, MEMSUFFIX)(T0, T2);
-    }
-    T2 = tmp;
-}
-
 void OPPROTO glue(op_lduw, MEMSUFFIX)(void)
 {
-    T1 = (uint64_t)(glue(ldl, MEMSUFFIX)(T0) & 0xffffffff);
+    T1 = (uint64_t)(glue(ldl, MEMSUFFIX)(ADDR(T0)) & 0xffffffff);
 }
 
 void OPPROTO glue(op_ldsw, MEMSUFFIX)(void)
 {
-    T1 = (int64_t)(glue(ldl, MEMSUFFIX)(T0) & 0xffffffff);
+    T1 = (int64_t)(glue(ldl, MEMSUFFIX)(ADDR(T0)) & 0xffffffff);
 }
 
 SPARC_LD_OP(ldx, ldq);

Modified: trunk/src/host/qemu-neo1973/target-sparc/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/translate.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/target-sparc/translate.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -45,8 +45,8 @@
                          according to jump_pc[T2] */
 
 typedef struct DisasContext {
-    target_ulong pc;	/* current Program Counter: integer or DYNAMIC_PC */
-    target_ulong npc;	/* next PC: integer or DYNAMIC_PC or JUMP_PC */
+    target_ulong pc;    /* current Program Counter: integer or DYNAMIC_PC */
+    target_ulong npc;   /* next PC: integer or DYNAMIC_PC or JUMP_PC */
     target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
     int is_br;
     int mem_idx;
@@ -87,7 +87,7 @@
 #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
 
 #ifdef TARGET_SPARC64
-#define DFPREG(r) (((r & 1) << 6) | (r & 0x1e))
+#define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
 #else
 #define DFPREG(r) (r & 0x1e)
 #endif
@@ -346,119 +346,34 @@
 GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
 GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
 
-#ifdef ALIGN_7_BUGS_FIXED
-#else
-#ifndef CONFIG_USER_ONLY
-#define gen_op_check_align_T0_7()
-#endif
-#endif
-
+/* moves */
+#ifdef CONFIG_USER_ONLY
+#define supervisor(dc) 0
 #ifdef TARGET_SPARC64
-// 'a' versions allowed to user depending on asi
-#if defined(CONFIG_USER_ONLY)
-#define supervisor(dc) 0
 #define hypervisor(dc) 0
+#endif
 #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) \
-    {									\
-	int asi, offset;						\
-									\
-	if (IS_IMM) {							\
-	    offset = GET_FIELD(insn, 25, 31);				\
-	    if (is_ld)							\
-		gen_op_ld_asi_reg(offset, size, sign);			\
-	    else							\
-		gen_op_st_asi_reg(offset, size, sign);			\
-	    return;							\
-	}								\
-	asi = GET_FIELD(insn, 19, 26);					\
-	switch (asi) {							\
-	case 0x80: /* Primary address space */				\
-	    gen_op_##width##_raw();					\
-	    break;							\
-	case 0x82: /* Primary address space, non-faulting load */       \
-	    gen_op_##width##_raw();					\
-	    break;							\
-	default:							\
-            break;							\
-	}								\
-    }
-
 #else
-#define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
-#define OP_LD_TABLE(width)						\
+#define supervisor(dc) (dc->mem_idx >= 1)
+#ifdef TARGET_SPARC64
+#define hypervisor(dc) (dc->mem_idx == 2)
+#define OP_LD_TABLE(width)                                              \
     static GenOpFunc * const gen_op_##width[] = {                       \
-	&gen_op_##width##_user,						\
-	&gen_op_##width##_kernel,					\
-    };									\
-									\
-    static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
-    {									\
-	int asi, offset;						\
-									\
-	if (IS_IMM) {							\
-	    offset = GET_FIELD(insn, 25, 31);				\
-	    if (is_ld)							\
-		gen_op_ld_asi_reg(offset, size, sign);			\
-	    else							\
-		gen_op_st_asi_reg(offset, size, sign);			\
-	    return;							\
-	}								\
-	asi = GET_FIELD(insn, 19, 26);					\
-	if (is_ld)							\
-	    gen_op_ld_asi(asi, size, sign);				\
-	else								\
-	    gen_op_st_asi(asi, size, sign);				\
-    }
-
-#define supervisor(dc) (dc->mem_idx == 1)
-#define hypervisor(dc) (dc->mem_idx == 2)
+        &gen_op_##width##_user,                                         \
+        &gen_op_##width##_kernel,                                       \
+        &gen_op_##width##_hypv,                                         \
+    };
+#else
+#define OP_LD_TABLE(width)                                              \
+    static GenOpFunc * const gen_op_##width[] = {                       \
+        &gen_op_##width##_user,                                         \
+        &gen_op_##width##_kernel,                                       \
+    };
 #endif
-#else
-#if defined(CONFIG_USER_ONLY)
-#define gen_op_ldst(name)        gen_op_##name##_raw()
-#define OP_LD_TABLE(width)
-#define supervisor(dc) 0
-#else
 #define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
-#define OP_LD_TABLE(width)						      \
-static GenOpFunc * const gen_op_##width[] = {                                 \
-    &gen_op_##width##_user,                                                   \
-    &gen_op_##width##_kernel,                                                 \
-};                                                                            \
-                                                                              \
-static void gen_op_##width##a(int insn, int is_ld, int size, int sign)        \
-{                                                                             \
-    int asi;                                                                  \
-                                                                              \
-    asi = GET_FIELD(insn, 19, 26);                                            \
-    switch (asi) {                                                            \
-	case 10: /* User data access */                                       \
-	    gen_op_##width##_user();                                          \
-	    break;                                                            \
-	case 11: /* Supervisor data access */                                 \
-	    gen_op_##width##_kernel();                                        \
-	    break;                                                            \
-        case 0x20 ... 0x2f: /* MMU passthrough */			      \
-	    if (is_ld)                                                        \
-		gen_op_ld_asi(asi, size, sign);				      \
-	    else                                                              \
-		gen_op_st_asi(asi, size, sign);				      \
-	    break;                                                            \
-	default:                                                              \
-	    if (is_ld)                                                        \
-		gen_op_ld_asi(asi, size, sign);			              \
-	    else                                                              \
-		gen_op_st_asi(asi, size, sign);				      \
-            break;                                                            \
-    }                                                                         \
-}
-
-#define supervisor(dc) (dc->mem_idx == 1)
 #endif
-#endif
 
+#ifndef CONFIG_USER_ONLY
 OP_LD_TABLE(ld);
 OP_LD_TABLE(st);
 OP_LD_TABLE(ldub);
@@ -481,10 +396,194 @@
 OP_LD_TABLE(ldsw);
 OP_LD_TABLE(ldx);
 OP_LD_TABLE(stx);
-OP_LD_TABLE(cas);
-OP_LD_TABLE(casx);
 #endif
+#endif
 
+/* asi moves */
+#ifdef TARGET_SPARC64
+static inline void gen_ld_asi(int insn, int size, int sign)
+{
+    int asi, offset;
+
+    if (IS_IMM) {
+        offset = GET_FIELD(insn, 25, 31);
+        gen_op_ld_asi_reg(offset, size, sign);
+    } else {
+        asi = GET_FIELD(insn, 19, 26);
+        gen_op_ld_asi(asi, size, sign);
+    }
+}
+
+static inline void gen_st_asi(int insn, int size)
+{
+    int asi, offset;
+
+    if (IS_IMM) {
+        offset = GET_FIELD(insn, 25, 31);
+        gen_op_st_asi_reg(offset, size);
+    } else {
+        asi = GET_FIELD(insn, 19, 26);
+        gen_op_st_asi(asi, size);
+    }
+}
+
+static inline void gen_ldf_asi(int insn, int size)
+{
+    int asi, offset, rd;
+
+    rd = DFPREG(GET_FIELD(insn, 2, 6));
+    if (IS_IMM) {
+        offset = GET_FIELD(insn, 25, 31);
+        gen_op_ldf_asi_reg(offset, size, rd);
+    } else {
+        asi = GET_FIELD(insn, 19, 26);
+        gen_op_ldf_asi(asi, size, rd);
+    }
+}
+
+static inline void gen_stf_asi(int insn, int size)
+{
+    int asi, offset, rd;
+
+    rd = DFPREG(GET_FIELD(insn, 2, 6));
+    if (IS_IMM) {
+        offset = GET_FIELD(insn, 25, 31);
+        gen_op_stf_asi_reg(offset, size, rd);
+    } else {
+        asi = GET_FIELD(insn, 19, 26);
+        gen_op_stf_asi(asi, size, rd);
+    }
+}
+
+static inline void gen_swap_asi(int insn)
+{
+    int asi, offset;
+
+    if (IS_IMM) {
+        offset = GET_FIELD(insn, 25, 31);
+        gen_op_swap_asi_reg(offset);
+    } else {
+        asi = GET_FIELD(insn, 19, 26);
+        gen_op_swap_asi(asi);
+    }
+}
+
+static inline void gen_ldstub_asi(int insn)
+{
+    int asi, offset;
+
+    if (IS_IMM) {
+        offset = GET_FIELD(insn, 25, 31);
+        gen_op_ldstub_asi_reg(offset);
+    } else {
+        asi = GET_FIELD(insn, 19, 26);
+        gen_op_ldstub_asi(asi);
+    }
+}
+
+static inline void gen_ldda_asi(int insn)
+{
+    int asi, offset;
+
+    if (IS_IMM) {
+        offset = GET_FIELD(insn, 25, 31);
+        gen_op_ldda_asi_reg(offset);
+    } else {
+        asi = GET_FIELD(insn, 19, 26);
+        gen_op_ldda_asi(asi);
+    }
+}
+
+static inline void gen_stda_asi(int insn)
+{
+    int asi, offset;
+
+    if (IS_IMM) {
+        offset = GET_FIELD(insn, 25, 31);
+        gen_op_stda_asi_reg(offset);
+    } else {
+        asi = GET_FIELD(insn, 19, 26);
+        gen_op_stda_asi(asi);
+    }
+}
+
+static inline void gen_cas_asi(int insn)
+{
+    int asi, offset;
+
+    if (IS_IMM) {
+        offset = GET_FIELD(insn, 25, 31);
+        gen_op_cas_asi_reg(offset);
+    } else {
+        asi = GET_FIELD(insn, 19, 26);
+        gen_op_cas_asi(asi);
+    }
+}
+
+static inline void gen_casx_asi(int insn)
+{
+    int asi, offset;
+
+    if (IS_IMM) {
+        offset = GET_FIELD(insn, 25, 31);
+        gen_op_casx_asi_reg(offset);
+    } else {
+        asi = GET_FIELD(insn, 19, 26);
+        gen_op_casx_asi(asi);
+    }
+}
+
+#elif !defined(CONFIG_USER_ONLY)
+
+static inline void gen_ld_asi(int insn, int size, int sign)
+{
+    int asi;
+
+    asi = GET_FIELD(insn, 19, 26);
+    gen_op_ld_asi(asi, size, sign);
+}
+
+static inline void gen_st_asi(int insn, int size)
+{
+    int asi;
+
+    asi = GET_FIELD(insn, 19, 26);
+    gen_op_st_asi(asi, size);
+}
+
+static inline void gen_ldstub_asi(int insn)
+{
+    int asi;
+
+    asi = GET_FIELD(insn, 19, 26);
+    gen_op_ldstub_asi(asi);
+}
+
+static inline void gen_swap_asi(int insn)
+{
+    int asi;
+
+    asi = GET_FIELD(insn, 19, 26);
+    gen_op_swap_asi(asi);
+}
+
+static inline void gen_ldda_asi(int insn)
+{
+    int asi;
+
+    asi = GET_FIELD(insn, 19, 26);
+    gen_op_ld_asi(asi, 8, 0);
+}
+
+static inline void gen_stda_asi(int insn)
+{
+    int asi;
+
+    asi = GET_FIELD(insn, 19, 26);
+    gen_op_st_asi(asi, 8);
+}
+#endif
+
 static inline void gen_movl_imm_TN(int reg, uint32_t imm)
 {
     gen_op_movl_TN_im[reg](imm);
@@ -518,9 +617,9 @@
 static inline void gen_movl_reg_TN(int reg, int t)
 {
     if (reg)
-	gen_op_movl_reg_TN[t][reg] ();
+        gen_op_movl_reg_TN[t][reg] ();
     else
-	gen_movl_imm_TN(t, 0);
+        gen_movl_imm_TN(t, 0);
 }
 
 static inline void gen_movl_reg_T0(int reg)
@@ -541,7 +640,7 @@
 static inline void gen_movl_TN_reg(int reg, int t)
 {
     if (reg)
-	gen_op_movl_TN_reg[t][reg] ();
+        gen_op_movl_TN_reg[t][reg] ();
 }
 
 static inline void gen_movl_T0_reg(int reg)
@@ -699,118 +798,118 @@
 
 static GenOpFunc * const gen_cond[2][16] = {
     {
-	gen_op_eval_bn,
-	gen_op_eval_be,
-	gen_op_eval_ble,
-	gen_op_eval_bl,
-	gen_op_eval_bleu,
-	gen_op_eval_bcs,
-	gen_op_eval_bneg,
-	gen_op_eval_bvs,
-	gen_op_eval_ba,
-	gen_op_eval_bne,
-	gen_op_eval_bg,
-	gen_op_eval_bge,
-	gen_op_eval_bgu,
-	gen_op_eval_bcc,
-	gen_op_eval_bpos,
-	gen_op_eval_bvc,
+        gen_op_eval_bn,
+        gen_op_eval_be,
+        gen_op_eval_ble,
+        gen_op_eval_bl,
+        gen_op_eval_bleu,
+        gen_op_eval_bcs,
+        gen_op_eval_bneg,
+        gen_op_eval_bvs,
+        gen_op_eval_ba,
+        gen_op_eval_bne,
+        gen_op_eval_bg,
+        gen_op_eval_bge,
+        gen_op_eval_bgu,
+        gen_op_eval_bcc,
+        gen_op_eval_bpos,
+        gen_op_eval_bvc,
     },
     {
 #ifdef TARGET_SPARC64
-	gen_op_eval_bn,
-	gen_op_eval_xbe,
-	gen_op_eval_xble,
-	gen_op_eval_xbl,
-	gen_op_eval_xbleu,
-	gen_op_eval_xbcs,
-	gen_op_eval_xbneg,
-	gen_op_eval_xbvs,
-	gen_op_eval_ba,
-	gen_op_eval_xbne,
-	gen_op_eval_xbg,
-	gen_op_eval_xbge,
-	gen_op_eval_xbgu,
-	gen_op_eval_xbcc,
-	gen_op_eval_xbpos,
-	gen_op_eval_xbvc,
+        gen_op_eval_bn,
+        gen_op_eval_xbe,
+        gen_op_eval_xble,
+        gen_op_eval_xbl,
+        gen_op_eval_xbleu,
+        gen_op_eval_xbcs,
+        gen_op_eval_xbneg,
+        gen_op_eval_xbvs,
+        gen_op_eval_ba,
+        gen_op_eval_xbne,
+        gen_op_eval_xbg,
+        gen_op_eval_xbge,
+        gen_op_eval_xbgu,
+        gen_op_eval_xbcc,
+        gen_op_eval_xbpos,
+        gen_op_eval_xbvc,
 #endif
     },
 };
 
 static GenOpFunc * const gen_fcond[4][16] = {
     {
-	gen_op_eval_bn,
-	gen_op_eval_fbne,
-	gen_op_eval_fblg,
-	gen_op_eval_fbul,
-	gen_op_eval_fbl,
-	gen_op_eval_fbug,
-	gen_op_eval_fbg,
-	gen_op_eval_fbu,
-	gen_op_eval_ba,
-	gen_op_eval_fbe,
-	gen_op_eval_fbue,
-	gen_op_eval_fbge,
-	gen_op_eval_fbuge,
-	gen_op_eval_fble,
-	gen_op_eval_fbule,
-	gen_op_eval_fbo,
+        gen_op_eval_bn,
+        gen_op_eval_fbne,
+        gen_op_eval_fblg,
+        gen_op_eval_fbul,
+        gen_op_eval_fbl,
+        gen_op_eval_fbug,
+        gen_op_eval_fbg,
+        gen_op_eval_fbu,
+        gen_op_eval_ba,
+        gen_op_eval_fbe,
+        gen_op_eval_fbue,
+        gen_op_eval_fbge,
+        gen_op_eval_fbuge,
+        gen_op_eval_fble,
+        gen_op_eval_fbule,
+        gen_op_eval_fbo,
     },
 #ifdef TARGET_SPARC64
     {
-	gen_op_eval_bn,
-	gen_op_eval_fbne_fcc1,
-	gen_op_eval_fblg_fcc1,
-	gen_op_eval_fbul_fcc1,
-	gen_op_eval_fbl_fcc1,
-	gen_op_eval_fbug_fcc1,
-	gen_op_eval_fbg_fcc1,
-	gen_op_eval_fbu_fcc1,
-	gen_op_eval_ba,
-	gen_op_eval_fbe_fcc1,
-	gen_op_eval_fbue_fcc1,
-	gen_op_eval_fbge_fcc1,
-	gen_op_eval_fbuge_fcc1,
-	gen_op_eval_fble_fcc1,
-	gen_op_eval_fbule_fcc1,
-	gen_op_eval_fbo_fcc1,
+        gen_op_eval_bn,
+        gen_op_eval_fbne_fcc1,
+        gen_op_eval_fblg_fcc1,
+        gen_op_eval_fbul_fcc1,
+        gen_op_eval_fbl_fcc1,
+        gen_op_eval_fbug_fcc1,
+        gen_op_eval_fbg_fcc1,
+        gen_op_eval_fbu_fcc1,
+        gen_op_eval_ba,
+        gen_op_eval_fbe_fcc1,
+        gen_op_eval_fbue_fcc1,
+        gen_op_eval_fbge_fcc1,
+        gen_op_eval_fbuge_fcc1,
+        gen_op_eval_fble_fcc1,
+        gen_op_eval_fbule_fcc1,
+        gen_op_eval_fbo_fcc1,
     },
     {
-	gen_op_eval_bn,
-	gen_op_eval_fbne_fcc2,
-	gen_op_eval_fblg_fcc2,
-	gen_op_eval_fbul_fcc2,
-	gen_op_eval_fbl_fcc2,
-	gen_op_eval_fbug_fcc2,
-	gen_op_eval_fbg_fcc2,
-	gen_op_eval_fbu_fcc2,
-	gen_op_eval_ba,
-	gen_op_eval_fbe_fcc2,
-	gen_op_eval_fbue_fcc2,
-	gen_op_eval_fbge_fcc2,
-	gen_op_eval_fbuge_fcc2,
-	gen_op_eval_fble_fcc2,
-	gen_op_eval_fbule_fcc2,
-	gen_op_eval_fbo_fcc2,
+        gen_op_eval_bn,
+        gen_op_eval_fbne_fcc2,
+        gen_op_eval_fblg_fcc2,
+        gen_op_eval_fbul_fcc2,
+        gen_op_eval_fbl_fcc2,
+        gen_op_eval_fbug_fcc2,
+        gen_op_eval_fbg_fcc2,
+        gen_op_eval_fbu_fcc2,
+        gen_op_eval_ba,
+        gen_op_eval_fbe_fcc2,
+        gen_op_eval_fbue_fcc2,
+        gen_op_eval_fbge_fcc2,
+        gen_op_eval_fbuge_fcc2,
+        gen_op_eval_fble_fcc2,
+        gen_op_eval_fbule_fcc2,
+        gen_op_eval_fbo_fcc2,
     },
     {
-	gen_op_eval_bn,
-	gen_op_eval_fbne_fcc3,
-	gen_op_eval_fblg_fcc3,
-	gen_op_eval_fbul_fcc3,
-	gen_op_eval_fbl_fcc3,
-	gen_op_eval_fbug_fcc3,
-	gen_op_eval_fbg_fcc3,
-	gen_op_eval_fbu_fcc3,
-	gen_op_eval_ba,
-	gen_op_eval_fbe_fcc3,
-	gen_op_eval_fbue_fcc3,
-	gen_op_eval_fbge_fcc3,
-	gen_op_eval_fbuge_fcc3,
-	gen_op_eval_fble_fcc3,
-	gen_op_eval_fbule_fcc3,
-	gen_op_eval_fbo_fcc3,
+        gen_op_eval_bn,
+        gen_op_eval_fbne_fcc3,
+        gen_op_eval_fblg_fcc3,
+        gen_op_eval_fbul_fcc3,
+        gen_op_eval_fbl_fcc3,
+        gen_op_eval_fbug_fcc3,
+        gen_op_eval_fbg_fcc3,
+        gen_op_eval_fbu_fcc3,
+        gen_op_eval_ba,
+        gen_op_eval_fbe_fcc3,
+        gen_op_eval_fbue_fcc3,
+        gen_op_eval_fbge_fcc3,
+        gen_op_eval_fbuge_fcc3,
+        gen_op_eval_fble_fcc3,
+        gen_op_eval_fbule_fcc3,
+        gen_op_eval_fbo_fcc3,
     },
 #else
     {}, {}, {},
@@ -820,27 +919,27 @@
 #ifdef TARGET_SPARC64
 static void gen_cond_reg(int cond)
 {
-	switch (cond) {
-	case 0x1:
-	    gen_op_eval_brz();
-	    break;
-	case 0x2:
-	    gen_op_eval_brlez();
-	    break;
-	case 0x3:
-	    gen_op_eval_brlz();
-	    break;
-	case 0x5:
-	    gen_op_eval_brnz();
-	    break;
-	case 0x6:
-	    gen_op_eval_brgz();
-	    break;
+        switch (cond) {
+        case 0x1:
+            gen_op_eval_brz();
+            break;
+        case 0x2:
+            gen_op_eval_brlez();
+            break;
+        case 0x3:
+            gen_op_eval_brlz();
+            break;
+        case 0x5:
+            gen_op_eval_brnz();
+            break;
+        case 0x6:
+            gen_op_eval_brgz();
+            break;
         default:
-	case 0x7:
-	    gen_op_eval_brgez();
-	    break;
-	}
+        case 0x7:
+            gen_op_eval_brgez();
+            break;
+        }
 }
 #endif
 
@@ -851,35 +950,35 @@
     target_ulong target = dc->pc + offset;
 
     if (cond == 0x0) {
-	/* unconditional not taken */
-	if (a) {
-	    dc->pc = dc->npc + 4;
-	    dc->npc = dc->pc + 4;
-	} else {
-	    dc->pc = dc->npc;
-	    dc->npc = dc->pc + 4;
-	}
+        /* unconditional not taken */
+        if (a) {
+            dc->pc = dc->npc + 4;
+            dc->npc = dc->pc + 4;
+        } else {
+            dc->pc = dc->npc;
+            dc->npc = dc->pc + 4;
+        }
     } else if (cond == 0x8) {
-	/* unconditional taken */
-	if (a) {
-	    dc->pc = target;
-	    dc->npc = dc->pc + 4;
-	} else {
-	    dc->pc = dc->npc;
-	    dc->npc = target;
-	}
+        /* unconditional taken */
+        if (a) {
+            dc->pc = target;
+            dc->npc = dc->pc + 4;
+        } else {
+            dc->pc = dc->npc;
+            dc->npc = target;
+        }
     } else {
         flush_T2(dc);
         gen_cond[cc][cond]();
-	if (a) {
-	    gen_branch_a(dc, target, dc->npc);
+        if (a) {
+            gen_branch_a(dc, target, dc->npc);
             dc->is_br = 1;
-	} else {
+        } else {
             dc->pc = dc->npc;
             dc->jump_pc[0] = target;
             dc->jump_pc[1] = dc->npc + 4;
             dc->npc = JUMP_PC;
-	}
+        }
     }
 }
 
@@ -890,35 +989,35 @@
     target_ulong target = dc->pc + offset;
 
     if (cond == 0x0) {
-	/* unconditional not taken */
-	if (a) {
-	    dc->pc = dc->npc + 4;
-	    dc->npc = dc->pc + 4;
-	} else {
-	    dc->pc = dc->npc;
-	    dc->npc = dc->pc + 4;
-	}
+        /* unconditional not taken */
+        if (a) {
+            dc->pc = dc->npc + 4;
+            dc->npc = dc->pc + 4;
+        } else {
+            dc->pc = dc->npc;
+            dc->npc = dc->pc + 4;
+        }
     } else if (cond == 0x8) {
-	/* unconditional taken */
-	if (a) {
-	    dc->pc = target;
-	    dc->npc = dc->pc + 4;
-	} else {
-	    dc->pc = dc->npc;
-	    dc->npc = target;
-	}
+        /* unconditional taken */
+        if (a) {
+            dc->pc = target;
+            dc->npc = dc->pc + 4;
+        } else {
+            dc->pc = dc->npc;
+            dc->npc = target;
+        }
     } else {
         flush_T2(dc);
         gen_fcond[cc][cond]();
-	if (a) {
-	    gen_branch_a(dc, target, dc->npc);
+        if (a) {
+            gen_branch_a(dc, target, dc->npc);
             dc->is_br = 1;
-	} else {
+        } else {
             dc->pc = dc->npc;
             dc->jump_pc[0] = target;
             dc->jump_pc[1] = dc->npc + 4;
             dc->npc = JUMP_PC;
-	}
+        }
     }
 }
 
@@ -932,13 +1031,13 @@
     flush_T2(dc);
     gen_cond_reg(cond);
     if (a) {
-	gen_branch_a(dc, target, dc->npc);
-	dc->is_br = 1;
+        gen_branch_a(dc, target, dc->npc);
+        dc->is_br = 1;
     } else {
-	dc->pc = dc->npc;
-	dc->jump_pc[0] = target;
-	dc->jump_pc[1] = dc->npc + 4;
-	dc->npc = JUMP_PC;
+        dc->pc = dc->npc;
+        dc->jump_pc[0] = target;
+        dc->jump_pc[1] = dc->npc + 4;
+        dc->npc = JUMP_PC;
     }
 }
 
@@ -995,139 +1094,139 @@
 
     rd = GET_FIELD(insn, 2, 6);
     switch (opc) {
-    case 0:			/* branches/sethi */
-	{
-	    unsigned int xop = GET_FIELD(insn, 7, 9);
-	    int32_t target;
-	    switch (xop) {
+    case 0:                     /* branches/sethi */
+        {
+            unsigned int xop = GET_FIELD(insn, 7, 9);
+            int32_t target;
+            switch (xop) {
 #ifdef TARGET_SPARC64
-	    case 0x1:		/* V9 BPcc */
-		{
-		    int cc;
+            case 0x1:           /* V9 BPcc */
+                {
+                    int cc;
 
-		    target = GET_FIELD_SP(insn, 0, 18);
-		    target = sign_extend(target, 18);
-		    target <<= 2;
-		    cc = GET_FIELD_SP(insn, 20, 21);
-		    if (cc == 0)
-			do_branch(dc, target, insn, 0);
-		    else if (cc == 2)
-			do_branch(dc, target, insn, 1);
-		    else
-			goto illegal_insn;
-		    goto jmp_insn;
-		}
-	    case 0x3:		/* V9 BPr */
-		{
-		    target = GET_FIELD_SP(insn, 0, 13) |
+                    target = GET_FIELD_SP(insn, 0, 18);
+                    target = sign_extend(target, 18);
+                    target <<= 2;
+                    cc = GET_FIELD_SP(insn, 20, 21);
+                    if (cc == 0)
+                        do_branch(dc, target, insn, 0);
+                    else if (cc == 2)
+                        do_branch(dc, target, insn, 1);
+                    else
+                        goto illegal_insn;
+                    goto jmp_insn;
+                }
+            case 0x3:           /* V9 BPr */
+                {
+                    target = GET_FIELD_SP(insn, 0, 13) |
                         (GET_FIELD_SP(insn, 20, 21) << 14);
-		    target = sign_extend(target, 16);
-		    target <<= 2;
-		    rs1 = GET_FIELD(insn, 13, 17);
-		    gen_movl_reg_T0(rs1);
-		    do_branch_reg(dc, target, insn);
-		    goto jmp_insn;
-		}
-	    case 0x5:		/* V9 FBPcc */
-		{
-		    int cc = GET_FIELD_SP(insn, 20, 21);
+                    target = sign_extend(target, 16);
+                    target <<= 2;
+                    rs1 = GET_FIELD(insn, 13, 17);
+                    gen_movl_reg_T0(rs1);
+                    do_branch_reg(dc, target, insn);
+                    goto jmp_insn;
+                }
+            case 0x5:           /* V9 FBPcc */
+                {
+                    int cc = GET_FIELD_SP(insn, 20, 21);
                     if (gen_trap_ifnofpu(dc))
                         goto jmp_insn;
-		    target = GET_FIELD_SP(insn, 0, 18);
-		    target = sign_extend(target, 19);
-		    target <<= 2;
-		    do_fbranch(dc, target, insn, cc);
-		    goto jmp_insn;
-		}
+                    target = GET_FIELD_SP(insn, 0, 18);
+                    target = sign_extend(target, 19);
+                    target <<= 2;
+                    do_fbranch(dc, target, insn, cc);
+                    goto jmp_insn;
+                }
 #else
-	    case 0x7:		/* CBN+x */
-		{
-		    goto ncp_insn;
-		}
+            case 0x7:           /* CBN+x */
+                {
+                    goto ncp_insn;
+                }
 #endif
-	    case 0x2:		/* BN+x */
-		{
-		    target = GET_FIELD(insn, 10, 31);
-		    target = sign_extend(target, 22);
-		    target <<= 2;
-		    do_branch(dc, target, insn, 0);
-		    goto jmp_insn;
-		}
-	    case 0x6:		/* FBN+x */
-		{
+            case 0x2:           /* BN+x */
+                {
+                    target = GET_FIELD(insn, 10, 31);
+                    target = sign_extend(target, 22);
+                    target <<= 2;
+                    do_branch(dc, target, insn, 0);
+                    goto jmp_insn;
+                }
+            case 0x6:           /* FBN+x */
+                {
                     if (gen_trap_ifnofpu(dc))
                         goto jmp_insn;
-		    target = GET_FIELD(insn, 10, 31);
-		    target = sign_extend(target, 22);
-		    target <<= 2;
-		    do_fbranch(dc, target, insn, 0);
-		    goto jmp_insn;
-		}
-	    case 0x4:		/* SETHI */
+                    target = GET_FIELD(insn, 10, 31);
+                    target = sign_extend(target, 22);
+                    target <<= 2;
+                    do_fbranch(dc, target, insn, 0);
+                    goto jmp_insn;
+                }
+            case 0x4:           /* SETHI */
 #define OPTIM
 #if defined(OPTIM)
-		if (rd) { // nop
+                if (rd) { // nop
 #endif
-		    uint32_t value = GET_FIELD(insn, 10, 31);
-		    gen_movl_imm_T0(value << 10);
-		    gen_movl_T0_reg(rd);
+                    uint32_t value = GET_FIELD(insn, 10, 31);
+                    gen_movl_imm_T0(value << 10);
+                    gen_movl_T0_reg(rd);
 #if defined(OPTIM)
-		}
+                }
 #endif
-		break;
-	    case 0x0:		/* UNIMPL */
-	    default:
+                break;
+            case 0x0:           /* UNIMPL */
+            default:
                 goto illegal_insn;
-	    }
-	    break;
-	}
-	break;
+            }
+            break;
+        }
+        break;
     case 1:
-	/*CALL*/ {
-	    target_long target = GET_FIELDs(insn, 2, 31) << 2;
+        /*CALL*/ {
+            target_long target = GET_FIELDs(insn, 2, 31) << 2;
 
 #ifdef TARGET_SPARC64
-	    if (dc->pc == (uint32_t)dc->pc) {
-		gen_op_movl_T0_im(dc->pc);
-	    } else {
-		gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
-	    }
+            if (dc->pc == (uint32_t)dc->pc) {
+                gen_op_movl_T0_im(dc->pc);
+            } else {
+                gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
+            }
 #else
-	    gen_op_movl_T0_im(dc->pc);
+            gen_op_movl_T0_im(dc->pc);
 #endif
-	    gen_movl_T0_reg(15);
-	    target += dc->pc;
+            gen_movl_T0_reg(15);
+            target += dc->pc;
             gen_mov_pc_npc(dc);
-	    dc->npc = target;
-	}
-	goto jmp_insn;
-    case 2:			/* FPU & Logical Operations */
-	{
-	    unsigned int xop = GET_FIELD(insn, 7, 12);
-	    if (xop == 0x3a) {	/* generate trap */
+            dc->npc = target;
+        }
+        goto jmp_insn;
+    case 2:                     /* FPU & Logical Operations */
+        {
+            unsigned int xop = GET_FIELD(insn, 7, 12);
+            if (xop == 0x3a) {  /* generate trap */
                 int cond;
 
                 rs1 = GET_FIELD(insn, 13, 17);
                 gen_movl_reg_T0(rs1);
-		if (IS_IMM) {
-		    rs2 = GET_FIELD(insn, 25, 31);
+                if (IS_IMM) {
+                    rs2 = GET_FIELD(insn, 25, 31);
 #if defined(OPTIM)
-		    if (rs2 != 0) {
+                    if (rs2 != 0) {
 #endif
-			gen_movl_simm_T1(rs2);
-			gen_op_add_T1_T0();
+                        gen_movl_simm_T1(rs2);
+                        gen_op_add_T1_T0();
 #if defined(OPTIM)
-		    }
+                    }
 #endif
                 } else {
                     rs2 = GET_FIELD(insn, 27, 31);
 #if defined(OPTIM)
-		    if (rs2 != 0) {
+                    if (rs2 != 0) {
 #endif
-			gen_movl_reg_T1(rs2);
-			gen_op_add_T1_T0();
+                        gen_movl_reg_T1(rs2);
+                        gen_op_add_T1_T0();
 #if defined(OPTIM)
-		    }
+                    }
 #endif
                 }
                 cond = GET_FIELD(insn, 3, 6);
@@ -1136,20 +1235,20 @@
                     gen_op_trap_T0();
                 } else if (cond != 0) {
 #ifdef TARGET_SPARC64
-		    /* V9 icc/xcc */
-		    int cc = GET_FIELD_SP(insn, 11, 12);
-		    flush_T2(dc);
+                    /* V9 icc/xcc */
+                    int cc = GET_FIELD_SP(insn, 11, 12);
+                    flush_T2(dc);
                     save_state(dc);
-		    if (cc == 0)
-			gen_cond[0][cond]();
-		    else if (cc == 2)
-			gen_cond[1][cond]();
-		    else
-			goto illegal_insn;
+                    if (cc == 0)
+                        gen_cond[0][cond]();
+                    else if (cc == 2)
+                        gen_cond[1][cond]();
+                    else
+                        goto illegal_insn;
 #else
-		    flush_T2(dc);
+                    flush_T2(dc);
                     save_state(dc);
-		    gen_cond[0][cond]();
+                    gen_cond[0][cond]();
 #endif
                     gen_op_trapcc_T0();
                 }
@@ -1176,56 +1275,56 @@
                     gen_movl_T0_reg(rd);
                     break;
 #ifdef TARGET_SPARC64
-		case 0x2: /* V9 rdccr */
+                case 0x2: /* V9 rdccr */
                     gen_op_rdccr();
                     gen_movl_T0_reg(rd);
                     break;
-		case 0x3: /* V9 rdasi */
-		    gen_op_movl_T0_env(offsetof(CPUSPARCState, asi));
+                case 0x3: /* V9 rdasi */
+                    gen_op_movl_T0_env(offsetof(CPUSPARCState, asi));
                     gen_movl_T0_reg(rd);
                     break;
-		case 0x4: /* V9 rdtick */
+                case 0x4: /* V9 rdtick */
                     gen_op_rdtick();
                     gen_movl_T0_reg(rd);
                     break;
-		case 0x5: /* V9 rdpc */
-		    if (dc->pc == (uint32_t)dc->pc) {
-			gen_op_movl_T0_im(dc->pc);
-		    } else {
-			gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
-		    }
-		    gen_movl_T0_reg(rd);
-		    break;
-		case 0x6: /* V9 rdfprs */
-		    gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));
+                case 0x5: /* V9 rdpc */
+                    if (dc->pc == (uint32_t)dc->pc) {
+                        gen_op_movl_T0_im(dc->pc);
+                    } else {
+                        gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
+                    }
                     gen_movl_T0_reg(rd);
                     break;
+                case 0x6: /* V9 rdfprs */
+                    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 */
+                case 0x13: /* Graphics Status */
                     if (gen_trap_ifnofpu(dc))
                         goto jmp_insn;
-		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, gsr));
+                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, gsr));
                     gen_movl_T0_reg(rd);
                     break;
-		case 0x17: /* Tick compare */
-		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr));
+                case 0x17: /* Tick compare */
+                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr));
                     gen_movl_T0_reg(rd);
                     break;
-		case 0x18: /* System tick */
+                case 0x18: /* System tick */
                     gen_op_rdstick();
                     gen_movl_T0_reg(rd);
                     break;
-		case 0x19: /* System tick compare */
-		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, stick_cmpr));
+                case 0x19: /* System tick compare */
+                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, stick_cmpr));
                     gen_movl_T0_reg(rd);
                     break;
-		case 0x10: /* Performance Control */
-		case 0x11: /* Performance Instrumentation Counter */
-		case 0x12: /* Dispatch Control */
-		case 0x14: /* Softint set, WO */
-		case 0x15: /* Softint clear, WO */
-		case 0x16: /* Softint write */
+                case 0x10: /* Performance Control */
+                case 0x11: /* Performance Instrumentation Counter */
+                case 0x12: /* Dispatch Control */
+                case 0x14: /* Softint set, WO */
+                case 0x15: /* Softint clear, WO */
+                case 0x16: /* Softint write */
 #endif
                 default:
                     goto illegal_insn;
@@ -1233,8 +1332,8 @@
 #if !defined(CONFIG_USER_ONLY)
             } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
 #ifndef TARGET_SPARC64
-		if (!supervisor(dc))
-		    goto priv_insn;
+                if (!supervisor(dc))
+                    goto priv_insn;
                 gen_op_rdpsr();
 #else
                 if (!hypervisor(dc))
@@ -1266,56 +1365,56 @@
                 gen_movl_T0_reg(rd);
                 break;
             } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
-		if (!supervisor(dc))
-		    goto priv_insn;
+                if (!supervisor(dc))
+                    goto priv_insn;
 #ifdef TARGET_SPARC64
                 rs1 = GET_FIELD(insn, 13, 17);
-		switch (rs1) {
-		case 0: // tpc
-		    gen_op_rdtpc();
-		    break;
-		case 1: // tnpc
-		    gen_op_rdtnpc();
-		    break;
-		case 2: // tstate
-		    gen_op_rdtstate();
-		    break;
-		case 3: // tt
-		    gen_op_rdtt();
-		    break;
-		case 4: // tick
-		    gen_op_rdtick();
-		    break;
-		case 5: // tba
-		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
-		    break;
-		case 6: // pstate
-		    gen_op_rdpstate();
-		    break;
-		case 7: // tl
-		    gen_op_movl_T0_env(offsetof(CPUSPARCState, tl));
-		    break;
-		case 8: // pil
-		    gen_op_movl_T0_env(offsetof(CPUSPARCState, psrpil));
-		    break;
-		case 9: // cwp
-		    gen_op_rdcwp();
-		    break;
-		case 10: // cansave
-		    gen_op_movl_T0_env(offsetof(CPUSPARCState, cansave));
-		    break;
-		case 11: // canrestore
-		    gen_op_movl_T0_env(offsetof(CPUSPARCState, canrestore));
-		    break;
-		case 12: // cleanwin
-		    gen_op_movl_T0_env(offsetof(CPUSPARCState, cleanwin));
-		    break;
-		case 13: // otherwin
-		    gen_op_movl_T0_env(offsetof(CPUSPARCState, otherwin));
-		    break;
-		case 14: // wstate
-		    gen_op_movl_T0_env(offsetof(CPUSPARCState, wstate));
-		    break;
+                switch (rs1) {
+                case 0: // tpc
+                    gen_op_rdtpc();
+                    break;
+                case 1: // tnpc
+                    gen_op_rdtnpc();
+                    break;
+                case 2: // tstate
+                    gen_op_rdtstate();
+                    break;
+                case 3: // tt
+                    gen_op_rdtt();
+                    break;
+                case 4: // tick
+                    gen_op_rdtick();
+                    break;
+                case 5: // tba
+                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
+                    break;
+                case 6: // pstate
+                    gen_op_rdpstate();
+                    break;
+                case 7: // tl
+                    gen_op_movl_T0_env(offsetof(CPUSPARCState, tl));
+                    break;
+                case 8: // pil
+                    gen_op_movl_T0_env(offsetof(CPUSPARCState, psrpil));
+                    break;
+                case 9: // cwp
+                    gen_op_rdcwp();
+                    break;
+                case 10: // cansave
+                    gen_op_movl_T0_env(offsetof(CPUSPARCState, cansave));
+                    break;
+                case 11: // canrestore
+                    gen_op_movl_T0_env(offsetof(CPUSPARCState, canrestore));
+                    break;
+                case 12: // cleanwin
+                    gen_op_movl_T0_env(offsetof(CPUSPARCState, cleanwin));
+                    break;
+                case 13: // otherwin
+                    gen_op_movl_T0_env(offsetof(CPUSPARCState, otherwin));
+                    break;
+                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;
@@ -1324,506 +1423,506 @@
                         goto priv_insn;
                     gen_op_movl_T0_env(offsetof(CPUSPARCState, ssr));
                     break;
-		case 31: // ver
-		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, version));
-		    break;
-		case 15: // fq
-		default:
-		    goto illegal_insn;
-		}
+                case 31: // ver
+                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, version));
+                    break;
+                case 15: // fq
+                default:
+                    goto illegal_insn;
+                }
 #else
-		gen_op_movl_T0_env(offsetof(CPUSPARCState, wim));
+                gen_op_movl_T0_env(offsetof(CPUSPARCState, wim));
 #endif
                 gen_movl_T0_reg(rd);
                 break;
             } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
 #ifdef TARGET_SPARC64
-		gen_op_flushw();
+                gen_op_flushw();
 #else
-		if (!supervisor(dc))
-		    goto priv_insn;
-		gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
+                if (!supervisor(dc))
+                    goto priv_insn;
+                gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
                 gen_movl_T0_reg(rd);
 #endif
                 break;
 #endif
-	    } else if (xop == 0x34) {	/* FPU Operations */
+            } else if (xop == 0x34) {   /* FPU Operations */
                 if (gen_trap_ifnofpu(dc))
                     goto jmp_insn;
-		gen_op_clear_ieee_excp_and_FTT();
+                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);
-		switch (xop) {
-		    case 0x1: /* fmovs */
-                	gen_op_load_fpr_FT0(rs2);
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x5: /* fnegs */
-                	gen_op_load_fpr_FT1(rs2);
-			gen_op_fnegs();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x9: /* fabss */
-                	gen_op_load_fpr_FT1(rs2);
-			gen_op_fabss();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x29: /* fsqrts */
-                	gen_op_load_fpr_FT1(rs2);
-			gen_op_fsqrts();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x2a: /* fsqrtd */
-                	gen_op_load_fpr_DT1(DFPREG(rs2));
-			gen_op_fsqrtd();
-			gen_op_store_DT0_fpr(DFPREG(rd));
-			break;
-		    case 0x2b: /* fsqrtq */
-		        goto nfpu_insn;
-		    case 0x41:
-                	gen_op_load_fpr_FT0(rs1);
-                	gen_op_load_fpr_FT1(rs2);
-			gen_op_fadds();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x42:
-                	gen_op_load_fpr_DT0(DFPREG(rs1));
-                	gen_op_load_fpr_DT1(DFPREG(rs2));
-			gen_op_faddd();
-			gen_op_store_DT0_fpr(DFPREG(rd));
-			break;
-		    case 0x43: /* faddq */
-		        goto nfpu_insn;
-		    case 0x45:
-                	gen_op_load_fpr_FT0(rs1);
-                	gen_op_load_fpr_FT1(rs2);
-			gen_op_fsubs();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x46:
-                	gen_op_load_fpr_DT0(DFPREG(rs1));
-                	gen_op_load_fpr_DT1(DFPREG(rs2));
-			gen_op_fsubd();
-			gen_op_store_DT0_fpr(DFPREG(rd));
-			break;
-		    case 0x47: /* fsubq */
-		        goto nfpu_insn;
-		    case 0x49:
-                	gen_op_load_fpr_FT0(rs1);
-                	gen_op_load_fpr_FT1(rs2);
-			gen_op_fmuls();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x4a:
-                	gen_op_load_fpr_DT0(DFPREG(rs1));
-                	gen_op_load_fpr_DT1(DFPREG(rs2));
-			gen_op_fmuld();
-			gen_op_store_DT0_fpr(rd);
-			break;
-		    case 0x4b: /* fmulq */
-		        goto nfpu_insn;
-		    case 0x4d:
-                	gen_op_load_fpr_FT0(rs1);
-                	gen_op_load_fpr_FT1(rs2);
-			gen_op_fdivs();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x4e:
-                	gen_op_load_fpr_DT0(DFPREG(rs1));
-			gen_op_load_fpr_DT1(DFPREG(rs2));
-			gen_op_fdivd();
-			gen_op_store_DT0_fpr(DFPREG(rd));
-			break;
-		    case 0x4f: /* fdivq */
-		        goto nfpu_insn;
-		    case 0x69:
-                	gen_op_load_fpr_FT0(rs1);
-                	gen_op_load_fpr_FT1(rs2);
-			gen_op_fsmuld();
-			gen_op_store_DT0_fpr(DFPREG(rd));
-			break;
-		    case 0x6e: /* fdmulq */
-		        goto nfpu_insn;
-		    case 0xc4:
-                	gen_op_load_fpr_FT1(rs2);
-			gen_op_fitos();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0xc6:
-                	gen_op_load_fpr_DT1(DFPREG(rs2));
-			gen_op_fdtos();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0xc7: /* fqtos */
-		        goto nfpu_insn;
-		    case 0xc8:
-                	gen_op_load_fpr_FT1(rs2);
-			gen_op_fitod();
-			gen_op_store_DT0_fpr(DFPREG(rd));
-			break;
-		    case 0xc9:
-                	gen_op_load_fpr_FT1(rs2);
-			gen_op_fstod();
-			gen_op_store_DT0_fpr(DFPREG(rd));
-			break;
-		    case 0xcb: /* fqtod */
-		        goto nfpu_insn;
-		    case 0xcc: /* fitoq */
-		        goto nfpu_insn;
-		    case 0xcd: /* fstoq */
-		        goto nfpu_insn;
-		    case 0xce: /* fdtoq */
-		        goto nfpu_insn;
-		    case 0xd1:
-                	gen_op_load_fpr_FT1(rs2);
-			gen_op_fstoi();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0xd2:
-                	gen_op_load_fpr_DT1(rs2);
-			gen_op_fdtoi();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0xd3: /* fqtoi */
-		        goto nfpu_insn;
+                rs2 = GET_FIELD(insn, 27, 31);
+                xop = GET_FIELD(insn, 18, 26);
+                switch (xop) {
+                    case 0x1: /* fmovs */
+                        gen_op_load_fpr_FT0(rs2);
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x5: /* fnegs */
+                        gen_op_load_fpr_FT1(rs2);
+                        gen_op_fnegs();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x9: /* fabss */
+                        gen_op_load_fpr_FT1(rs2);
+                        gen_op_fabss();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x29: /* fsqrts */
+                        gen_op_load_fpr_FT1(rs2);
+                        gen_op_fsqrts();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x2a: /* fsqrtd */
+                        gen_op_load_fpr_DT1(DFPREG(rs2));
+                        gen_op_fsqrtd();
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                        break;
+                    case 0x2b: /* fsqrtq */
+                        goto nfpu_insn;
+                    case 0x41:
+                        gen_op_load_fpr_FT0(rs1);
+                        gen_op_load_fpr_FT1(rs2);
+                        gen_op_fadds();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x42:
+                        gen_op_load_fpr_DT0(DFPREG(rs1));
+                        gen_op_load_fpr_DT1(DFPREG(rs2));
+                        gen_op_faddd();
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                        break;
+                    case 0x43: /* faddq */
+                        goto nfpu_insn;
+                    case 0x45:
+                        gen_op_load_fpr_FT0(rs1);
+                        gen_op_load_fpr_FT1(rs2);
+                        gen_op_fsubs();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x46:
+                        gen_op_load_fpr_DT0(DFPREG(rs1));
+                        gen_op_load_fpr_DT1(DFPREG(rs2));
+                        gen_op_fsubd();
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                        break;
+                    case 0x47: /* fsubq */
+                        goto nfpu_insn;
+                    case 0x49:
+                        gen_op_load_fpr_FT0(rs1);
+                        gen_op_load_fpr_FT1(rs2);
+                        gen_op_fmuls();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x4a:
+                        gen_op_load_fpr_DT0(DFPREG(rs1));
+                        gen_op_load_fpr_DT1(DFPREG(rs2));
+                        gen_op_fmuld();
+                        gen_op_store_DT0_fpr(rd);
+                        break;
+                    case 0x4b: /* fmulq */
+                        goto nfpu_insn;
+                    case 0x4d:
+                        gen_op_load_fpr_FT0(rs1);
+                        gen_op_load_fpr_FT1(rs2);
+                        gen_op_fdivs();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x4e:
+                        gen_op_load_fpr_DT0(DFPREG(rs1));
+                        gen_op_load_fpr_DT1(DFPREG(rs2));
+                        gen_op_fdivd();
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                        break;
+                    case 0x4f: /* fdivq */
+                        goto nfpu_insn;
+                    case 0x69:
+                        gen_op_load_fpr_FT0(rs1);
+                        gen_op_load_fpr_FT1(rs2);
+                        gen_op_fsmuld();
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                        break;
+                    case 0x6e: /* fdmulq */
+                        goto nfpu_insn;
+                    case 0xc4:
+                        gen_op_load_fpr_FT1(rs2);
+                        gen_op_fitos();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0xc6:
+                        gen_op_load_fpr_DT1(DFPREG(rs2));
+                        gen_op_fdtos();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0xc7: /* fqtos */
+                        goto nfpu_insn;
+                    case 0xc8:
+                        gen_op_load_fpr_FT1(rs2);
+                        gen_op_fitod();
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                        break;
+                    case 0xc9:
+                        gen_op_load_fpr_FT1(rs2);
+                        gen_op_fstod();
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                        break;
+                    case 0xcb: /* fqtod */
+                        goto nfpu_insn;
+                    case 0xcc: /* fitoq */
+                        goto nfpu_insn;
+                    case 0xcd: /* fstoq */
+                        goto nfpu_insn;
+                    case 0xce: /* fdtoq */
+                        goto nfpu_insn;
+                    case 0xd1:
+                        gen_op_load_fpr_FT1(rs2);
+                        gen_op_fstoi();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0xd2:
+                        gen_op_load_fpr_DT1(rs2);
+                        gen_op_fdtoi();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0xd3: /* fqtoi */
+                        goto nfpu_insn;
 #ifdef TARGET_SPARC64
-		    case 0x2: /* V9 fmovd */
-                	gen_op_load_fpr_DT0(DFPREG(rs2));
-			gen_op_store_DT0_fpr(DFPREG(rd));
-			break;
-		    case 0x6: /* V9 fnegd */
-                	gen_op_load_fpr_DT1(DFPREG(rs2));
-			gen_op_fnegd();
-			gen_op_store_DT0_fpr(DFPREG(rd));
-			break;
-		    case 0xa: /* V9 fabsd */
-                	gen_op_load_fpr_DT1(DFPREG(rs2));
-			gen_op_fabsd();
-			gen_op_store_DT0_fpr(DFPREG(rd));
-			break;
-		    case 0x81: /* V9 fstox */
-                	gen_op_load_fpr_FT1(rs2);
-			gen_op_fstox();
-			gen_op_store_DT0_fpr(DFPREG(rd));
-			break;
-		    case 0x82: /* V9 fdtox */
-                	gen_op_load_fpr_DT1(DFPREG(rs2));
-			gen_op_fdtox();
-			gen_op_store_DT0_fpr(DFPREG(rd));
-			break;
-		    case 0x84: /* V9 fxtos */
-                	gen_op_load_fpr_DT1(DFPREG(rs2));
-			gen_op_fxtos();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x88: /* V9 fxtod */
-                	gen_op_load_fpr_DT1(DFPREG(rs2));
-			gen_op_fxtod();
-			gen_op_store_DT0_fpr(DFPREG(rd));
-			break;
-		    case 0x3: /* V9 fmovq */
-		    case 0x7: /* V9 fnegq */
-		    case 0xb: /* V9 fabsq */
-		    case 0x83: /* V9 fqtox */
-		    case 0x8c: /* V9 fxtoq */
-		        goto nfpu_insn;
+                    case 0x2: /* V9 fmovd */
+                        gen_op_load_fpr_DT0(DFPREG(rs2));
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                        break;
+                    case 0x6: /* V9 fnegd */
+                        gen_op_load_fpr_DT1(DFPREG(rs2));
+                        gen_op_fnegd();
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                        break;
+                    case 0xa: /* V9 fabsd */
+                        gen_op_load_fpr_DT1(DFPREG(rs2));
+                        gen_op_fabsd();
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                        break;
+                    case 0x81: /* V9 fstox */
+                        gen_op_load_fpr_FT1(rs2);
+                        gen_op_fstox();
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                        break;
+                    case 0x82: /* V9 fdtox */
+                        gen_op_load_fpr_DT1(DFPREG(rs2));
+                        gen_op_fdtox();
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                        break;
+                    case 0x84: /* V9 fxtos */
+                        gen_op_load_fpr_DT1(DFPREG(rs2));
+                        gen_op_fxtos();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x88: /* V9 fxtod */
+                        gen_op_load_fpr_DT1(DFPREG(rs2));
+                        gen_op_fxtod();
+                        gen_op_store_DT0_fpr(DFPREG(rd));
+                        break;
+                    case 0x3: /* V9 fmovq */
+                    case 0x7: /* V9 fnegq */
+                    case 0xb: /* V9 fabsq */
+                    case 0x83: /* V9 fqtox */
+                    case 0x8c: /* V9 fxtoq */
+                        goto nfpu_insn;
 #endif
-		    default:
-                	goto illegal_insn;
-		}
-	    } else if (xop == 0x35) {	/* FPU Operations */
+                    default:
+                        goto illegal_insn;
+                }
+            } else if (xop == 0x35) {   /* FPU Operations */
 #ifdef TARGET_SPARC64
-		int cond;
+                int cond;
 #endif
                 if (gen_trap_ifnofpu(dc))
                     goto jmp_insn;
-		gen_op_clear_ieee_excp_and_FTT();
+                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);
+                rs2 = GET_FIELD(insn, 27, 31);
+                xop = GET_FIELD(insn, 18, 26);
 #ifdef TARGET_SPARC64
-		if ((xop & 0x11f) == 0x005) { // V9 fmovsr
-		    cond = GET_FIELD_SP(insn, 14, 17);
-		    gen_op_load_fpr_FT0(rd);
-		    gen_op_load_fpr_FT1(rs2);
-		    rs1 = GET_FIELD(insn, 13, 17);
-		    gen_movl_reg_T0(rs1);
-		    flush_T2(dc);
-		    gen_cond_reg(cond);
-		    gen_op_fmovs_cc();
-		    gen_op_store_FT0_fpr(rd);
-		    break;
-		} else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
-		    cond = GET_FIELD_SP(insn, 14, 17);
-		    gen_op_load_fpr_DT0(rd);
-		    gen_op_load_fpr_DT1(rs2);
-		    flush_T2(dc);
-		    rs1 = GET_FIELD(insn, 13, 17);
-		    gen_movl_reg_T0(rs1);
-		    gen_cond_reg(cond);
-		    gen_op_fmovs_cc();
-		    gen_op_store_DT0_fpr(rd);
-		    break;
-		} else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
-		    goto nfpu_insn;
-		}
+                if ((xop & 0x11f) == 0x005) { // V9 fmovsr
+                    cond = GET_FIELD_SP(insn, 14, 17);
+                    gen_op_load_fpr_FT0(rd);
+                    gen_op_load_fpr_FT1(rs2);
+                    rs1 = GET_FIELD(insn, 13, 17);
+                    gen_movl_reg_T0(rs1);
+                    flush_T2(dc);
+                    gen_cond_reg(cond);
+                    gen_op_fmovs_cc();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
+                    cond = GET_FIELD_SP(insn, 14, 17);
+                    gen_op_load_fpr_DT0(rd);
+                    gen_op_load_fpr_DT1(rs2);
+                    flush_T2(dc);
+                    rs1 = GET_FIELD(insn, 13, 17);
+                    gen_movl_reg_T0(rs1);
+                    gen_cond_reg(cond);
+                    gen_op_fmovs_cc();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
+                    goto nfpu_insn;
+                }
 #endif
-		switch (xop) {
+                switch (xop) {
 #ifdef TARGET_SPARC64
-		    case 0x001: /* V9 fmovscc %fcc0 */
-			cond = GET_FIELD_SP(insn, 14, 17);
-                	gen_op_load_fpr_FT0(rd);
-                	gen_op_load_fpr_FT1(rs2);
-			flush_T2(dc);
-			gen_fcond[0][cond]();
-			gen_op_fmovs_cc();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x002: /* V9 fmovdcc %fcc0 */
-			cond = GET_FIELD_SP(insn, 14, 17);
-                	gen_op_load_fpr_DT0(rd);
-                	gen_op_load_fpr_DT1(rs2);
-			flush_T2(dc);
-			gen_fcond[0][cond]();
-			gen_op_fmovd_cc();
-			gen_op_store_DT0_fpr(rd);
-			break;
-		    case 0x003: /* V9 fmovqcc %fcc0 */
-		        goto nfpu_insn;
-		    case 0x041: /* V9 fmovscc %fcc1 */
-			cond = GET_FIELD_SP(insn, 14, 17);
-                	gen_op_load_fpr_FT0(rd);
-                	gen_op_load_fpr_FT1(rs2);
-			flush_T2(dc);
-			gen_fcond[1][cond]();
-			gen_op_fmovs_cc();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x042: /* V9 fmovdcc %fcc1 */
-			cond = GET_FIELD_SP(insn, 14, 17);
-                	gen_op_load_fpr_DT0(rd);
-                	gen_op_load_fpr_DT1(rs2);
-			flush_T2(dc);
-			gen_fcond[1][cond]();
-			gen_op_fmovd_cc();
-			gen_op_store_DT0_fpr(rd);
-			break;
-		    case 0x043: /* V9 fmovqcc %fcc1 */
-		        goto nfpu_insn;
-		    case 0x081: /* V9 fmovscc %fcc2 */
-			cond = GET_FIELD_SP(insn, 14, 17);
-                	gen_op_load_fpr_FT0(rd);
-                	gen_op_load_fpr_FT1(rs2);
-			flush_T2(dc);
-			gen_fcond[2][cond]();
-			gen_op_fmovs_cc();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x082: /* V9 fmovdcc %fcc2 */
-			cond = GET_FIELD_SP(insn, 14, 17);
-                	gen_op_load_fpr_DT0(rd);
-                	gen_op_load_fpr_DT1(rs2);
-			flush_T2(dc);
-			gen_fcond[2][cond]();
-			gen_op_fmovd_cc();
-			gen_op_store_DT0_fpr(rd);
-			break;
-		    case 0x083: /* V9 fmovqcc %fcc2 */
-		        goto nfpu_insn;
-		    case 0x0c1: /* V9 fmovscc %fcc3 */
-			cond = GET_FIELD_SP(insn, 14, 17);
-                	gen_op_load_fpr_FT0(rd);
-                	gen_op_load_fpr_FT1(rs2);
-			flush_T2(dc);
-			gen_fcond[3][cond]();
-			gen_op_fmovs_cc();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x0c2: /* V9 fmovdcc %fcc3 */
-			cond = GET_FIELD_SP(insn, 14, 17);
-                	gen_op_load_fpr_DT0(rd);
-                	gen_op_load_fpr_DT1(rs2);
-			flush_T2(dc);
-			gen_fcond[3][cond]();
-			gen_op_fmovd_cc();
-			gen_op_store_DT0_fpr(rd);
-			break;
-		    case 0x0c3: /* V9 fmovqcc %fcc3 */
-		        goto nfpu_insn;
-		    case 0x101: /* V9 fmovscc %icc */
-			cond = GET_FIELD_SP(insn, 14, 17);
-                	gen_op_load_fpr_FT0(rd);
-                	gen_op_load_fpr_FT1(rs2);
-			flush_T2(dc);
-			gen_cond[0][cond]();
-			gen_op_fmovs_cc();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x102: /* V9 fmovdcc %icc */
-			cond = GET_FIELD_SP(insn, 14, 17);
-                	gen_op_load_fpr_DT0(rd);
-                	gen_op_load_fpr_DT1(rs2);
-			flush_T2(dc);
-			gen_cond[0][cond]();
-			gen_op_fmovd_cc();
-			gen_op_store_DT0_fpr(rd);
-			break;
-		    case 0x103: /* V9 fmovqcc %icc */
-		        goto nfpu_insn;
-		    case 0x181: /* V9 fmovscc %xcc */
-			cond = GET_FIELD_SP(insn, 14, 17);
-                	gen_op_load_fpr_FT0(rd);
-                	gen_op_load_fpr_FT1(rs2);
-			flush_T2(dc);
-			gen_cond[1][cond]();
-			gen_op_fmovs_cc();
-			gen_op_store_FT0_fpr(rd);
-			break;
-		    case 0x182: /* V9 fmovdcc %xcc */
-			cond = GET_FIELD_SP(insn, 14, 17);
-                	gen_op_load_fpr_DT0(rd);
-                	gen_op_load_fpr_DT1(rs2);
-			flush_T2(dc);
-			gen_cond[1][cond]();
-			gen_op_fmovd_cc();
-			gen_op_store_DT0_fpr(rd);
-			break;
-		    case 0x183: /* V9 fmovqcc %xcc */
-		        goto nfpu_insn;
+                    case 0x001: /* V9 fmovscc %fcc0 */
+                        cond = GET_FIELD_SP(insn, 14, 17);
+                        gen_op_load_fpr_FT0(rd);
+                        gen_op_load_fpr_FT1(rs2);
+                        flush_T2(dc);
+                        gen_fcond[0][cond]();
+                        gen_op_fmovs_cc();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x002: /* V9 fmovdcc %fcc0 */
+                        cond = GET_FIELD_SP(insn, 14, 17);
+                        gen_op_load_fpr_DT0(rd);
+                        gen_op_load_fpr_DT1(rs2);
+                        flush_T2(dc);
+                        gen_fcond[0][cond]();
+                        gen_op_fmovd_cc();
+                        gen_op_store_DT0_fpr(rd);
+                        break;
+                    case 0x003: /* V9 fmovqcc %fcc0 */
+                        goto nfpu_insn;
+                    case 0x041: /* V9 fmovscc %fcc1 */
+                        cond = GET_FIELD_SP(insn, 14, 17);
+                        gen_op_load_fpr_FT0(rd);
+                        gen_op_load_fpr_FT1(rs2);
+                        flush_T2(dc);
+                        gen_fcond[1][cond]();
+                        gen_op_fmovs_cc();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x042: /* V9 fmovdcc %fcc1 */
+                        cond = GET_FIELD_SP(insn, 14, 17);
+                        gen_op_load_fpr_DT0(rd);
+                        gen_op_load_fpr_DT1(rs2);
+                        flush_T2(dc);
+                        gen_fcond[1][cond]();
+                        gen_op_fmovd_cc();
+                        gen_op_store_DT0_fpr(rd);
+                        break;
+                    case 0x043: /* V9 fmovqcc %fcc1 */
+                        goto nfpu_insn;
+                    case 0x081: /* V9 fmovscc %fcc2 */
+                        cond = GET_FIELD_SP(insn, 14, 17);
+                        gen_op_load_fpr_FT0(rd);
+                        gen_op_load_fpr_FT1(rs2);
+                        flush_T2(dc);
+                        gen_fcond[2][cond]();
+                        gen_op_fmovs_cc();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x082: /* V9 fmovdcc %fcc2 */
+                        cond = GET_FIELD_SP(insn, 14, 17);
+                        gen_op_load_fpr_DT0(rd);
+                        gen_op_load_fpr_DT1(rs2);
+                        flush_T2(dc);
+                        gen_fcond[2][cond]();
+                        gen_op_fmovd_cc();
+                        gen_op_store_DT0_fpr(rd);
+                        break;
+                    case 0x083: /* V9 fmovqcc %fcc2 */
+                        goto nfpu_insn;
+                    case 0x0c1: /* V9 fmovscc %fcc3 */
+                        cond = GET_FIELD_SP(insn, 14, 17);
+                        gen_op_load_fpr_FT0(rd);
+                        gen_op_load_fpr_FT1(rs2);
+                        flush_T2(dc);
+                        gen_fcond[3][cond]();
+                        gen_op_fmovs_cc();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x0c2: /* V9 fmovdcc %fcc3 */
+                        cond = GET_FIELD_SP(insn, 14, 17);
+                        gen_op_load_fpr_DT0(rd);
+                        gen_op_load_fpr_DT1(rs2);
+                        flush_T2(dc);
+                        gen_fcond[3][cond]();
+                        gen_op_fmovd_cc();
+                        gen_op_store_DT0_fpr(rd);
+                        break;
+                    case 0x0c3: /* V9 fmovqcc %fcc3 */
+                        goto nfpu_insn;
+                    case 0x101: /* V9 fmovscc %icc */
+                        cond = GET_FIELD_SP(insn, 14, 17);
+                        gen_op_load_fpr_FT0(rd);
+                        gen_op_load_fpr_FT1(rs2);
+                        flush_T2(dc);
+                        gen_cond[0][cond]();
+                        gen_op_fmovs_cc();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x102: /* V9 fmovdcc %icc */
+                        cond = GET_FIELD_SP(insn, 14, 17);
+                        gen_op_load_fpr_DT0(rd);
+                        gen_op_load_fpr_DT1(rs2);
+                        flush_T2(dc);
+                        gen_cond[0][cond]();
+                        gen_op_fmovd_cc();
+                        gen_op_store_DT0_fpr(rd);
+                        break;
+                    case 0x103: /* V9 fmovqcc %icc */
+                        goto nfpu_insn;
+                    case 0x181: /* V9 fmovscc %xcc */
+                        cond = GET_FIELD_SP(insn, 14, 17);
+                        gen_op_load_fpr_FT0(rd);
+                        gen_op_load_fpr_FT1(rs2);
+                        flush_T2(dc);
+                        gen_cond[1][cond]();
+                        gen_op_fmovs_cc();
+                        gen_op_store_FT0_fpr(rd);
+                        break;
+                    case 0x182: /* V9 fmovdcc %xcc */
+                        cond = GET_FIELD_SP(insn, 14, 17);
+                        gen_op_load_fpr_DT0(rd);
+                        gen_op_load_fpr_DT1(rs2);
+                        flush_T2(dc);
+                        gen_cond[1][cond]();
+                        gen_op_fmovd_cc();
+                        gen_op_store_DT0_fpr(rd);
+                        break;
+                    case 0x183: /* V9 fmovqcc %xcc */
+                        goto nfpu_insn;
 #endif
-		    case 0x51: /* V9 %fcc */
-                	gen_op_load_fpr_FT0(rs1);
-                	gen_op_load_fpr_FT1(rs2);
+                    case 0x51: /* V9 %fcc */
+                        gen_op_load_fpr_FT0(rs1);
+                        gen_op_load_fpr_FT1(rs2);
 #ifdef TARGET_SPARC64
-			gen_fcmps[rd & 3]();
+                        gen_fcmps[rd & 3]();
 #else
-			gen_op_fcmps();
+                        gen_op_fcmps();
 #endif
-			break;
-		    case 0x52: /* V9 %fcc */
-                	gen_op_load_fpr_DT0(DFPREG(rs1));
-                	gen_op_load_fpr_DT1(DFPREG(rs2));
+                        break;
+                    case 0x52: /* V9 %fcc */
+                        gen_op_load_fpr_DT0(DFPREG(rs1));
+                        gen_op_load_fpr_DT1(DFPREG(rs2));
 #ifdef TARGET_SPARC64
-			gen_fcmpd[rd & 3]();
+                        gen_fcmpd[rd & 3]();
 #else
-			gen_op_fcmpd();
+                        gen_op_fcmpd();
 #endif
-			break;
-		    case 0x53: /* fcmpq */
-		        goto nfpu_insn;
-		    case 0x55: /* fcmpes, V9 %fcc */
-                	gen_op_load_fpr_FT0(rs1);
-                	gen_op_load_fpr_FT1(rs2);
+                        break;
+                    case 0x53: /* fcmpq */
+                        goto nfpu_insn;
+                    case 0x55: /* fcmpes, V9 %fcc */
+                        gen_op_load_fpr_FT0(rs1);
+                        gen_op_load_fpr_FT1(rs2);
 #ifdef TARGET_SPARC64
-			gen_fcmpes[rd & 3]();
+                        gen_fcmpes[rd & 3]();
 #else
-			gen_op_fcmpes();
+                        gen_op_fcmpes();
 #endif
-			break;
-		    case 0x56: /* fcmped, V9 %fcc */
-                	gen_op_load_fpr_DT0(DFPREG(rs1));
-                	gen_op_load_fpr_DT1(DFPREG(rs2));
+                        break;
+                    case 0x56: /* fcmped, V9 %fcc */
+                        gen_op_load_fpr_DT0(DFPREG(rs1));
+                        gen_op_load_fpr_DT1(DFPREG(rs2));
 #ifdef TARGET_SPARC64
-			gen_fcmped[rd & 3]();
+                        gen_fcmped[rd & 3]();
 #else
-			gen_op_fcmped();
+                        gen_op_fcmped();
 #endif
-			break;
-		    case 0x57: /* fcmpeq */
-		        goto nfpu_insn;
-		    default:
-                	goto illegal_insn;
-		}
+                        break;
+                    case 0x57: /* fcmpeq */
+                        goto nfpu_insn;
+                    default:
+                        goto illegal_insn;
+                }
 #if defined(OPTIM)
-	    } else if (xop == 0x2) {
-		// clr/mov shortcut
+            } else if (xop == 0x2) {
+                // clr/mov shortcut
 
                 rs1 = GET_FIELD(insn, 13, 17);
-		if (rs1 == 0) {
-		    // or %g0, x, y -> mov T1, x; mov y, T1
-		    if (IS_IMM) {	/* immediate */
-			rs2 = GET_FIELDs(insn, 19, 31);
-			gen_movl_simm_T1(rs2);
-		    } else {		/* register */
-			rs2 = GET_FIELD(insn, 27, 31);
-			gen_movl_reg_T1(rs2);
-		    }
-		    gen_movl_T1_reg(rd);
-		} else {
-		    gen_movl_reg_T0(rs1);
-		    if (IS_IMM) {	/* immediate */
-			// or x, #0, y -> mov T1, x; mov y, T1
-			rs2 = GET_FIELDs(insn, 19, 31);
-			if (rs2 != 0) {
-			    gen_movl_simm_T1(rs2);
-			    gen_op_or_T1_T0();
-			}
-		    } else {		/* register */
-			// or x, %g0, y -> mov T1, x; mov y, T1
-			rs2 = GET_FIELD(insn, 27, 31);
-			if (rs2 != 0) {
-			    gen_movl_reg_T1(rs2);
-			    gen_op_or_T1_T0();
-			}
-		    }
-		    gen_movl_T0_reg(rd);
-		}
+                if (rs1 == 0) {
+                    // or %g0, x, y -> mov T1, x; mov y, T1
+                    if (IS_IMM) {       /* immediate */
+                        rs2 = GET_FIELDs(insn, 19, 31);
+                        gen_movl_simm_T1(rs2);
+                    } else {            /* register */
+                        rs2 = GET_FIELD(insn, 27, 31);
+                        gen_movl_reg_T1(rs2);
+                    }
+                    gen_movl_T1_reg(rd);
+                } else {
+                    gen_movl_reg_T0(rs1);
+                    if (IS_IMM) {       /* immediate */
+                        // or x, #0, y -> mov T1, x; mov y, T1
+                        rs2 = GET_FIELDs(insn, 19, 31);
+                        if (rs2 != 0) {
+                            gen_movl_simm_T1(rs2);
+                            gen_op_or_T1_T0();
+                        }
+                    } else {            /* register */
+                        // or x, %g0, y -> mov T1, x; mov y, T1
+                        rs2 = GET_FIELD(insn, 27, 31);
+                        if (rs2 != 0) {
+                            gen_movl_reg_T1(rs2);
+                            gen_op_or_T1_T0();
+                        }
+                    }
+                    gen_movl_T0_reg(rd);
+                }
 #endif
 #ifdef TARGET_SPARC64
-	    } else if (xop == 0x25) { /* sll, V9 sllx */
+            } else if (xop == 0x25) { /* sll, V9 sllx */
                 rs1 = GET_FIELD(insn, 13, 17);
-		gen_movl_reg_T0(rs1);
-		if (IS_IMM) {	/* immediate */
+                gen_movl_reg_T0(rs1);
+                if (IS_IMM) {   /* immediate */
                     rs2 = GET_FIELDs(insn, 20, 31);
                     gen_movl_simm_T1(rs2);
-                } else {		/* register */
+                } else {                /* register */
                     rs2 = GET_FIELD(insn, 27, 31);
                     gen_movl_reg_T1(rs2);
                 }
-		if (insn & (1 << 12))
-		    gen_op_sllx();
-		else
-		    gen_op_sll();
-		gen_movl_T0_reg(rd);
-	    } else if (xop == 0x26) { /* srl, V9 srlx */
+                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);
-		gen_movl_reg_T0(rs1);
-		if (IS_IMM) {	/* immediate */
+                gen_movl_reg_T0(rs1);
+                if (IS_IMM) {   /* immediate */
                     rs2 = GET_FIELDs(insn, 20, 31);
                     gen_movl_simm_T1(rs2);
-                } else {		/* register */
+                } else {                /* register */
                     rs2 = GET_FIELD(insn, 27, 31);
                     gen_movl_reg_T1(rs2);
                 }
-		if (insn & (1 << 12))
-		    gen_op_srlx();
-		else
-		    gen_op_srl();
-		gen_movl_T0_reg(rd);
-	    } else if (xop == 0x27) { /* sra, V9 srax */
+                if (insn & (1 << 12))
+                    gen_op_srlx();
+                else
+                    gen_op_srl();
+                gen_movl_T0_reg(rd);
+            } else if (xop == 0x27) { /* sra, V9 srax */
                 rs1 = GET_FIELD(insn, 13, 17);
-		gen_movl_reg_T0(rs1);
-		if (IS_IMM) {	/* immediate */
+                gen_movl_reg_T0(rs1);
+                if (IS_IMM) {   /* immediate */
                     rs2 = GET_FIELDs(insn, 20, 31);
                     gen_movl_simm_T1(rs2);
-                } else {		/* register */
+                } else {                /* register */
                     rs2 = GET_FIELD(insn, 27, 31);
                     gen_movl_reg_T1(rs2);
                 }
-		if (insn & (1 << 12))
-		    gen_op_srax();
-		else
-		    gen_op_sra();
-		gen_movl_T0_reg(rd);
+                if (insn & (1 << 12))
+                    gen_op_srax();
+                else
+                    gen_op_sra();
+                gen_movl_T0_reg(rd);
 #endif
             } else if (xop < 0x36) {
                 rs1 = GET_FIELD(insn, 13, 17);
-		gen_movl_reg_T0(rs1);
-		if (IS_IMM) {	/* immediate */
+                gen_movl_reg_T0(rs1);
+                if (IS_IMM) {   /* immediate */
                     rs2 = GET_FIELDs(insn, 19, 31);
                     gen_movl_simm_T1(rs2);
-                } else {		/* register */
+                } else {                /* register */
                     rs2 = GET_FIELD(insn, 27, 31);
                     gen_movl_reg_T1(rs2);
                 }
@@ -1841,10 +1940,10 @@
                             gen_op_logic_T0_cc();
                         break;
                     case 0x2:
-			gen_op_or_T1_T0();
-			if (xop & 0x10)
-			    gen_op_logic_T0_cc();
-			break;
+                        gen_op_or_T1_T0();
+                        if (xop & 0x10)
+                            gen_op_logic_T0_cc();
+                        break;
                     case 0x3:
                         gen_op_xor_T1_T0();
                         if (xop & 0x10)
@@ -1878,7 +1977,7 @@
                             gen_op_addx_T1_T0();
                         break;
 #ifdef TARGET_SPARC64
-		    case 0x9: /* V9 mulx */
+                    case 0x9: /* V9 mulx */
                         gen_op_mulx_T1_T0();
                         break;
 #endif
@@ -1899,7 +1998,7 @@
                             gen_op_subx_T1_T0();
                         break;
 #ifdef TARGET_SPARC64
-		    case 0xd: /* V9 udivx */
+                    case 0xd: /* V9 udivx */
                         gen_op_udivx_T1_T0();
                         break;
 #endif
@@ -1916,40 +2015,42 @@
                     default:
                         goto illegal_insn;
                     }
-		    gen_movl_T0_reg(rd);
+                    gen_movl_T0_reg(rd);
                 } 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 */
-			gen_op_tsub_T1_T0_ccTV();
-		        gen_movl_T0_reg(rd);
-			break;
+                    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 */
+                        save_state(dc);
+                        gen_op_tadd_T1_T0_ccTV();
+                        gen_movl_T0_reg(rd);
+                        break;
+                    case 0x23: /* tsubcctv */
+                        save_state(dc);
+                        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);
                         break;
 #ifndef TARGET_SPARC64
-                    case 0x25:	/* sll */
-			gen_op_sll();
+                    case 0x25:  /* sll */
+                        gen_op_sll();
                         gen_movl_T0_reg(rd);
                         break;
                     case 0x26:  /* srl */
-			gen_op_srl();
+                        gen_op_srl();
                         gen_movl_T0_reg(rd);
                         break;
                     case 0x27:  /* sra */
-			gen_op_sra();
+                        gen_op_sra();
                         gen_movl_T0_reg(rd);
                         break;
 #endif
@@ -1957,8 +2058,8 @@
                         {
                             switch(rd) {
                             case 0: /* wry */
-				gen_op_xor_T1_T0();
-				gen_op_movtl_env_T0(offsetof(CPUSPARCState, y));
+                                gen_op_xor_T1_T0();
+                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, y));
                                 break;
 #ifndef TARGET_SPARC64
                             case 0x01 ... 0x0f: /* undefined in the
@@ -1971,62 +2072,68 @@
                                                    microSPARC II */
                                 break;
 #else
-			    case 0x2: /* V9 wrccr */
+                            case 0x2: /* V9 wrccr */
+                                gen_op_xor_T1_T0();
                                 gen_op_wrccr();
-				break;
-			    case 0x3: /* V9 wrasi */
-				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));
+                                break;
+                            case 0x3: /* V9 wrasi */
+                                gen_op_xor_T1_T0();
+                                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 */
+                                break;
+                            case 0xf: /* V9 sir, nop if user */
 #if !defined(CONFIG_USER_ONLY)
-				if (supervisor(dc))
-				    gen_op_sir();
+                                if (supervisor(dc))
+                                    gen_op_sir();
 #endif
-				break;
-			    case 0x13: /* Graphics Status */
+                                break;
+                            case 0x13: /* Graphics Status */
                                 if (gen_trap_ifnofpu(dc))
                                     goto jmp_insn;
-				gen_op_movtl_env_T0(offsetof(CPUSPARCState, gsr));
-				break;
-			    case 0x17: /* Tick compare */
+                                gen_op_xor_T1_T0();
+                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, gsr));
+                                break;
+                            case 0x17: /* Tick compare */
 #if !defined(CONFIG_USER_ONLY)
-				if (!supervisor(dc))
-				    goto illegal_insn;
+                                if (!supervisor(dc))
+                                    goto illegal_insn;
 #endif
+                                gen_op_xor_T1_T0();
                                 gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr));
                                 gen_op_wrtick_cmpr();
-				break;
-			    case 0x18: /* System tick */
+                                break;
+                            case 0x18: /* System tick */
 #if !defined(CONFIG_USER_ONLY)
-				if (!supervisor(dc))
-				    goto illegal_insn;
+                                if (!supervisor(dc))
+                                    goto illegal_insn;
 #endif
+                                gen_op_xor_T1_T0();
                                 gen_op_wrstick();
-				break;
-			    case 0x19: /* System tick compare */
+                                break;
+                            case 0x19: /* System tick compare */
 #if !defined(CONFIG_USER_ONLY)
-				if (!supervisor(dc))
-				    goto illegal_insn;
+                                if (!supervisor(dc))
+                                    goto illegal_insn;
 #endif
+                                gen_op_xor_T1_T0();
                                 gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
                                 gen_op_wrstick_cmpr();
-				break;
+                                break;
 
-			    case 0x10: /* Performance Control */
-			    case 0x11: /* Performance Instrumentation Counter */
-			    case 0x12: /* Dispatch Control */
-			    case 0x14: /* Softint set */
-			    case 0x15: /* Softint clear */
-			    case 0x16: /* Softint write */
+                            case 0x10: /* Performance Control */
+                            case 0x11: /* Performance Instrumentation Counter */
+                            case 0x12: /* Dispatch Control */
+                            case 0x14: /* Softint set */
+                            case 0x15: /* Softint clear */
+                            case 0x16: /* Softint write */
 #endif
                             default:
                                 goto illegal_insn;
@@ -2036,22 +2143,22 @@
 #if !defined(CONFIG_USER_ONLY)
                     case 0x31: /* wrpsr, V9 saved, restored */
                         {
-			    if (!supervisor(dc))
-				goto priv_insn;
+                            if (!supervisor(dc))
+                                goto priv_insn;
 #ifdef TARGET_SPARC64
-			    switch (rd) {
-			    case 0:
-				gen_op_saved();
-				break;
-			    case 1:
-				gen_op_restored();
-				break;
+                            switch (rd) {
+                            case 0:
+                                gen_op_saved();
+                                break;
+                            case 1:
+                                gen_op_restored();
+                                break;
                             case 2: /* UA2005 allclean */
                             case 3: /* UA2005 otherw */
                             case 4: /* UA2005 normalw */
                             case 5: /* UA2005 invalw */
                                 // XXX
-			    default:
+                            default:
                                 goto illegal_insn;
                             }
 #else
@@ -2059,69 +2166,69 @@
                             gen_op_wrpsr();
                             save_state(dc);
                             gen_op_next_insn();
-			    gen_op_movl_T0_0();
-			    gen_op_exit_tb();
-			    dc->is_br = 1;
+                            gen_op_movl_T0_0();
+                            gen_op_exit_tb();
+                            dc->is_br = 1;
 #endif
                         }
                         break;
                     case 0x32: /* wrwim, V9 wrpr */
                         {
-			    if (!supervisor(dc))
-				goto priv_insn;
+                            if (!supervisor(dc))
+                                goto priv_insn;
                             gen_op_xor_T1_T0();
 #ifdef TARGET_SPARC64
-			    switch (rd) {
-			    case 0: // tpc
-				gen_op_wrtpc();
-				break;
-			    case 1: // tnpc
-				gen_op_wrtnpc();
-				break;
-			    case 2: // tstate
-				gen_op_wrtstate();
-				break;
-			    case 3: // tt
-				gen_op_wrtt();
-				break;
-			    case 4: // tick
-				gen_op_wrtick();
-				break;
-			    case 5: // tba
-				gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
-				break;
-			    case 6: // pstate
-				gen_op_wrpstate();
+                            switch (rd) {
+                            case 0: // tpc
+                                gen_op_wrtpc();
+                                break;
+                            case 1: // tnpc
+                                gen_op_wrtnpc();
+                                break;
+                            case 2: // tstate
+                                gen_op_wrtstate();
+                                break;
+                            case 3: // tt
+                                gen_op_wrtt();
+                                break;
+                            case 4: // tick
+                                gen_op_wrtick();
+                                break;
+                            case 5: // tba
+                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
+                                break;
+                            case 6: // pstate
+                                gen_op_wrpstate();
                                 save_state(dc);
                                 gen_op_next_insn();
                                 gen_op_movl_T0_0();
                                 gen_op_exit_tb();
                                 dc->is_br = 1;
-				break;
-			    case 7: // tl
-				gen_op_movl_env_T0(offsetof(CPUSPARCState, tl));
-				break;
-			    case 8: // pil
-				gen_op_movl_env_T0(offsetof(CPUSPARCState, psrpil));
-				break;
-			    case 9: // cwp
-				gen_op_wrcwp();
-				break;
-			    case 10: // cansave
-				gen_op_movl_env_T0(offsetof(CPUSPARCState, cansave));
-				break;
-			    case 11: // canrestore
-				gen_op_movl_env_T0(offsetof(CPUSPARCState, canrestore));
-				break;
-			    case 12: // cleanwin
-				gen_op_movl_env_T0(offsetof(CPUSPARCState, cleanwin));
-				break;
-			    case 13: // otherwin
-				gen_op_movl_env_T0(offsetof(CPUSPARCState, otherwin));
-				break;
-			    case 14: // wstate
-				gen_op_movl_env_T0(offsetof(CPUSPARCState, wstate));
-				break;
+                                break;
+                            case 7: // tl
+                                gen_op_movl_env_T0(offsetof(CPUSPARCState, tl));
+                                break;
+                            case 8: // pil
+                                gen_op_movl_env_T0(offsetof(CPUSPARCState, psrpil));
+                                break;
+                            case 9: // cwp
+                                gen_op_wrcwp();
+                                break;
+                            case 10: // cansave
+                                gen_op_movl_env_T0(offsetof(CPUSPARCState, cansave));
+                                break;
+                            case 11: // canrestore
+                                gen_op_movl_env_T0(offsetof(CPUSPARCState, canrestore));
+                                break;
+                            case 12: // cleanwin
+                                gen_op_movl_env_T0(offsetof(CPUSPARCState, cleanwin));
+                                break;
+                            case 13: // otherwin
+                                gen_op_movl_env_T0(offsetof(CPUSPARCState, otherwin));
+                                break;
+                            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;
@@ -2130,19 +2237,19 @@
                                     goto priv_insn;
                                 gen_op_movl_env_T0(offsetof(CPUSPARCState, ssr));
                                 break;
-			    default:
-				goto illegal_insn;
-			    }
+                            default:
+                                goto illegal_insn;
+                            }
 #else
-			    gen_op_wrwim();
+                            gen_op_wrwim();
 #endif
                         }
                         break;
                     case 0x33: /* wrtbr, UA2005 wrhpr */
                         {
 #ifndef TARGET_SPARC64
-			    if (!supervisor(dc))
-				goto priv_insn;
+                            if (!supervisor(dc))
+                                goto priv_insn;
                             gen_op_xor_T1_T0();
                             gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
 #else
@@ -2180,77 +2287,77 @@
                         break;
 #endif
 #ifdef TARGET_SPARC64
-		    case 0x2c: /* V9 movcc */
-			{
-			    int cc = GET_FIELD_SP(insn, 11, 12);
-			    int cond = GET_FIELD_SP(insn, 14, 17);
-			    if (IS_IMM) {	/* immediate */
-				rs2 = GET_FIELD_SPs(insn, 0, 10);
-				gen_movl_simm_T1(rs2);
-			    }
-			    else {
-				rs2 = GET_FIELD_SP(insn, 0, 4);
-				gen_movl_reg_T1(rs2);
-			    }
-			    gen_movl_reg_T0(rd);
-			    flush_T2(dc);
-			    if (insn & (1 << 18)) {
-				if (cc == 0)
-				    gen_cond[0][cond]();
-				else if (cc == 2)
-				    gen_cond[1][cond]();
-				else
-				    goto illegal_insn;
-			    } else {
-				gen_fcond[cc][cond]();
-			    }
-			    gen_op_mov_cc();
-			    gen_movl_T0_reg(rd);
-			    break;
-			}
-		    case 0x2d: /* V9 sdivx */
+                    case 0x2c: /* V9 movcc */
+                        {
+                            int cc = GET_FIELD_SP(insn, 11, 12);
+                            int cond = GET_FIELD_SP(insn, 14, 17);
+                            if (IS_IMM) {       /* immediate */
+                                rs2 = GET_FIELD_SPs(insn, 0, 10);
+                                gen_movl_simm_T1(rs2);
+                            }
+                            else {
+                                rs2 = GET_FIELD_SP(insn, 0, 4);
+                                gen_movl_reg_T1(rs2);
+                            }
+                            gen_movl_reg_T0(rd);
+                            flush_T2(dc);
+                            if (insn & (1 << 18)) {
+                                if (cc == 0)
+                                    gen_cond[0][cond]();
+                                else if (cc == 2)
+                                    gen_cond[1][cond]();
+                                else
+                                    goto illegal_insn;
+                            } else {
+                                gen_fcond[cc][cond]();
+                            }
+                            gen_op_mov_cc();
+                            gen_movl_T0_reg(rd);
+                            break;
+                        }
+                    case 0x2d: /* V9 sdivx */
                         gen_op_sdivx_T1_T0();
-			gen_movl_T0_reg(rd);
+                        gen_movl_T0_reg(rd);
                         break;
-		    case 0x2e: /* V9 popc */
-			{
-			    if (IS_IMM) {	/* immediate */
-				rs2 = GET_FIELD_SPs(insn, 0, 12);
-				gen_movl_simm_T1(rs2);
-				// XXX optimize: popc(constant)
-			    }
-			    else {
-				rs2 = GET_FIELD_SP(insn, 0, 4);
-				gen_movl_reg_T1(rs2);
-			    }
-			    gen_op_popc();
-			    gen_movl_T0_reg(rd);
-			}
-		    case 0x2f: /* V9 movr */
-			{
-			    int cond = GET_FIELD_SP(insn, 10, 12);
-			    rs1 = GET_FIELD(insn, 13, 17);
-			    flush_T2(dc);
-			    gen_movl_reg_T0(rs1);
-			    gen_cond_reg(cond);
-			    if (IS_IMM) {	/* immediate */
-				rs2 = GET_FIELD_SPs(insn, 0, 9);
-				gen_movl_simm_T1(rs2);
-			    }
-			    else {
-				rs2 = GET_FIELD_SP(insn, 0, 4);
-				gen_movl_reg_T1(rs2);
-			    }
-			    gen_movl_reg_T0(rd);
-			    gen_op_mov_cc();
-			    gen_movl_T0_reg(rd);
-			    break;
-			}
+                    case 0x2e: /* V9 popc */
+                        {
+                            if (IS_IMM) {       /* immediate */
+                                rs2 = GET_FIELD_SPs(insn, 0, 12);
+                                gen_movl_simm_T1(rs2);
+                                // XXX optimize: popc(constant)
+                            }
+                            else {
+                                rs2 = GET_FIELD_SP(insn, 0, 4);
+                                gen_movl_reg_T1(rs2);
+                            }
+                            gen_op_popc();
+                            gen_movl_T0_reg(rd);
+                        }
+                    case 0x2f: /* V9 movr */
+                        {
+                            int cond = GET_FIELD_SP(insn, 10, 12);
+                            rs1 = GET_FIELD(insn, 13, 17);
+                            flush_T2(dc);
+                            gen_movl_reg_T0(rs1);
+                            gen_cond_reg(cond);
+                            if (IS_IMM) {       /* immediate */
+                                rs2 = GET_FIELD_SPs(insn, 0, 9);
+                                gen_movl_simm_T1(rs2);
+                            }
+                            else {
+                                rs2 = GET_FIELD_SP(insn, 0, 4);
+                                gen_movl_reg_T1(rs2);
+                            }
+                            gen_movl_reg_T0(rd);
+                            gen_op_mov_cc();
+                            gen_movl_T0_reg(rd);
+                            break;
+                        }
 #endif
-		    default:
-			goto illegal_insn;
-		    }
-		}
+                    default:
+                        goto illegal_insn;
+                    }
+                }
             } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
 #ifdef TARGET_SPARC64
                 int opf = GET_FIELD_SP(insn, 5, 13);
@@ -2647,75 +2754,75 @@
                     goto illegal_insn;
                 }
 #else
-	        goto ncp_insn;
+                goto ncp_insn;
 #endif
             } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
 #ifdef TARGET_SPARC64
-	        goto illegal_insn;
+                goto illegal_insn;
 #else
-	        goto ncp_insn;
+                goto ncp_insn;
 #endif
 #ifdef TARGET_SPARC64
-	    } else if (xop == 0x39) { /* V9 return */
+            } else if (xop == 0x39) { /* V9 return */
                 rs1 = GET_FIELD(insn, 13, 17);
                 save_state(dc);
-		gen_movl_reg_T0(rs1);
-                if (IS_IMM) {	/* immediate */
-		    rs2 = GET_FIELDs(insn, 19, 31);
+                gen_movl_reg_T0(rs1);
+                if (IS_IMM) {   /* immediate */
+                    rs2 = GET_FIELDs(insn, 19, 31);
 #if defined(OPTIM)
-		    if (rs2) {
+                    if (rs2) {
 #endif
-			gen_movl_simm_T1(rs2);
-			gen_op_add_T1_T0();
+                        gen_movl_simm_T1(rs2);
+                        gen_op_add_T1_T0();
 #if defined(OPTIM)
-		    }
+                    }
 #endif
-                } else {		/* register */
+                } else {                /* register */
                     rs2 = GET_FIELD(insn, 27, 31);
 #if defined(OPTIM)
-		    if (rs2) {
+                    if (rs2) {
 #endif
-			gen_movl_reg_T1(rs2);
-			gen_op_add_T1_T0();
+                        gen_movl_reg_T1(rs2);
+                        gen_op_add_T1_T0();
 #if defined(OPTIM)
-		    }
+                    }
 #endif
                 }
-		gen_op_restore();
-		gen_mov_pc_npc(dc);
+                gen_op_restore();
+                gen_mov_pc_npc(dc);
                 gen_op_check_align_T0_3();
-		gen_op_movl_npc_T0();
-		dc->npc = DYNAMIC_PC;
-		goto jmp_insn;
+                gen_op_movl_npc_T0();
+                dc->npc = DYNAMIC_PC;
+                goto jmp_insn;
 #endif
-	    } else {
+            } else {
                 rs1 = GET_FIELD(insn, 13, 17);
-		gen_movl_reg_T0(rs1);
-                if (IS_IMM) {	/* immediate */
-		    rs2 = GET_FIELDs(insn, 19, 31);
+                gen_movl_reg_T0(rs1);
+                if (IS_IMM) {   /* immediate */
+                    rs2 = GET_FIELDs(insn, 19, 31);
 #if defined(OPTIM)
-		    if (rs2) {
+                    if (rs2) {
 #endif
-			gen_movl_simm_T1(rs2);
-			gen_op_add_T1_T0();
+                        gen_movl_simm_T1(rs2);
+                        gen_op_add_T1_T0();
 #if defined(OPTIM)
-		    }
+                    }
 #endif
-                } else {		/* register */
+                } else {                /* register */
                     rs2 = GET_FIELD(insn, 27, 31);
 #if defined(OPTIM)
-		    if (rs2) {
+                    if (rs2) {
 #endif
-			gen_movl_reg_T1(rs2);
-			gen_op_add_T1_T0();
+                        gen_movl_reg_T1(rs2);
+                        gen_op_add_T1_T0();
 #if defined(OPTIM)
-		    }
+                    }
 #endif
                 }
-		switch (xop) {
-		case 0x38:	/* jmpl */
-		    {
-			if (rd != 0) {
+                switch (xop) {
+                case 0x38:      /* jmpl */
+                    {
+                        if (rd != 0) {
 #ifdef TARGET_SPARC64
                             if (dc->pc == (uint32_t)dc->pc) {
                                 gen_op_movl_T1_im(dc->pc);
@@ -2723,512 +2830,468 @@
                                 gen_op_movq_T1_im64(dc->pc >> 32, dc->pc);
                             }
 #else
-			    gen_op_movl_T1_im(dc->pc);
+                            gen_op_movl_T1_im(dc->pc);
 #endif
-			    gen_movl_T1_reg(rd);
-			}
+                            gen_movl_T1_reg(rd);
+                        }
                         gen_mov_pc_npc(dc);
                         gen_op_check_align_T0_3();
-			gen_op_movl_npc_T0();
-			dc->npc = DYNAMIC_PC;
-		    }
-		    goto jmp_insn;
+                        gen_op_movl_npc_T0();
+                        dc->npc = DYNAMIC_PC;
+                    }
+                    goto jmp_insn;
 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
-		case 0x39:	/* rett, V9 return */
-		    {
-			if (!supervisor(dc))
-			    goto priv_insn;
+                case 0x39:      /* rett, V9 return */
+                    {
+                        if (!supervisor(dc))
+                            goto priv_insn;
                         gen_mov_pc_npc(dc);
                         gen_op_check_align_T0_3();
-			gen_op_movl_npc_T0();
-			dc->npc = DYNAMIC_PC;
-			gen_op_rett();
-		    }
-		    goto jmp_insn;
+                        gen_op_movl_npc_T0();
+                        dc->npc = DYNAMIC_PC;
+                        gen_op_rett();
+                    }
+                    goto jmp_insn;
 #endif
-		case 0x3b: /* flush */
-		    gen_op_flush_T0();
-		    break;
-		case 0x3c:	/* save */
-		    save_state(dc);
-		    gen_op_save();
-		    gen_movl_T0_reg(rd);
-		    break;
-		case 0x3d:	/* restore */
-		    save_state(dc);
-		    gen_op_restore();
-		    gen_movl_T0_reg(rd);
-		    break;
+                case 0x3b: /* flush */
+                    gen_op_flush_T0();
+                    break;
+                case 0x3c:      /* save */
+                    save_state(dc);
+                    gen_op_save();
+                    gen_movl_T0_reg(rd);
+                    break;
+                case 0x3d:      /* restore */
+                    save_state(dc);
+                    gen_op_restore();
+                    gen_movl_T0_reg(rd);
+                    break;
 #if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
-		case 0x3e:      /* V9 done/retry */
-		    {
-			switch (rd) {
-			case 0:
-			    if (!supervisor(dc))
-				goto priv_insn;
-			    dc->npc = DYNAMIC_PC;
-			    dc->pc = DYNAMIC_PC;
-			    gen_op_done();
-			    goto jmp_insn;
-			case 1:
-			    if (!supervisor(dc))
-				goto priv_insn;
-			    dc->npc = DYNAMIC_PC;
-			    dc->pc = DYNAMIC_PC;
-			    gen_op_retry();
-			    goto jmp_insn;
-			default:
-			    goto illegal_insn;
-			}
-		    }
-		    break;
+                case 0x3e:      /* V9 done/retry */
+                    {
+                        switch (rd) {
+                        case 0:
+                            if (!supervisor(dc))
+                                goto priv_insn;
+                            dc->npc = DYNAMIC_PC;
+                            dc->pc = DYNAMIC_PC;
+                            gen_op_done();
+                            goto jmp_insn;
+                        case 1:
+                            if (!supervisor(dc))
+                                goto priv_insn;
+                            dc->npc = DYNAMIC_PC;
+                            dc->pc = DYNAMIC_PC;
+                            gen_op_retry();
+                            goto jmp_insn;
+                        default:
+                            goto illegal_insn;
+                        }
+                    }
+                    break;
 #endif
-		default:
-		    goto illegal_insn;
-		}
+                default:
+                    goto illegal_insn;
+                }
             }
-	    break;
-	}
-	break;
-    case 3:			/* load/store instructions */
-	{
-	    unsigned int xop = GET_FIELD(insn, 7, 12);
-	    rs1 = GET_FIELD(insn, 13, 17);
+            break;
+        }
+        break;
+    case 3:                     /* load/store instructions */
+        {
+            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);
+            gen_movl_reg_T0(rs1);
+            if (xop == 0x3c || xop == 0x3e)
+            {
+                rs2 = GET_FIELD(insn, 27, 31);
+                gen_movl_reg_T1(rs2);
+            }
+            else if (IS_IMM) {       /* immediate */
+                rs2 = GET_FIELDs(insn, 19, 31);
 #if defined(OPTIM)
-		if (rs2 != 0) {
+                if (rs2 != 0) {
 #endif
-		    gen_movl_simm_T1(rs2);
-		    gen_op_add_T1_T0();
+                    gen_movl_simm_T1(rs2);
+                    gen_op_add_T1_T0();
 #if defined(OPTIM)
-		}
+                }
 #endif
-	    } else {		/* register */
-		rs2 = GET_FIELD(insn, 27, 31);
+            } else {            /* register */
+                rs2 = GET_FIELD(insn, 27, 31);
 #if defined(OPTIM)
-		if (rs2 != 0) {
+                if (rs2 != 0) {
 #endif
-		    gen_movl_reg_T1(rs2);
-		    gen_op_add_T1_T0();
+                    gen_movl_reg_T1(rs2);
+                    gen_op_add_T1_T0();
 #if defined(OPTIM)
-		}
+                }
 #endif
-	    }
+            }
             if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
                 (xop > 0x17 && xop <= 0x1d ) ||
                 (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
-		switch (xop) {
-		case 0x0:	/* load word */
-#ifdef CONFIG_USER_ONLY
+                switch (xop) {
+                case 0x0:       /* load word */
                     gen_op_check_align_T0_3();
-#endif
 #ifndef TARGET_SPARC64
-		    gen_op_ldst(ld);
+                    gen_op_ldst(ld);
 #else
                     gen_op_ldst(lduw);
 #endif
-		    break;
-		case 0x1:	/* load unsigned byte */
-		    gen_op_ldst(ldub);
-		    break;
-		case 0x2:	/* load unsigned halfword */
-#ifdef CONFIG_USER_ONLY
+                    break;
+                case 0x1:       /* load unsigned byte */
+                    gen_op_ldst(ldub);
+                    break;
+                case 0x2:       /* load unsigned halfword */
                     gen_op_check_align_T0_1();
-#endif
-		    gen_op_ldst(lduh);
-		    break;
-		case 0x3:	/* load double word */
+                    gen_op_ldst(lduh);
+                    break;
+                case 0x3:       /* load double word */
+                    if (rd & 1)
+                        goto illegal_insn;
                     gen_op_check_align_T0_7();
-		    if (rd & 1)
-                        goto illegal_insn;
-		    gen_op_ldst(ldd);
-		    gen_movl_T0_reg(rd + 1);
-		    break;
-		case 0x9:	/* load signed byte */
-		    gen_op_ldst(ldsb);
-		    break;
-		case 0xa:	/* load signed halfword */
-#ifdef CONFIG_USER_ONLY
+                    gen_op_ldst(ldd);
+                    gen_movl_T0_reg(rd + 1);
+                    break;
+                case 0x9:       /* load signed byte */
+                    gen_op_ldst(ldsb);
+                    break;
+                case 0xa:       /* load signed halfword */
                     gen_op_check_align_T0_1();
-#endif
-		    gen_op_ldst(ldsh);
-		    break;
-		case 0xd:	/* ldstub -- XXX: should be atomically */
-		    gen_op_ldst(ldstub);
-		    break;
-		case 0x0f:	/* swap register with memory. Also atomically */
-#ifdef CONFIG_USER_ONLY
+                    gen_op_ldst(ldsh);
+                    break;
+                case 0xd:       /* ldstub -- XXX: should be atomically */
+                    gen_op_ldst(ldstub);
+                    break;
+                case 0x0f:      /* swap register with memory. Also atomically */
                     gen_op_check_align_T0_3();
-#endif
-		    gen_movl_reg_T1(rd);
-		    gen_op_ldst(swap);
-		    break;
+                    gen_movl_reg_T1(rd);
+                    gen_op_ldst(swap);
+                    break;
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
-		case 0x10:	/* load word alternate */
+                case 0x10:      /* load word alternate */
 #ifndef TARGET_SPARC64
-		    if (IS_IMM)
-			goto illegal_insn;
-		    if (!supervisor(dc))
-			goto priv_insn;
-#ifdef CONFIG_USER_ONLY
-                    gen_op_check_align_T0_3();
+                    if (IS_IMM)
+                        goto illegal_insn;
+                    if (!supervisor(dc))
+                        goto priv_insn;
 #endif
-		    gen_op_lda(insn, 1, 4, 0);
-#else
-#ifdef CONFIG_USER_ONLY
                     gen_op_check_align_T0_3();
-#endif
-                    gen_op_lduwa(insn, 1, 4, 0);
-#endif
-		    break;
-		case 0x11:	/* load unsigned byte alternate */
+                    gen_ld_asi(insn, 4, 0);
+                    break;
+                case 0x11:      /* load unsigned byte alternate */
 #ifndef TARGET_SPARC64
-		    if (IS_IMM)
-			goto illegal_insn;
-		    if (!supervisor(dc))
-			goto priv_insn;
+                    if (IS_IMM)
+                        goto illegal_insn;
+                    if (!supervisor(dc))
+                        goto priv_insn;
 #endif
-		    gen_op_lduba(insn, 1, 1, 0);
-		    break;
-		case 0x12:	/* load unsigned halfword alternate */
+                    gen_ld_asi(insn, 1, 0);
+                    break;
+                case 0x12:      /* load unsigned halfword alternate */
 #ifndef TARGET_SPARC64
-		    if (IS_IMM)
-			goto illegal_insn;
-		    if (!supervisor(dc))
-			goto priv_insn;
+                    if (IS_IMM)
+                        goto illegal_insn;
+                    if (!supervisor(dc))
+                        goto priv_insn;
 #endif
-#ifdef CONFIG_USER_ONLY
                     gen_op_check_align_T0_1();
-#endif
-		    gen_op_lduha(insn, 1, 2, 0);
-		    break;
-		case 0x13:	/* load double word alternate */
+                    gen_ld_asi(insn, 2, 0);
+                    break;
+                case 0x13:      /* load double word alternate */
 #ifndef TARGET_SPARC64
-		    if (IS_IMM)
-			goto illegal_insn;
-		    if (!supervisor(dc))
-			goto priv_insn;
+                    if (IS_IMM)
+                        goto illegal_insn;
+                    if (!supervisor(dc))
+                        goto priv_insn;
 #endif
-		    if (rd & 1)
+                    if (rd & 1)
                         goto illegal_insn;
                     gen_op_check_align_T0_7();
-		    gen_op_ldda(insn, 1, 8, 0);
-		    gen_movl_T0_reg(rd + 1);
-		    break;
-		case 0x19:	/* load signed byte alternate */
+                    gen_ldda_asi(insn);
+                    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;
+                    if (IS_IMM)
+                        goto illegal_insn;
+                    if (!supervisor(dc))
+                        goto priv_insn;
 #endif
-		    gen_op_ldsba(insn, 1, 1, 1);
-		    break;
-		case 0x1a:	/* load signed halfword alternate */
+                    gen_ld_asi(insn, 1, 1);
+                    break;
+                case 0x1a:      /* load signed halfword alternate */
 #ifndef TARGET_SPARC64
-		    if (IS_IMM)
-			goto illegal_insn;
-		    if (!supervisor(dc))
-			goto priv_insn;
+                    if (IS_IMM)
+                        goto illegal_insn;
+                    if (!supervisor(dc))
+                        goto priv_insn;
 #endif
-#ifdef CONFIG_USER_ONLY
                     gen_op_check_align_T0_1();
-#endif
-		    gen_op_ldsha(insn, 1, 2 ,1);
-		    break;
-		case 0x1d:	/* ldstuba -- XXX: should be atomically */
+                    gen_ld_asi(insn, 2, 1);
+                    break;
+                case 0x1d:      /* ldstuba -- XXX: should be atomically */
 #ifndef TARGET_SPARC64
-		    if (IS_IMM)
-			goto illegal_insn;
-		    if (!supervisor(dc))
-			goto priv_insn;
+                    if (IS_IMM)
+                        goto illegal_insn;
+                    if (!supervisor(dc))
+                        goto priv_insn;
 #endif
-		    gen_op_ldstuba(insn, 1, 1, 0);
-		    break;
-		case 0x1f:	/* swap reg with alt. memory. Also atomically */
+                    gen_ldstub_asi(insn);
+                    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;
+                    if (IS_IMM)
+                        goto illegal_insn;
+                    if (!supervisor(dc))
+                        goto priv_insn;
 #endif
-		    gen_movl_reg_T1(rd);
-#ifdef CONFIG_USER_ONLY
                     gen_op_check_align_T0_3();
-#endif
-		    gen_op_swapa(insn, 1, 4, 0);
-		    break;
+                    gen_movl_reg_T1(rd);
+                    gen_swap_asi(insn);
+                    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;
-                    (void) &gen_op_ldfa;
-                    (void) &gen_op_lddfa;
-#else
-                    (void) &gen_op_lda;
-#if !defined(CONFIG_USER_ONLY)
-		    (void) &gen_op_cas;
-		    (void) &gen_op_casx;
+                case 0x30: /* ldc */
+                case 0x31: /* ldcsr */
+                case 0x33: /* lddc */
+                    goto ncp_insn;
 #endif
 #endif
-#endif
 #ifdef TARGET_SPARC64
-		case 0x08: /* V9 ldsw */
-#ifdef CONFIG_USER_ONLY
+                case 0x08: /* V9 ldsw */
                     gen_op_check_align_T0_3();
-#endif
-		    gen_op_ldst(ldsw);
-		    break;
-		case 0x0b: /* V9 ldx */
+                    gen_op_ldst(ldsw);
+                    break;
+                case 0x0b: /* V9 ldx */
                     gen_op_check_align_T0_7();
-		    gen_op_ldst(ldx);
-		    break;
-		case 0x18: /* V9 ldswa */
-#ifdef CONFIG_USER_ONLY
+                    gen_op_ldst(ldx);
+                    break;
+                case 0x18: /* V9 ldswa */
                     gen_op_check_align_T0_3();
-#endif
-		    gen_op_ldswa(insn, 1, 4, 1);
-		    break;
-		case 0x1b: /* V9 ldxa */
+                    gen_ld_asi(insn, 4, 1);
+                    break;
+                case 0x1b: /* V9 ldxa */
                     gen_op_check_align_T0_7();
-		    gen_op_ldxa(insn, 1, 8, 0);
-		    break;
-		case 0x2d: /* V9 prefetch, no effect */
-		    goto skip_move;
-		case 0x30: /* V9 ldfa */
-#ifdef CONFIG_USER_ONLY
+                    gen_ld_asi(insn, 8, 0);
+                    break;
+                case 0x2d: /* V9 prefetch, no effect */
+                    goto skip_move;
+                case 0x30: /* V9 ldfa */
                     gen_op_check_align_T0_3();
+                    gen_ldf_asi(insn, 4);
+                    goto skip_move;
+                case 0x33: /* V9 lddfa */
+                    gen_op_check_align_T0_3();
+                    gen_ldf_asi(insn, 8);
+                    goto skip_move;
+                case 0x3d: /* V9 prefetcha, no effect */
+                    goto skip_move;
+                case 0x32: /* V9 ldqfa */
+                    goto nfpu_insn;
 #endif
-		    gen_op_ldfa(insn, 1, 8, 0); // XXX
-		    break;
-		case 0x33: /* V9 lddfa */
-                    gen_op_check_align_T0_7();
-		    gen_op_lddfa(insn, 1, 8, 0); // XXX
-
-		    break;
-		case 0x3d: /* V9 prefetcha, no effect */
-		    goto skip_move;
-		case 0x32: /* V9 ldqfa */
-		    goto nfpu_insn;
-#endif
-		default:
-		    goto illegal_insn;
-		}
-		gen_movl_T1_reg(rd);
+                default:
+                    goto illegal_insn;
+                }
+                gen_movl_T1_reg(rd);
 #ifdef TARGET_SPARC64
-	    skip_move: ;
+            skip_move: ;
 #endif
-	    } else if (xop >= 0x20 && xop < 0x24) {
+            } else if (xop >= 0x20 && xop < 0x24) {
                 if (gen_trap_ifnofpu(dc))
                     goto jmp_insn;
-		switch (xop) {
-		case 0x20:	/* load fpreg */
-#ifdef CONFIG_USER_ONLY
+                switch (xop) {
+                case 0x20:      /* load fpreg */
                     gen_op_check_align_T0_3();
-#endif
-		    gen_op_ldst(ldf);
-		    gen_op_store_FT0_fpr(rd);
-		    break;
-		case 0x21:	/* load fsr */
-#ifdef CONFIG_USER_ONLY
+                    gen_op_ldst(ldf);
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x21:      /* load fsr */
                     gen_op_check_align_T0_3();
-#endif
-		    gen_op_ldst(ldf);
-		    gen_op_ldfsr();
-		    break;
-		case 0x22:      /* load quad fpreg */
-		    goto nfpu_insn;
-		case 0x23:	/* load double fpreg */
+                    gen_op_ldst(ldf);
+                    gen_op_ldfsr();
+                    break;
+                case 0x22:      /* load quad fpreg */
+                    goto nfpu_insn;
+                case 0x23:      /* load double fpreg */
                     gen_op_check_align_T0_7();
-		    gen_op_ldst(lddf);
-		    gen_op_store_DT0_fpr(DFPREG(rd));
-		    break;
-		default:
-		    goto illegal_insn;
-		}
-	    } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || \
-		       xop == 0xe || xop == 0x1e) {
-		gen_movl_reg_T1(rd);
-		switch (xop) {
-		case 0x4:
-#ifdef CONFIG_USER_ONLY
+                    gen_op_ldst(lddf);
+                    gen_op_store_DT0_fpr(DFPREG(rd));
+                    break;
+                default:
+                    goto illegal_insn;
+                }
+            } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || \
+                       xop == 0xe || xop == 0x1e) {
+                gen_movl_reg_T1(rd);
+                switch (xop) {
+                case 0x4:
                     gen_op_check_align_T0_3();
-#endif
-		    gen_op_ldst(st);
-		    break;
-		case 0x5:
-		    gen_op_ldst(stb);
-		    break;
-		case 0x6:
-#ifdef CONFIG_USER_ONLY
+                    gen_op_ldst(st);
+                    break;
+                case 0x5:
+                    gen_op_ldst(stb);
+                    break;
+                case 0x6:
                     gen_op_check_align_T0_1();
-#endif
-		    gen_op_ldst(sth);
-		    break;
-		case 0x7:
-		    if (rd & 1)
+                    gen_op_ldst(sth);
+                    break;
+                case 0x7:
+                    if (rd & 1)
                         goto illegal_insn;
                     gen_op_check_align_T0_7();
                     flush_T2(dc);
-		    gen_movl_reg_T2(rd + 1);
-		    gen_op_ldst(std);
-		    break;
+                    gen_movl_reg_T2(rd + 1);
+                    gen_op_ldst(std);
+                    break;
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
-		case 0x14:
+                case 0x14:
 #ifndef TARGET_SPARC64
-		    if (IS_IMM)
-			goto illegal_insn;
-		    if (!supervisor(dc))
-			goto priv_insn;
+                    if (IS_IMM)
+                        goto illegal_insn;
+                    if (!supervisor(dc))
+                        goto priv_insn;
 #endif
-#ifdef CONFIG_USER_ONLY
                     gen_op_check_align_T0_3();
-#endif
-		    gen_op_sta(insn, 0, 4, 0);
+                    gen_st_asi(insn, 4);
                     break;
-		case 0x15:
+                case 0x15:
 #ifndef TARGET_SPARC64
-		    if (IS_IMM)
-			goto illegal_insn;
-		    if (!supervisor(dc))
-			goto priv_insn;
+                    if (IS_IMM)
+                        goto illegal_insn;
+                    if (!supervisor(dc))
+                        goto priv_insn;
 #endif
-		    gen_op_stba(insn, 0, 1, 0);
+                    gen_st_asi(insn, 1);
                     break;
-		case 0x16:
+                case 0x16:
 #ifndef TARGET_SPARC64
-		    if (IS_IMM)
-			goto illegal_insn;
-		    if (!supervisor(dc))
-			goto priv_insn;
+                    if (IS_IMM)
+                        goto illegal_insn;
+                    if (!supervisor(dc))
+                        goto priv_insn;
 #endif
-#ifdef CONFIG_USER_ONLY
                     gen_op_check_align_T0_1();
-#endif
-		    gen_op_stha(insn, 0, 2, 0);
+                    gen_st_asi(insn, 2);
                     break;
-		case 0x17:
+                case 0x17:
 #ifndef TARGET_SPARC64
-		    if (IS_IMM)
-			goto illegal_insn;
-		    if (!supervisor(dc))
-			goto priv_insn;
+                    if (IS_IMM)
+                        goto illegal_insn;
+                    if (!supervisor(dc))
+                        goto priv_insn;
 #endif
-		    if (rd & 1)
+                    if (rd & 1)
                         goto illegal_insn;
                     gen_op_check_align_T0_7();
                     flush_T2(dc);
-		    gen_movl_reg_T2(rd + 1);
-		    gen_op_stda(insn, 0, 8, 0);
+                    gen_movl_reg_T2(rd + 1);
+                    gen_stda_asi(insn);
                     break;
 #endif
 #ifdef TARGET_SPARC64
-		case 0x0e: /* V9 stx */
+                case 0x0e: /* V9 stx */
                     gen_op_check_align_T0_7();
-		    gen_op_ldst(stx);
-		    break;
-		case 0x1e: /* V9 stxa */
+                    gen_op_ldst(stx);
+                    break;
+                case 0x1e: /* V9 stxa */
                     gen_op_check_align_T0_7();
-		    gen_op_stxa(insn, 0, 8, 0); // XXX
-		    break;
+                    gen_st_asi(insn, 8);
+                    break;
 #endif
-		default:
-		    goto illegal_insn;
-		}
-	    } else if (xop > 0x23 && xop < 0x28) {
+                default:
+                    goto illegal_insn;
+                }
+            } else if (xop > 0x23 && xop < 0x28) {
                 if (gen_trap_ifnofpu(dc))
                     goto jmp_insn;
-		switch (xop) {
-		case 0x24:
-#ifdef CONFIG_USER_ONLY
+                switch (xop) {
+                case 0x24:
                     gen_op_check_align_T0_3();
-#endif
                     gen_op_load_fpr_FT0(rd);
-		    gen_op_ldst(stf);
-		    break;
-		case 0x25: /* stfsr, V9 stxfsr */
+                    gen_op_ldst(stf);
+                    break;
+                case 0x25: /* stfsr, V9 stxfsr */
 #ifdef CONFIG_USER_ONLY
                     gen_op_check_align_T0_3();
 #endif
-		    gen_op_stfsr();
-		    gen_op_ldst(stf);
-		    break;
+                    gen_op_stfsr();
+                    gen_op_ldst(stf);
+                    break;
 #if !defined(CONFIG_USER_ONLY)
-		case 0x26: /* stdfq */
-		    if (!supervisor(dc))
-			goto priv_insn;
-		    if (gen_trap_ifnofpu(dc))
-			goto jmp_insn;
-		    goto nfq_insn;
+                case 0x26: /* stdfq */
+                    if (!supervisor(dc))
+                        goto priv_insn;
+                    if (gen_trap_ifnofpu(dc))
+                        goto jmp_insn;
+                    goto nfq_insn;
 #endif
-		case 0x27:
+                case 0x27:
                     gen_op_check_align_T0_7();
                     gen_op_load_fpr_DT0(DFPREG(rd));
-		    gen_op_ldst(stdf);
-		    break;
-		default:
-		    goto illegal_insn;
-		}
-	    } else if (xop > 0x33 && xop < 0x3f) {
-		switch (xop) {
+                    gen_op_ldst(stdf);
+                    break;
+                default:
+                    goto illegal_insn;
+                }
+            } else if (xop > 0x33 && xop < 0x3f) {
+                switch (xop) {
 #ifdef TARGET_SPARC64
-		case 0x34: /* V9 stfa */
-#ifdef CONFIG_USER_ONLY
+                case 0x34: /* V9 stfa */
                     gen_op_check_align_T0_3();
-#endif
-		    gen_op_stfa(insn, 0, 0, 0); // XXX
-		    break;
-		case 0x37: /* V9 stdfa */
-                    gen_op_check_align_T0_7();
-		    gen_op_stdfa(insn, 0, 0, 0); // XXX
-		    break;
-		case 0x3c: /* V9 casa */
-#ifdef CONFIG_USER_ONLY
+                    gen_op_load_fpr_FT0(rd);
+                    gen_stf_asi(insn, 4);
+                    break;
+                case 0x37: /* V9 stdfa */
                     gen_op_check_align_T0_3();
-#endif
-		    gen_op_casa(insn, 0, 4, 0); // XXX
-		    break;
-		case 0x3e: /* V9 casxa */
+                    gen_op_load_fpr_DT0(DFPREG(rd));
+                    gen_stf_asi(insn, 8);
+                    break;
+                case 0x3c: /* V9 casa */
+                    gen_op_check_align_T0_3();
+                    flush_T2(dc);
+                    gen_movl_reg_T2(rd);
+                    gen_cas_asi(insn);
+                    gen_movl_T1_reg(rd);
+                    break;
+                case 0x3e: /* V9 casxa */
                     gen_op_check_align_T0_7();
-		    gen_op_casxa(insn, 0, 8, 0); // XXX
-		    break;
-		case 0x36: /* V9 stqfa */
-		    goto nfpu_insn;
+                    flush_T2(dc);
+                    gen_movl_reg_T2(rd);
+                    gen_casx_asi(insn);
+                    gen_movl_T1_reg(rd);
+                    break;
+                case 0x36: /* V9 stqfa */
+                    goto nfpu_insn;
 #else
-		case 0x34: /* stc */
-		case 0x35: /* stcsr */
-		case 0x36: /* stdcq */
-		case 0x37: /* stdc */
-		    goto ncp_insn;
+                case 0x34: /* stc */
+                case 0x35: /* stcsr */
+                case 0x36: /* stdcq */
+                case 0x37: /* stdc */
+                    goto ncp_insn;
 #endif
-		default:
-		    goto illegal_insn;
-		}
+                default:
+                    goto illegal_insn;
+                }
             }
-	    else
-		goto illegal_insn;
-	}
-	break;
+            else
+                goto illegal_insn;
+        }
+        break;
     }
     /* default case for non jump instructions */
     if (dc->npc == DYNAMIC_PC) {
-	dc->pc = DYNAMIC_PC;
-	gen_op_next_insn();
+        dc->pc = DYNAMIC_PC;
+        gen_op_next_insn();
     } else if (dc->npc == JUMP_PC) {
         /* we can do a static jump */
         gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1]);
         dc->is_br = 1;
     } else {
-	dc->pc = dc->npc;
-	dc->npc = dc->npc + 4;
+        dc->pc = dc->npc;
+        dc->npc = dc->npc + 4;
     }
  jmp_insn:
     return;
@@ -3266,7 +3329,7 @@
 }
 
 static inline int gen_intermediate_code_internal(TranslationBlock * tb,
-						 int spc, CPUSPARCState *env)
+                                                 int spc, CPUSPARCState *env)
 {
     target_ulong pc_start, last_pc;
     uint16_t *gen_opc_end;
@@ -3279,17 +3342,8 @@
     dc->pc = pc_start;
     last_pc = dc->pc;
     dc->npc = (target_ulong) tb->cs_base;
-#if defined(CONFIG_USER_ONLY)
-    dc->mem_idx = 0;
-    dc->fpu_enabled = 1;
-#else
-    dc->mem_idx = ((env->psrs) != 0);
-#ifdef TARGET_SPARC64
-    dc->fpu_enabled = (((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0));
-#else
-    dc->fpu_enabled = ((env->psref) != 0);
-#endif
-#endif
+    dc->mem_idx = cpu_mmu_index(env);
+    dc->fpu_enabled = cpu_fpu_enabled(env);
     gen_opc_ptr = gen_opc_buf;
     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
     gen_opparam_ptr = gen_opparam_buf;
@@ -3299,12 +3353,12 @@
         if (env->nb_breakpoints > 0) {
             for(j = 0; j < env->nb_breakpoints; j++) {
                 if (env->breakpoints[j] == dc->pc) {
-		    if (dc->pc != pc_start)
-			save_state(dc);
+                    if (dc->pc != pc_start)
+                        save_state(dc);
                     gen_op_debug();
-		    gen_op_movl_T0_0();
-		    gen_op_exit_tb();
-		    dc->is_br = 1;
+                    gen_op_movl_T0_0();
+                    gen_op_exit_tb();
+                    dc->is_br = 1;
                     goto exit_gen_loop;
                 }
             }
@@ -3322,14 +3376,14 @@
                 gen_opc_instr_start[lj] = 1;
             }
         }
-	last_pc = dc->pc;
-	disas_sparc_insn(dc);
+        last_pc = dc->pc;
+        disas_sparc_insn(dc);
 
-	if (dc->is_br)
-	    break;
-	/* if the next PC is different, we abort now */
-	if (dc->pc != (last_pc + 4))
-	    break;
+        if (dc->is_br)
+            break;
+        /* if the next PC is different, we abort now */
+        if (dc->pc != (last_pc + 4))
+            break;
         /* if we reach a page boundary, we stop generation so that the
            PC of a TT_TFAULT exception is always in the right page */
         if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
@@ -3343,7 +3397,7 @@
             break;
         }
     } while ((gen_opc_ptr < gen_opc_end) &&
-	     (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
+             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
 
  exit_gen_loop:
     if (!dc->is_br) {
@@ -3377,10 +3431,10 @@
     }
 #ifdef DEBUG_DISAS
     if (loglevel & CPU_LOG_TB_IN_ASM) {
-	fprintf(logfile, "--------------\n");
-	fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
-	target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
-	fprintf(logfile, "\n");
+        fprintf(logfile, "--------------\n");
+        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
+        target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
+        fprintf(logfile, "\n");
         if (loglevel & CPU_LOG_TB_OP) {
             fprintf(logfile, "OP:\n");
             dump_ops(gen_opc_buf, gen_opparam_buf);
@@ -3423,10 +3477,12 @@
     env->psrps = 1;
 #ifdef TARGET_SPARC64
     env->pstate = PS_PRIV;
+    env->hpstate = HS_PRIV;
     env->pc = 0x1fff0000000ULL;
 #else
-    env->pc = 0xffd00000;
+    env->pc = 0;
     env->mmuregs[0] &= ~(MMU_E | MMU_NF);
+    env->mmuregs[0] |= MMU_BM;
 #endif
     env->npc = env->pc + 4;
 #endif
@@ -3438,7 +3494,7 @@
 
     env = qemu_mallocz(sizeof(CPUSPARCState));
     if (!env)
-	return NULL;
+        return NULL;
     cpu_exec_init(env);
     cpu_reset(env);
     return (env);
@@ -3518,12 +3574,13 @@
     }
 }
 
-int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def)
+int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def, unsigned int cpu)
 {
     env->version = def->iu_version;
     env->fsr = def->fpu_version;
 #if !defined(TARGET_SPARC64)
-    env->mmuregs[0] = def->mmu_version;
+    env->mmuregs[0] |= def->mmu_version;
+    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
 #endif
     return 0;
 }
@@ -3539,22 +3596,22 @@
     cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc, env->npc);
     cpu_fprintf(f, "General Registers:\n");
     for (i = 0; i < 4; i++)
-	cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
+        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
     cpu_fprintf(f, "\n");
     for (; i < 8; i++)
-	cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
+        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
     cpu_fprintf(f, "\nCurrent Register Window:\n");
     for (x = 0; x < 3; x++) {
-	for (i = 0; i < 4; i++)
-	    cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
-		    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
-		    env->regwptr[i + x * 8]);
-	cpu_fprintf(f, "\n");
-	for (; i < 8; i++)
-	    cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
-		    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
-		    env->regwptr[i + x * 8]);
-	cpu_fprintf(f, "\n");
+        for (i = 0; i < 4; i++)
+            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
+                    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
+                    env->regwptr[i + x * 8]);
+        cpu_fprintf(f, "\n");
+        for (; i < 8; i++)
+            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
+                    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
+                    env->regwptr[i + x * 8]);
+        cpu_fprintf(f, "\n");
     }
     cpu_fprintf(f, "\nFloating Point Registers:\n");
     for (i = 0; i < 32; i++) {
@@ -3566,16 +3623,16 @@
     }
 #ifdef TARGET_SPARC64
     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);
+                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);
+                env->cansave, env->canrestore, env->otherwin, env->wstate,
+                env->cleanwin, NWINDOWS - 1 - env->cwp);
 #else
     cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
-	    GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
-	    GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
-	    env->psrs?'S':'-', env->psrps?'P':'-',
-	    env->psret?'E':'-', env->wim);
+            GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
+            GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
+            env->psrs?'S':'-', env->psrps?'P':'-',
+            env->psret?'E':'-', env->wim);
 #endif
     cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
 }
@@ -3589,7 +3646,7 @@
 #else
 extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
                                  int *access_index, target_ulong address, int rw,
-                                 int is_user);
+                                 int mmu_idx);
 
 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {

Modified: trunk/src/host/qemu-neo1973/tests/Makefile
===================================================================
--- trunk/src/host/qemu-neo1973/tests/Makefile	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/tests/Makefile	2007-10-29 21:14:04 UTC (rev 3303)
@@ -98,6 +98,11 @@
            ../$${arch}-linux-user/qemu-$${arch} $${arch}/ls -l linux-test.c ; \
         done
 
+
+# testsuite for the CRIS port.
+test-cris:
+	$(MAKE) -C cris check
+
 clean:
 	rm -f *~ *.o test-i386.out test-i386.ref \
            test-x86_64.log test-x86_64.ref qruncom $(TESTS)

Modified: trunk/src/host/qemu-neo1973/thunk.c
===================================================================
--- trunk/src/host/qemu-neo1973/thunk.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/thunk.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -136,13 +136,13 @@
     case TYPE_ULONGLONG:
         *(uint64_t *)dst = tswap64(*(uint64_t *)src);
         break;
-#if HOST_LONG_BITS == 32 && TARGET_LONG_BITS == 32
+#if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32
     case TYPE_LONG:
     case TYPE_ULONG:
     case TYPE_PTRVOID:
         *(uint32_t *)dst = tswap32(*(uint32_t *)src);
         break;
-#elif HOST_LONG_BITS == 64 && TARGET_LONG_BITS == 32
+#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
     case TYPE_LONG:
     case TYPE_ULONG:
     case TYPE_PTRVOID:

Modified: trunk/src/host/qemu-neo1973/thunk.h
===================================================================
--- trunk/src/host/qemu-neo1973/thunk.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/thunk.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -98,7 +98,7 @@
         if (is_host) {
             return HOST_LONG_SIZE;
         } else {
-            return TARGET_LONG_SIZE;
+            return TARGET_ABI_BITS / 8;
         }
         break;
     case TYPE_ARRAY:
@@ -135,7 +135,7 @@
         if (is_host) {
             return HOST_LONG_SIZE;
         } else {
-            return TARGET_LONG_SIZE;
+            return TARGET_ABI_BITS / 8;
         }
         break;
     case TYPE_ARRAY:

Modified: trunk/src/host/qemu-neo1973/usb-linux.c
===================================================================
--- trunk/src/host/qemu-neo1973/usb-linux.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/usb-linux.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -28,6 +28,7 @@
 #include <sys/ioctl.h>
 #include <linux/usbdevice_fs.h>
 #include <linux/version.h>
+#include <signal.h>
 
 /* We redefine it to avoid version problems */
 struct usb_ctrltransfer {
@@ -48,15 +49,174 @@
                                 const char *devname);
 
 //#define DEBUG
+//#define DEBUG_ISOCH
+//#define USE_ASYNCIO
 
 #define USBDEVFS_PATH "/proc/bus/usb"
 #define PRODUCT_NAME_SZ 32
+#define SIG_ISOCOMPLETE (SIGRTMIN+7)
+#define MAX_ENDPOINTS 16
 
+struct sigaction sigact;
+
+/* endpoint association data */
+struct endp_data {
+    uint8_t type;
+};
+
+/* FIXME: move USBPacket to PendingURB */
 typedef struct USBHostDevice {
     USBDevice dev;
     int fd;
+    USBPacket *packet;
+    struct endp_data endp_table[MAX_ENDPOINTS];
+    int configuration;
+    uint8_t descr[1024];
+    int descr_len;
+    int urbs_ready;
 } USBHostDevice;
 
+typedef struct PendingURB {
+    struct usbdevfs_urb *urb;
+    USBHostDevice *dev;
+    QEMUBH *bh;
+    int status;
+    struct PendingURB *next;
+} PendingURB;
+
+static PendingURB *pending_urbs = NULL;
+
+static int add_pending_urb(struct usbdevfs_urb *urb)
+{
+    PendingURB *purb = qemu_mallocz(sizeof(PendingURB));
+    if (purb) {
+        purb->urb = urb;
+        purb->dev = NULL;
+        purb->bh = NULL;
+        purb->status = 0;
+        purb->next = pending_urbs;
+        pending_urbs = purb;
+        return 1;
+    }
+    return 0;
+}
+
+static int del_pending_urb(struct usbdevfs_urb *urb)
+{
+    PendingURB *purb = pending_urbs;
+    PendingURB *prev = NULL;
+
+    while (purb && purb->urb != urb) {
+        prev = purb;
+        purb = purb->next;
+    }
+
+    if (purb && purb->urb == urb) {
+        if (prev) {
+            prev->next = purb->next;
+        } else {
+            pending_urbs = purb->next;
+        }
+        qemu_free(purb);
+        return 1;
+    }
+    return 0;
+}
+
+#ifdef USE_ASYNCIO
+static PendingURB *get_pending_urb(struct usbdevfs_urb *urb)
+{
+    PendingURB *purb = pending_urbs;
+
+    while (purb && purb->urb != urb) {
+        purb = purb->next;
+    }
+
+    if (purb && purb->urb == urb) {
+        return purb;
+    }
+    return NULL;
+}
+#endif
+
+static int usb_host_update_interfaces(USBHostDevice *dev, int configuration)
+{
+    int dev_descr_len, config_descr_len;
+    int interface, nb_interfaces, nb_configurations;
+    int ret, i;
+
+    if (configuration == 0) /* address state - ignore */
+        return 1;
+
+    i = 0;
+    dev_descr_len = dev->descr[0];
+    if (dev_descr_len > dev->descr_len)
+        goto fail;
+    nb_configurations = dev->descr[17];
+
+    i += dev_descr_len;
+    while (i < dev->descr_len) {
+#ifdef DEBUG
+        printf("i is %d, descr_len is %d, dl %d, dt %d\n", i, dev->descr_len,
+               dev->descr[i], dev->descr[i+1]);
+#endif
+        if (dev->descr[i+1] != USB_DT_CONFIG) {
+            i += dev->descr[i];
+            continue;
+        }
+        config_descr_len = dev->descr[i];
+
+        if (configuration == dev->descr[i + 5])
+            break;
+
+        i += config_descr_len;
+    }
+
+    if (i >= dev->descr_len) {
+        printf("usb_host: error - device has no matching configuration\n");
+        goto fail;
+    }
+    nb_interfaces = dev->descr[i + 4];
+
+#ifdef USBDEVFS_DISCONNECT
+    /* earlier Linux 2.4 do not support that */
+    {
+        struct usbdevfs_ioctl ctrl;
+        for (interface = 0; interface < nb_interfaces; interface++) {
+            ctrl.ioctl_code = USBDEVFS_DISCONNECT;
+            ctrl.ifno = interface;
+            ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
+            if (ret < 0 && errno != ENODATA) {
+                perror("USBDEVFS_DISCONNECT");
+                goto fail;
+            }
+        }
+    }
+#endif
+
+    /* XXX: only grab if all interfaces are free */
+    for (interface = 0; interface < nb_interfaces; interface++) {
+        ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface);
+        if (ret < 0) {
+            if (errno == EBUSY) {
+                fprintf(stderr,
+                        "usb_host: warning - device already grabbed\n");
+            } else {
+                perror("USBDEVFS_CLAIMINTERFACE");
+            }
+        fail:
+            return 0;
+        }
+    }
+
+#ifdef DEBUG
+    printf("usb_host: %d interfaces claimed for configuration %d\n",
+           nb_interfaces, configuration);
+#endif
+
+    return 1;
+}
+
 static void usb_host_handle_reset(USBDevice *dev)
 {
 #if 0
@@ -76,6 +236,8 @@
     qemu_free(s);
 }
 
+static int usb_linux_update_endp_table(USBHostDevice *s);
+
 static int usb_host_handle_control(USBDevice *dev,
                                    int request,
                                    int value,
@@ -85,13 +247,33 @@
 {
     USBHostDevice *s = (USBHostDevice *)dev;
     struct usb_ctrltransfer ct;
+    struct usbdevfs_setinterface si;
+    int intf_update_required = 0;
     int ret;
 
     if (request == (DeviceOutRequest | USB_REQ_SET_ADDRESS)) {
         /* specific SET_ADDRESS support */
         dev->addr = value;
         return 0;
+    } else if (request == ((USB_RECIP_INTERFACE << 8) |
+                           USB_REQ_SET_INTERFACE)) {
+        /* set alternate setting for the interface */
+        si.interface = index;
+        si.altsetting = value;
+        ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
+        usb_linux_update_endp_table(s);
+    } else if (request == (DeviceOutRequest | USB_REQ_SET_CONFIGURATION)) {
+#ifdef DEBUG
+        printf("usb_host_handle_control: SET_CONFIGURATION request - "
+               "config %d\n", value & 0xff);
+#endif
+        if (s->configuration != (value & 0xff)) {
+            s->configuration = (value & 0xff);
+            intf_update_required = 1;
+        }
+        goto do_request;
     } else {
+    do_request:
         ct.bRequestType = request >> 8;
         ct.bRequest = request;
         ct.wValue = value;
@@ -100,19 +282,28 @@
         ct.timeout = 50;
         ct.data = data;
         ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
-        if (ret < 0) {
-            switch(errno) {
-            case ETIMEDOUT:
-                return USB_RET_NAK;
-            default:
-                return USB_RET_STALL;
-            }
-        } else {
-            return ret;
+    }
+
+    if (ret < 0) {
+        switch(errno) {
+        case ETIMEDOUT:
+            return USB_RET_NAK;
+        default:
+            return USB_RET_STALL;
         }
-   }
+    } else {
+        if (intf_update_required) {
+#ifdef DEBUG
+            printf("usb_host_handle_control: updating interfaces\n");
+#endif
+            usb_host_update_interfaces(s, value & 0xff);
+        }
+        return ret;
+    }
 }
 
+static int usb_host_handle_isoch(USBDevice *dev, USBPacket *p);
+
 static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBHostDevice *s = (USBHostDevice *)dev;
@@ -120,6 +311,10 @@
     int ret;
     uint8_t devep = p->devep;
 
+    if (s->endp_table[p->devep - 1].type == USBDEVFS_URB_TYPE_ISO) {
+        return usb_host_handle_isoch(dev, p);
+    }
+
     /* XXX: optimize and handle all data types by looking at the
        config descriptor */
     if (p->pid == USB_TOKEN_IN)
@@ -145,18 +340,277 @@
     }
 }
 
+#ifdef USE_ASYNCIO
+static void usb_linux_bh_cb(void *opaque)
+{
+    PendingURB *pending_urb = (PendingURB *)opaque;
+    USBHostDevice *s = pending_urb->dev;
+    struct usbdevfs_urb *purb = NULL;
+    USBPacket *p = s->packet;
+    int ret;
+
+    /* FIXME: handle purb->status */
+    qemu_free(pending_urb->bh);
+    del_pending_urb(pending_urb->urb);
+
+    if (!p) {
+        s->urbs_ready++;
+        return;
+    }
+
+    ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
+    if (ret < 0) {
+        printf("usb_linux_bh_cb: REAPURBNDELAY ioctl=%d errno=%d\n",
+               ret, errno);
+        return;
+    }
+
+#ifdef DEBUG_ISOCH
+    if (purb == pending_urb->urb) {
+        printf("usb_linux_bh_cb: urb mismatch reaped=%p pending=%p\n",
+               purb, urb);
+    }
+#endif
+
+    p->len = purb->actual_length;
+    usb_packet_complete(p);
+    qemu_free(purb);
+    s->packet = NULL;
+}
+
+static void isoch_done(int signum, siginfo_t *info, void *context)
+{
+    struct usbdevfs_urb *urb = (struct usbdevfs_urb *)info->si_addr;
+    USBHostDevice *s = (USBHostDevice *)urb->usercontext;
+    PendingURB *purb;
+
+    if (info->si_code != SI_ASYNCIO ||
+        info->si_signo != SIG_ISOCOMPLETE) {
+        return;
+    }
+
+    purb = get_pending_urb(urb);
+    if (purb) {
+        purb->bh = qemu_bh_new(usb_linux_bh_cb, purb);
+        if (purb->bh) {
+            purb->dev = s;
+            purb->status = info->si_errno;
+            qemu_bh_schedule(purb->bh);
+        }
+    }
+}
+#endif
+
+static int usb_host_handle_isoch(USBDevice *dev, USBPacket *p)
+{
+    USBHostDevice *s = (USBHostDevice *)dev;
+    struct usbdevfs_urb *urb, *purb = NULL;
+    int ret;
+    uint8_t devep = p->devep;
+
+    if (p->pid == USB_TOKEN_IN)
+        devep |= 0x80;
+
+    urb = qemu_mallocz(sizeof(struct usbdevfs_urb) +
+                       sizeof(struct usbdevfs_iso_packet_desc));
+    if (!urb) {
+        printf("usb_host_handle_isoch: malloc failed\n");
+        return 0;
+    }
+
+    urb->type = USBDEVFS_URB_TYPE_ISO;
+    urb->endpoint = devep;
+    urb->status = 0;
+    urb->flags = USBDEVFS_URB_ISO_ASAP;
+    urb->buffer = p->data;
+    urb->buffer_length = p->len;
+    urb->actual_length = 0;
+    urb->start_frame = 0;
+    urb->error_count = 0;
+#ifdef USE_ASYNCIO
+    urb->signr = SIG_ISOCOMPLETE;
+#else
+    urb->signr = 0;
+#endif
+    urb->usercontext = s;
+    urb->number_of_packets = 1;
+    urb->iso_frame_desc[0].length = p->len;
+    urb->iso_frame_desc[0].actual_length = 0;
+    urb->iso_frame_desc[0].status = 0;
+    ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
+    if (ret == 0) {
+        if (!add_pending_urb(urb)) {
+            printf("usb_host_handle_isoch: add_pending_urb failed %p\n", urb);
+        }
+    } else {
+        printf("usb_host_handle_isoch: SUBMITURB ioctl=%d errno=%d\n",
+               ret, errno);
+        qemu_free(urb);
+        switch(errno) {
+        case ETIMEDOUT:
+            return USB_RET_NAK;
+        case EPIPE:
+        default:
+            return USB_RET_STALL;
+        }
+    }
+#ifdef USE_ASYNCIO
+    /* FIXME: handle urbs_ready together with sync io
+     * workaround for injecting the signaled urbs into current frame */
+    if (s->urbs_ready > 0) {
+        ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
+        if (ret == 0) {
+            ret = purb->actual_length;
+            qemu_free(purb);
+            s->urbs_ready--;
+        }
+        return ret;
+    }
+    s->packet = p;
+    return USB_RET_ASYNC;
+#else
+    ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
+    if (ret == 0) {
+        if (del_pending_urb(purb)) {
+            ret = purb->actual_length;
+            qemu_free(purb);
+        } else {
+            printf("usb_host_handle_isoch: del_pending_urb failed %p\n", purb);
+        }
+    } else {
+#ifdef DEBUG_ISOCH
+        printf("usb_host_handle_isoch: REAPURBNDELAY ioctl=%d errno=%d\n",
+               ret, errno);
+#endif
+    }
+    return ret;
+#endif
+}
+
+/* returns 1 on problem encountered or 0 for success */
+static int usb_linux_update_endp_table(USBHostDevice *s)
+{
+    uint8_t *descriptors;
+    uint8_t devep, type, configuration, alt_interface;
+    struct usb_ctrltransfer ct;
+    int interface, ret, length, i;
+
+    ct.bRequestType = USB_DIR_IN;
+    ct.bRequest = USB_REQ_GET_CONFIGURATION;
+    ct.wValue = 0;
+    ct.wIndex = 0;
+    ct.wLength = 1;
+    ct.data = &configuration;
+    ct.timeout = 50;
+
+    ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
+    if (ret < 0) {
+        perror("usb_linux_update_endp_table");
+        return 1;
+    }
+
+    /* in address state */
+    if (configuration == 0)
+        return 1;
+
+    /* get the desired configuration, interface, and endpoint descriptors
+     * from device description */
+    descriptors = &s->descr[18];
+    length = s->descr_len - 18;
+    i = 0;
+
+    if (descriptors[i + 1] != USB_DT_CONFIG ||
+        descriptors[i + 5] != configuration) {
+        printf("invalid descriptor data - configuration\n");
+        return 1;
+    }
+    i += descriptors[i];
+
+    while (i < length) {
+        if (descriptors[i + 1] != USB_DT_INTERFACE ||
+            (descriptors[i + 1] == USB_DT_INTERFACE &&
+             descriptors[i + 4] == 0)) {
+            i += descriptors[i];
+            continue;
+        }
+
+        interface = descriptors[i + 2];
+
+        ct.bRequestType = USB_DIR_IN | USB_RECIP_INTERFACE;
+        ct.bRequest = USB_REQ_GET_INTERFACE;
+        ct.wValue = 0;
+        ct.wIndex = interface;
+        ct.wLength = 1;
+        ct.data = &alt_interface;
+        ct.timeout = 50;
+
+        ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
+        if (ret < 0) {
+            perror("usb_linux_update_endp_table");
+            return 1;
+        }
+
+        /* the current interface descriptor is the active interface
+         * and has endpoints */
+        if (descriptors[i + 3] != alt_interface) {
+            i += descriptors[i];
+            continue;
+        }
+
+        /* advance to the endpoints */
+        while (i < length && descriptors[i +1] != USB_DT_ENDPOINT)
+            i += descriptors[i];
+
+        if (i >= length)
+            break;
+
+        while (i < length) {
+            if (descriptors[i + 1] != USB_DT_ENDPOINT)
+                break;
+
+            devep = descriptors[i + 2];
+            switch (descriptors[i + 3] & 0x3) {
+            case 0x00:
+                type = USBDEVFS_URB_TYPE_CONTROL;
+                break;
+            case 0x01:
+                type = USBDEVFS_URB_TYPE_ISO;
+                break;
+            case 0x02:
+                type = USBDEVFS_URB_TYPE_BULK;
+                break;
+            case 0x03:
+                type = USBDEVFS_URB_TYPE_INTERRUPT;
+                break;
+            default:
+                printf("usb_host: malformed endpoint type\n");
+                type = USBDEVFS_URB_TYPE_BULK;
+            }
+            s->endp_table[(devep & 0xf) - 1].type = type;
+
+            i += descriptors[i];
+        }
+    }
+    return 0;
+}
+
 /* XXX: exclude high speed devices or implement EHCI */
 USBDevice *usb_host_device_open(const char *devname)
 {
-    int fd, interface, ret, i;
-    USBHostDevice *dev;
+    int fd = -1, ret;
+    USBHostDevice *dev = NULL;
     struct usbdevfs_connectinfo ci;
-    uint8_t descr[1024];
     char buf[1024];
-    int descr_len, dev_descr_len, config_descr_len, nb_interfaces;
     int bus_num, addr;
     char product_name[PRODUCT_NAME_SZ];
 
+    dev = qemu_mallocz(sizeof(USBHostDevice));
+    if (!dev)
+        goto fail;
+
+#ifdef DEBUG_ISOCH
+    printf("usb_host_device_open %s\n", devname);
+#endif
     if (usb_host_find_device(&bus_num, &addr,
                              product_name, sizeof(product_name),
                              devname) < 0)
@@ -164,62 +618,36 @@
 
     snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d",
              bus_num, addr);
-    fd = open(buf, O_RDWR);
+    fd = open(buf, O_RDWR | O_NONBLOCK);
     if (fd < 0) {
         perror(buf);
         return NULL;
     }
 
-    /* read the config description */
-    descr_len = read(fd, descr, sizeof(descr));
-    if (descr_len <= 0) {
-        perror("read descr");
+    /* read the device description */
+    dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
+    if (dev->descr_len <= 0) {
+        perror("usb_host_update_interfaces: reading device data failed");
         goto fail;
     }
 
-    i = 0;
-    dev_descr_len = descr[0];
-    if (dev_descr_len > descr_len)
-        goto fail;
-    i += dev_descr_len;
-    config_descr_len = descr[i];
-    if (i + config_descr_len > descr_len)
-        goto fail;
-    nb_interfaces = descr[i + 4];
-    if (nb_interfaces != 1) {
-        /* NOTE: currently we grab only one interface */
-        fprintf(stderr, "usb_host: only one interface supported\n");
-        goto fail;
-    }
-
-#ifdef USBDEVFS_DISCONNECT
-    /* earlier Linux 2.4 do not support that */
+#ifdef DEBUG
     {
-        struct usbdevfs_ioctl ctrl;
-        ctrl.ioctl_code = USBDEVFS_DISCONNECT;
-        ctrl.ifno = 0;
-        ret = ioctl(fd, USBDEVFS_IOCTL, &ctrl);
-        if (ret < 0 && errno != ENODATA) {
-            perror("USBDEVFS_DISCONNECT");
-            goto fail;
-        }
+        int x;
+        printf("=== begin dumping device descriptor data ===\n");
+        for (x = 0; x < dev->descr_len; x++)
+            printf("%02x ", dev->descr[x]);
+        printf("\n=== end dumping device descriptor data ===\n");
     }
 #endif
 
-    /* XXX: only grab if all interfaces are free */
-    interface = 0;
-    ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface);
-    if (ret < 0) {
-        if (errno == EBUSY) {
-            fprintf(stderr, "usb_host: device already grabbed\n");
-        } else {
-            perror("USBDEVFS_CLAIMINTERFACE");
-        }
-    fail:
-        close(fd);
-        return NULL;
-    }
+    dev->fd = fd;
+    dev->configuration = 1;
 
+    /* XXX - do something about initial configuration */
+    if (!usb_host_update_interfaces(dev, 1))
+        goto fail;
+
     ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
     if (ret < 0) {
         perror("USBDEVFS_CONNECTINFO");
@@ -230,10 +658,10 @@
     printf("host USB device %d.%d grabbed\n", bus_num, addr);
 #endif
 
-    dev = qemu_mallocz(sizeof(USBHostDevice));
-    if (!dev)
+    ret = usb_linux_update_endp_table(dev);
+    if (ret)
         goto fail;
-    dev->fd = fd;
+
     if (ci.slow)
         dev->dev.speed = USB_SPEED_LOW;
     else
@@ -252,7 +680,24 @@
         pstrcpy(dev->dev.devname, sizeof(dev->dev.devname),
                 product_name);
 
+#ifdef USE_ASYNCIO
+    /* set up the signal handlers */
+    sigemptyset(&sigact.sa_mask);
+    sigact.sa_sigaction = isoch_done;
+    sigact.sa_flags = SA_SIGINFO;
+    sigact.sa_restorer = 0;
+    ret = sigaction(SIG_ISOCOMPLETE, &sigact, NULL);
+    if (ret < 0) {
+        printf("sigaction SIG_ISOCOMPLETE=%d errno=%d\n", ret, errno);
+    }
+#endif
+    dev->urbs_ready = 0;
     return (USBDevice *)dev;
+fail:
+    if (dev)
+        qemu_free(dev);
+    close(fd);
+    return NULL;
 }
 
 static int get_tag_value(char *buf, int buf_size,
@@ -438,7 +883,7 @@
     { USB_CLASS_APP_SPEC, "Application Specific" },
     { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
     { USB_CLASS_STILL_IMAGE, "Still Image" },
-    { USB_CLASS_CSCID, 	"Smart Card" },
+    { USB_CLASS_CSCID, "Smart Card" },
     { USB_CLASS_CONTENT_SEC, "Content Security" },
     { -1, NULL }
 };

Modified: trunk/src/host/qemu-neo1973/vl.c
===================================================================
--- trunk/src/host/qemu-neo1973/vl.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/vl.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -117,6 +117,7 @@
 #include "exec-all.h"
 
 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
+#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
 #ifdef __sun__
 #define SMBD_COMMAND "/usr/sfw/sbin/smbd"
 #else
@@ -143,6 +144,7 @@
 #define MAX_IOPORTS 65536
 
 const char *bios_dir = CONFIG_QEMU_SHAREDIR;
+const char *bios_name = NULL;
 char phys_ram_file[1024];
 void *ioport_opaque[MAX_IOPORTS];
 IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
@@ -990,8 +992,6 @@
         }
         pt = &t->next;
     }
-
-    qemu_rearm_alarm_timer(alarm_timer);
 }
 
 /* modify the current timer so that it will be fired when current_time
@@ -1183,7 +1183,7 @@
 
 static uint64_t qemu_next_deadline(void)
 {
-    int64_t nearest_delta_us = UINT64_MAX;
+    int64_t nearest_delta_us = INT64_MAX;
     int64_t vmdelta_us;
 
     if (active_timers[QEMU_TIMER_REALTIME])
@@ -3784,6 +3784,10 @@
 }
 
 #endif /* !defined(_WIN32) */
+void do_info_slirp(void)
+{
+    slirp_stats();
+}
 
 #endif /* CONFIG_SLIRP */
 
@@ -3792,6 +3796,7 @@
 typedef struct TAPState {
     VLANClientState *vc;
     int fd;
+    char down_script[1024];
 } TAPState;
 
 static void tap_receive(void *opaque, const uint8_t *buf, int size)
@@ -4027,27 +4032,13 @@
 }
 #endif
 
-static int net_tap_init(VLANState *vlan, const char *ifname1,
-                        const char *setup_script)
+static int launch_script(const char *setup_script, const char *ifname, int fd)
 {
-    TAPState *s;
-    int pid, status, fd;
+    int pid, status;
     char *args[3];
     char **parg;
-    char ifname[128];
 
-    if (ifname1 != NULL)
-        pstrcpy(ifname, sizeof(ifname), ifname1);
-    else
-        ifname[0] = '\0';
-    TFR(fd = tap_open(ifname, sizeof(ifname)));
-    if (fd < 0)
-        return -1;
-
-    if (!setup_script || !strcmp(setup_script, "no"))
-        setup_script = "";
-    if (setup_script[0] != '\0') {
-        /* try to launch network init script */
+        /* try to launch network script */
         pid = fork();
         if (pid >= 0) {
             if (pid == 0) {
@@ -4061,7 +4052,7 @@
 
                 parg = args;
                 *parg++ = (char *)setup_script;
-                *parg++ = ifname;
+                *parg++ = (char *)ifname;
                 *parg++ = NULL;
                 execv(setup_script, args);
                 _exit(1);
@@ -4074,12 +4065,37 @@
                 return -1;
             }
         }
+    return 0;
+}
+
+static int net_tap_init(VLANState *vlan, const char *ifname1,
+                        const char *setup_script, const char *down_script)
+{
+    TAPState *s;
+    int fd;
+    char ifname[128];
+
+    if (ifname1 != NULL)
+        pstrcpy(ifname, sizeof(ifname), ifname1);
+    else
+        ifname[0] = '\0';
+    TFR(fd = tap_open(ifname, sizeof(ifname)));
+    if (fd < 0)
+        return -1;
+
+    if (!setup_script || !strcmp(setup_script, "no"))
+        setup_script = "";
+    if (setup_script[0] != '\0') {
+	if (launch_script(setup_script, ifname, fd))
+	    return -1;
     }
     s = net_tap_fd_init(vlan, fd);
     if (!s)
         return -1;
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "tap: ifname=%s setup_script=%s", ifname, setup_script);
+    if (down_script && strcmp(down_script, "no"))
+        snprintf(s->down_script, sizeof(s->down_script), "%s", down_script);
     return 0;
 }
 
@@ -4623,7 +4639,7 @@
 #else
     if (!strcmp(device, "tap")) {
         char ifname[64];
-        char setup_script[1024];
+        char setup_script[1024], down_script[1024];
         int fd;
         vlan->nb_host_devs++;
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
@@ -4638,7 +4654,10 @@
             if (get_param_value(setup_script, sizeof(setup_script), "script", p) == 0) {
                 pstrcpy(setup_script, sizeof(setup_script), DEFAULT_NETWORK_SCRIPT);
             }
-            ret = net_tap_init(vlan, ifname, setup_script);
+            if (get_param_value(down_script, sizeof(down_script), "downscript", p) == 0) {
+                pstrcpy(down_script, sizeof(down_script), DEFAULT_NETWORK_DOWN_SCRIPT);
+            }
+            ret = net_tap_init(vlan, ifname, setup_script, down_script);
         }
     } else
 #endif
@@ -7241,10 +7260,11 @@
            "-net tap[,vlan=n],ifname=name\n"
            "                connect the host TAP network interface to VLAN 'n'\n"
 #else
-           "-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"
+           "-net tap[,vlan=n][,fd=h][,ifname=name][,script=file][,downscript=dfile]\n"
+           "                connect the host TAP network interface to VLAN 'n' and use the\n"
+           "                network scripts 'file' (default=%s)\n"
+           "                and 'dfile' (default=%s);\n"
+           "                use '[down]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"
@@ -7317,6 +7337,7 @@
            DEFAULT_RAM_SIZE,
 #ifndef _WIN32
            DEFAULT_NETWORK_SCRIPT,
+           DEFAULT_NETWORK_DOWN_SCRIPT,
 #endif
            DEFAULT_GDBSTUB_PORT,
            "/tmp/qemu.log");
@@ -7369,6 +7390,7 @@
     QEMU_OPTION_d,
     QEMU_OPTION_hdachs,
     QEMU_OPTION_L,
+    QEMU_OPTION_bios,
     QEMU_OPTION_no_code_copy,
     QEMU_OPTION_k,
     QEMU_OPTION_localtime,
@@ -7462,6 +7484,7 @@
     { "d", HAS_ARG, QEMU_OPTION_d },
     { "hdachs", HAS_ARG, QEMU_OPTION_hdachs },
     { "L", HAS_ARG, QEMU_OPTION_L },
+    { "bios", HAS_ARG, QEMU_OPTION_bios },
     { "no-code-copy", 0, QEMU_OPTION_no_code_copy },
 #ifdef USE_KQEMU
     { "no-kqemu", 0, QEMU_OPTION_no_kqemu },
@@ -7584,6 +7607,7 @@
     qemu_register_machine(&mips_machine);
     qemu_register_machine(&mips_malta_machine);
     qemu_register_machine(&mips_pica61_machine);
+    qemu_register_machine(&mips_mipssim_machine);
 #elif defined(TARGET_SPARC)
 #ifdef TARGET_SPARC64
     qemu_register_machine(&sun4u_machine);
@@ -7604,11 +7628,14 @@
     qemu_register_machine(&palmte_machine);
 #elif defined(TARGET_SH4)
     qemu_register_machine(&shix_machine);
+    qemu_register_machine(&r2d_machine);
 #elif defined(TARGET_ALPHA)
     /* XXX: TODO */
 #elif defined(TARGET_M68K)
     qemu_register_machine(&mcf5208evb_machine);
     qemu_register_machine(&an5206_machine);
+#elif defined(TARGET_CRIS)
+    qemu_register_machine(&bareetraxfs_machine);
 #else
 #error unsupported CPU
 #endif
@@ -7908,14 +7935,9 @@
             case QEMU_OPTION_cpu:
                 /* hw initialization will check this */
                 if (*optarg == '?') {
-#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);
+/* XXX: implement xxx_cpu_list for targets that still miss it */
+#if defined(cpu_list)
+                    cpu_list(stdout, &fprintf);
 #endif
                     exit(0);
                 } else {
@@ -8110,6 +8132,9 @@
             case QEMU_OPTION_L:
                 bios_dir = optarg;
                 break;
+            case QEMU_OPTION_bios:
+                bios_name = optarg;
+                break;
             case QEMU_OPTION_S:
                 autostart = 0;
                 break;
@@ -8700,5 +8725,23 @@
 
     main_loop();
     quit_timers();
+
+#if !defined(_WIN32)
+    /* close network clients */
+    for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
+        VLANClientState *vc;
+
+        for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
+            if (vc->fd_read == tap_receive) {
+                char ifname[64];
+                TAPState *s = vc->opaque;
+
+                if (sscanf(vc->info_str, "tap: ifname=%63s ", ifname) == 1 &&
+                    s->down_script[0])
+                    launch_script(s->down_script, ifname, s->fd);
+            }
+    }
+    }
+#endif
     return 0;
 }

Modified: trunk/src/host/qemu-neo1973/vl.h
===================================================================
--- trunk/src/host/qemu-neo1973/vl.h	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/vl.h	2007-10-29 21:14:04 UTC (rev 3303)
@@ -109,6 +109,14 @@
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
 #endif
 
+#ifndef always_inline
+#if (__GNUC__ < 3) || defined(__APPLE__)
+#define always_inline inline
+#else
+#define always_inline __attribute__ (( always_inline )) inline
+#endif
+#endif
+
 /* cutils.c */
 void pstrcpy(char *buf, int buf_size, const char *str);
 char *pstrcat(char *buf, int buf_size, const char *s);
@@ -121,6 +129,7 @@
 void hw_error(const char *fmt, ...);
 
 extern const char *bios_dir;
+extern const char *bios_name;
 
 extern int vm_running;
 extern const char *qemu_name;
@@ -188,7 +197,9 @@
 
 /* XXX: make it dynamic */
 #define MAX_BIOS_SIZE (4 * 1024 * 1024)
-#if defined (TARGET_PPC) || defined (TARGET_SPARC64)
+#if defined (TARGET_PPC)
+#define BIOS_SIZE (1024 * 1024)
+#elif defined (TARGET_SPARC64)
 #define BIOS_SIZE ((512 + 32) * 1024)
 #elif defined(TARGET_MIPS)
 #define BIOS_SIZE (4 * 1024 * 1024)
@@ -432,6 +443,9 @@
 extern int nb_nics;
 extern NICInfo nd_table[MAX_NICS];
 
+/* SLIRP */
+void do_info_slirp(void);
+
 /* timers */
 
 typedef struct QEMUClock QEMUClock;
@@ -734,14 +748,6 @@
 
 typedef void SetIRQFunc(void *opaque, int irq_num, 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 */
@@ -857,12 +863,6 @@
 /* prep_pci.c */
 PCIBus *pci_prep_init(qemu_irq *pic);
 
-/* grackle_pci.c */
-PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic);
-
-/* unin_pci.c */
-PCIBus *pci_pmac_init(qemu_irq *pic);
-
 /* apb_pci.c */
 PCIBus *pci_apb_init(target_phys_addr_t special_base, target_phys_addr_t mem_base,
                      qemu_irq *pic);
@@ -890,9 +890,6 @@
 qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
                         qemu_irq **irqs, qemu_irq irq_out);
 
-/* heathrow_pic.c */
-qemu_irq *heathrow_pic_init(int *pmem_index);
-
 /* gt64xxx.c */
 PCIBus *pci_gt64120_init(qemu_irq *pic);
 
@@ -1002,7 +999,6 @@
                         qemu_irq *pic);
 void pci_piix4_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);
@@ -1069,6 +1065,9 @@
 void lance_init(NICInfo *nd, target_phys_addr_t leaddr, void *dma_opaque,
                 qemu_irq irq, qemu_irq *reset);
 
+/* mipsnet.c */
+void mipsnet_init(int base, qemu_irq irq, NICInfo *nd);
+
 /* vmmouse.c */
 void *vmmouse_init(void *m);
 
@@ -1132,6 +1131,7 @@
 typedef struct IOAPICState IOAPICState;
 
 int apic_init(CPUState *env);
+int apic_accept_pic_intr(CPUState *env);
 int apic_get_interrupt(CPUState *env);
 IOAPICState *ioapic_init(void);
 void ioapic_set_irq(void *opaque, int vector, int level);
@@ -1173,6 +1173,9 @@
 void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
 void acpi_bios_init(void);
 
+/* Axis ETRAX.  */
+extern QEMUMachine bareetraxfs_machine;
+
 /* pc.c */
 extern QEMUMachine pc_machine;
 extern QEMUMachine isapc_machine;
@@ -1194,12 +1197,15 @@
 /* mips_malta.c */
 extern QEMUMachine mips_malta_machine;
 
+/* mips_pica61.c */
+extern QEMUMachine mips_pica61_machine;
+
+/* mips_mipssim.c */
+extern QEMUMachine mips_mipssim_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);
@@ -1207,6 +1213,9 @@
 /* shix.c */
 extern QEMUMachine shix_machine;
 
+/* r2d.c */
+extern QEMUMachine r2d_machine;
+
 #ifdef TARGET_PPC
 /* PowerPC hardware exceptions management helpers */
 typedef void (*clk_setup_cb)(void *opaque, uint32_t freq);
@@ -1234,12 +1243,12 @@
 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);
 
 extern CPUWriteMemoryFunc *PPC_io_write[];
 extern CPUReadMemoryFunc *PPC_io_read[];
 void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val);
+#endif
 
 /* sun4m.c */
 extern QEMUMachine ss5_machine, ss10_machine;
@@ -1284,7 +1293,8 @@
 int load_uboot(const char *filename, target_ulong *ep, int *is_linux);
 
 /* slavio_timer.c */
-void slavio_timer_init(target_phys_addr_t addr, qemu_irq irq, int mode);
+void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq,
+                           qemu_irq *cpu_irqs);
 
 /* slavio_serial.c */
 SerialState *slavio_serial_init(target_phys_addr_t base, qemu_irq irq,
@@ -1318,20 +1328,28 @@
 extern QEMUMachine sun4u_machine;
 
 /* NVRAM helpers */
+typedef uint32_t (*nvram_read_t)(void *private, uint32_t addr);
+typedef void (*nvram_write_t)(void *private, uint32_t addr, uint32_t val);
+typedef struct nvram_t {
+    void *opaque;
+    nvram_read_t read_fn;
+    nvram_write_t write_fn;
+} nvram_t;
+
 #include "hw/m48t59.h"
 
-void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value);
-uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr);
-void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value);
-uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr);
-void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value);
-uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr);
-void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
+void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value);
+uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr);
+void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value);
+uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr);
+void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value);
+uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr);
+void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
                        const unsigned char *str, uint32_t max);
-int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max);
-void NVRAM_set_crc (m48t59_t *nvram, uint32_t addr,
+int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max);
+void NVRAM_set_crc (nvram_t *nvram, uint32_t addr,
                     uint32_t start, uint32_t count);
-int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
+int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
                           const unsigned char *arch,
                           uint32_t RAM_size, int boot_device,
                           uint32_t kernel_image, uint32_t kernel_size,
@@ -1379,10 +1397,7 @@
 void adb_kbd_init(ADBBusState *bus);
 void adb_mouse_init(ADBBusState *bus);
 
-/* cuda.c */
-
 extern ADBBusState adb_bus;
-int cuda_init(qemu_irq irq);
 
 #include "hw/usb.h"
 
@@ -1522,6 +1537,17 @@
 
 int sh7750_register_io_device(struct SH7750State *s,
 			      sh7750_io_device * device);
+/* sh_timer.c */
+#define TMU012_FEAT_TOCR   (1 << 0)
+#define TMU012_FEAT_3CHAN  (1 << 1)
+#define TMU012_FEAT_EXTCLK (1 << 2)
+void tmu012_init(uint32_t base, int feat, uint32_t freq);
+
+/* sh_serial.c */
+#define SH_SERIAL_FEAT_SCIF (1 << 0)
+void sh_serial_init (target_phys_addr_t base, int feat,
+		     uint32_t freq, CharDriverState *chr);
+
 /* tc58128.c */
 int tc58128_init(struct SH7750State *s, char *zone1, char *zone2);
 
@@ -1555,8 +1581,18 @@
 #define NAND_MFR_HYNIX		0xad
 #define NAND_MFR_MICRON		0x2c
 
-#include "ecc.h"
+/* ecc.c */
+struct ecc_state_s {
+    uint8_t cp;		/* Column parity */
+    uint16_t lp[2];	/* Line parity */
+    uint16_t count;
+};
 
+uint8_t ecc_digest(struct ecc_state_s *s, uint8_t sample);
+void ecc_reset(struct ecc_state_s *s);
+void ecc_put(QEMUFile *f, struct ecc_state_s *s);
+void ecc_get(QEMUFile *f, struct ecc_state_s *s);
+
 /* ads7846.c */
 struct ads7846_state_s;
 uint32_t ads7846_read(void *opaque);
@@ -1654,6 +1690,9 @@
 
 #include "hw/omap.h"
 
+/* tsc210x.c */
+struct uwire_slave_s *tsc2102_init(qemu_irq pint);
+
 /* mcf_uart.c */
 uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr);
 void mcf_uart_write(void *opaque, target_phys_addr_t addr, uint32_t val);

Modified: trunk/src/host/qemu-neo1973/vnc.c
===================================================================
--- trunk/src/host/qemu-neo1973/vnc.c	2007-10-29 20:40:05 UTC (rev 3302)
+++ trunk/src/host/qemu-neo1973/vnc.c	2007-10-29 21:14:04 UTC (rev 3303)
@@ -1818,6 +1818,7 @@
     VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
     if (vs->major != 3 ||
 	(vs->minor != 3 &&
+	 vs->minor != 4 &&
 	 vs->minor != 5 &&
 	 vs->minor != 7 &&
 	 vs->minor != 8)) {
@@ -1827,10 +1828,10 @@
 	vnc_client_error(vs);
 	return 0;
     }
-    /* Some broken client report v3.5 which spec requires to be treated
+    /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
      * as equivalent to v3.3 by servers
      */
-    if (vs->minor == 5)
+    if (vs->minor == 4 || vs->minor == 5)
 	vs->minor = 3;
 
     if (vs->minor == 3) {





More information about the commitlog mailing list