## Automatically generated incremental diff
## From:   linux-2.2.12-pre6
## To:     linux-2.2.12-pre7
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp hpa $

diff -urN linux-2.2.12-pre6/arch/ppc/defconfig linux-2.2.12-pre7/arch/ppc/defconfig
--- linux-2.2.12-pre6/arch/ppc/defconfig	2003-08-15 15:07:07.000000000 -0700
+++ linux-2.2.12-pre7/arch/ppc/defconfig	2003-08-15 15:07:07.000000000 -0700
@@ -9,14 +9,13 @@
 CONFIG_6xx=y
 # CONFIG_PPC64 is not set
 # CONFIG_8xx is not set
-CONFIG_PMAC=y
+# CONFIG_PMAC is not set
 # CONFIG_PREP is not set
 # CONFIG_CHRP is not set
-# CONFIG_ALL_PPC is not set
+CONFIG_ALL_PPC=y
 # CONFIG_APUS is not set
 # CONFIG_MBX is not set
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 CONFIG_6xx=y
 
 #
@@ -24,7 +23,7 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
+CONFIG_MODVERSIONS=y
 CONFIG_KMOD=y
 CONFIG_PCI=y
 # CONFIG_PCI_QUIRKS is not set
@@ -35,11 +34,10 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_MISC=m
+# CONFIG_BINFMT_MISC is not set
 # CONFIG_BINFMT_JAVA is not set
-CONFIG_PARPORT=m
-# CONFIG_PARPORT_PC is not set
-# CONFIG_VGA_CONSOLE is not set
+# CONFIG_PARPORT is not set
+CONFIG_VGA_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_COMPAT_XPMAC=y
 CONFIG_PMAC_PBOOK=y
@@ -52,6 +50,7 @@
 # CONFIG_TOTALMP is not set
 CONFIG_BOOTX_TEXT=y
 # CONFIG_MOTOROLA_HOTSWAP is not set
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Plug and Play support
@@ -61,7 +60,7 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_FD=y
 CONFIG_BLK_DEV_IDE=y
 
 #
@@ -75,16 +74,8 @@
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_VIA82C586 is not set
-CONFIG_BLK_DEV_CMD646=y
-# CONFIG_BLK_DEV_SL82C105 is not set
+# CONFIG_BLK_DEV_IDEPCI is not set
+CONFIG_BLK_DEV_SL82C105=y
 CONFIG_BLK_DEV_IDE_PMAC=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
 CONFIG_BLK_DEV_IDEDMA=y
@@ -100,10 +91,8 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-CONFIG_PARIDE_PARPORT=m
+CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -125,7 +114,7 @@
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
 CONFIG_IP_ALIAS=y
-# CONFIG_SYN_COOKIES is not set
+CONFIG_SYN_COOKIES=y
 
 #
 # (it is safe to leave these untouched)
@@ -200,14 +189,14 @@
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_G_NCR5380_PORT is not set
+# CONFIG_SCSI_G_NCR5380_MEM is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
-CONFIG_SCSI_NCR53C8XX=y
+# CONFIG_SCSI_NCR53C8XX is not set
 CONFIG_SCSI_SYM53C8XX=y
 CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
@@ -215,7 +204,7 @@
 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set
 # CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
-CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT=y
+# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
@@ -237,19 +226,10 @@
 # Network device support
 #
 CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_ETHERTAP is not set
-# CONFIG_NET_SB1000 is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
 CONFIG_NET_ETHERNET=y
 CONFIG_MACE=y
 CONFIG_BMAC=y
@@ -258,12 +238,11 @@
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_RTL8139 is not set
-# CONFIG_SIS900 is not set
 # CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
 # CONFIG_NET_ISA is not set
 CONFIG_NET_EISA=y
-# CONFIG_PCNET32 is not set
-# CONFIG_ACENIC is not set
+CONFIG_PCNET32=y
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
@@ -282,36 +261,22 @@
 # CONFIG_NET_POCKET is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-
-#
-# Appletalk devices
-#
+# CONFIG_DLCI is not set
 # CONFIG_LTPC is not set
 # CONFIG_COPS is not set
 # CONFIG_IPDDP is not set
-# CONFIG_PLIP is not set
-CONFIG_PPP=m
+CONFIG_PPP=y
 
 #
 # CCP compressors for PPP are only built as modules.
 #
 # CONFIG_SLIP is not set
 # CONFIG_NET_RADIO is not set
-
-#
-# Token ring devices
-#
 # CONFIG_TR is not set
-# CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
 # CONFIG_HOSTESS_SV11 is not set
 # CONFIG_COSA is not set
-# CONFIG_SEALEVEL_4021 is not set
-# CONFIG_DLCI is not set
+# CONFIG_RCPCI is not set
 
 #
 # Amateur Radio support
@@ -337,12 +302,16 @@
 CONFIG_FB_CONTROL=y
 CONFIG_FB_PLATINUM=y
 CONFIG_FB_VALKYRIE=y
-CONFIG_FB_ATY=y
+# CONFIG_FB_ATY is not set
 CONFIG_FB_IMSTT=y
 CONFIG_FB_CT65550=y
 # CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_MATROX is not set
-CONFIG_FB_ATY=y
+CONFIG_FB_MATROX=y
+# CONFIG_FB_MATROX_MILLENIUM is not set
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G100=y
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_ATY is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
 CONFIG_FBCON_CFB8=y
@@ -364,13 +333,22 @@
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-# CONFIG_SERIAL is not set
+CONFIG_SERIAL=m
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_PRINTER is not set
-# CONFIG_MOUSE is not set
+CONFIG_MOUSE=y
+
+#
+# Mice
+#
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
 # CONFIG_QIC02_TAPE is not set
 # CONFIG_WATCHDOG is not set
 CONFIG_NVRAM=y
@@ -391,6 +369,14 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
+# CONFIG_FT_NORMAL_DEBUG is not set
+# CONFIG_FT_FULL_DEBUG is not set
+# CONFIG_FT_NO_TRACE is not set
+# CONFIG_FT_NO_TRACE_AT_ALL is not set
+# CONFIG_FT_STD_FDC is not set
+# CONFIG_FT_MACH2 is not set
+# CONFIG_FT_PROBE_FC10 is not set
+# CONFIG_FT_ALT_FDC is not set
 
 #
 # USB drivers - not for the faint of heart
@@ -405,10 +391,10 @@
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 CONFIG_HFS_FS=y
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
 # CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=m
+CONFIG_VFAT_FS=y
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
@@ -421,7 +407,6 @@
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_EFS_FS is not set
 
 #
 # Network File Systems
@@ -473,7 +458,7 @@
 # CONFIG_NLS_ISO8859_7 is not set
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
-CONFIG_NLS_ISO8859_15=y
+# CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
 
 #
@@ -486,7 +471,34 @@
 # CONFIG_SOUND_SONICVIBES is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
+CONFIG_SOUND_OSS=y
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+CONFIG_SOUND_CS4232=m
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_UART6850 is not set
+
+#
+# Additional low level sound drivers
+#
+# CONFIG_LOWLEVEL_SOUND is not set
 
 #
 # Kernel hacking
diff -urN linux-2.2.12-pre6/arch/ppc/kernel/chrp_pci.c linux-2.2.12-pre7/arch/ppc/kernel/chrp_pci.c
--- linux-2.2.12-pre6/arch/ppc/kernel/chrp_pci.c	1999-08-09 12:04:57.000000000 -0700
+++ linux-2.2.12-pre7/arch/ppc/kernel/chrp_pci.c	2003-08-15 15:07:07.000000000 -0700
@@ -300,11 +300,11 @@
 		}
 		/* the F50 identifies the amd as a trident */
 		if ( (dev->vendor == PCI_VENDOR_ID_TRIDENT) &&
-		      (dev->class == PCI_CLASS_NETWORK_ETHERNET) )
+		      (dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET) )
 		{
 			dev->vendor = PCI_VENDOR_ID_AMD;
-			pcibios_write_config_word(dev->bus->number, dev->devfn,
-						   PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
+			pcibios_write_config_word(dev->bus->number,
+			  dev->devfn, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
 		}
 	}
 }
diff -urN linux-2.2.12-pre6/arch/ppc/kernel/feature.c linux-2.2.12-pre7/arch/ppc/kernel/feature.c
--- linux-2.2.12-pre6/arch/ppc/kernel/feature.c	1999-03-10 21:30:31.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/kernel/feature.c	2003-08-15 15:07:07.000000000 -0700
@@ -41,7 +41,9 @@
 	OH_BAY_FLOPPY_ENABLE,	/* FEATURE_Mediabay_floppy_enable */
 	0,			/* FEATURE_BMac_reset */
 	0,			/* FEATURE_BMac_IO_enable */
-	0			/* FEATURE_Modem_Reset -> guess...*/
+	0,			/* FEATURE_Modem_Reset -> guess... */
+	OH_IDE_POWER,		/* FEATURE_IDE_DiskPower -> guess... */
+	OH_IDE_RESET		/* FEATURE_IDE_Reset (0 based) -> guess... */
 };
 
 /* assume these are the same as the ohare until proven otherwise */
@@ -63,7 +65,9 @@
 	OH_BAY_FLOPPY_ENABLE,	/* FEATURE_Mediabay_floppy_enable */
 	0x80000000,		/* FEATURE_BMac_reset */
 	0x60000000,		/* FEATURE_BMac_IO_enable */
-	0x02000000		/* FEATURE_Modem_Reset -> guess...*/
+	0x02000000,		/* FEATURE_Modem_Reset -> guess...*/
+	OH_IDE_POWER,		/* FEATURE_IDE_DiskPower -> guess... */
+	OH_IDE_RESET		/* FEATURE_IDE_Reset (0 based) -> guess... */
 };
 
 /* definition of a feature controller object */
@@ -191,8 +195,8 @@
 
 	save_flags(flags);
 	cli();
-	st_le32( controllers[controller].reg,
-		 ld_le32(controllers[controller].reg) |
+	out_le32( controllers[controller].reg,
+		 in_le32(controllers[controller].reg) |
 		 controllers[controller].bits[f]);
 	restore_flags(flags);
 	udelay(10);
@@ -220,8 +224,8 @@
 
 	save_flags(flags);
 	cli();
-	st_le32( controllers[controller].reg,
-		 ld_le32(controllers[controller].reg) &
+	out_le32( controllers[controller].reg,
+		 in_le32(controllers[controller].reg) &
 		 ~(controllers[controller].bits[f]));
 	restore_flags(flags);
 	udelay(10);
@@ -241,7 +245,7 @@
 	if (controller < 0)
 		return controller;
 	
-	return (ld_le32(controllers[controller].reg) &
+	return (in_le32(controllers[controller].reg) &
 		controllers[controller].bits[f]) != 0;
 }
 
diff -urN linux-2.2.12-pre6/arch/ppc/kernel/Makefile linux-2.2.12-pre7/arch/ppc/kernel/Makefile
--- linux-2.2.12-pre6/arch/ppc/kernel/Makefile	1999-06-04 13:30:47.000000000 -0700
+++ linux-2.2.12-pre7/arch/ppc/kernel/Makefile	2003-08-15 15:07:07.000000000 -0700
@@ -25,6 +25,9 @@
 ifdef CONFIG_TOTALMP
 O_OBJS += totalmp.o
 endif
+ifdef CONFIG_PMAC_PBOOK
+O_OBJS += sleep.o
+endif
 
 ifeq ($(CONFIG_MBX),y)
 O_OBJS += mbx_setup.o mbx_pci.o softemu8xx.o i8259.o ppc8xx_pic.o
diff -urN linux-2.2.12-pre6/arch/ppc/kernel/misc.S linux-2.2.12-pre7/arch/ppc/kernel/misc.S
--- linux-2.2.12-pre6/arch/ppc/kernel/misc.S	2003-08-15 15:07:07.000000000 -0700
+++ linux-2.2.12-pre7/arch/ppc/kernel/misc.S	2003-08-15 15:07:07.000000000 -0700
@@ -17,6 +17,7 @@
 #include <asm/unistd.h>
 #include <asm/errno.h>
 #include <asm/processor.h>
+#include <asm/page.h>
 #include "ppc_asm.tmpl"
 #include "ppc_defs.h"
 
@@ -469,36 +470,42 @@
 	Author:	Terry Greeniaus (tgree@phys.ualberta.ca)
 	Please e-mail updates to this file to me, thanks!
 */
+/* Usage:
+	
+	When setting the L2CR register, you must do a few special
+	things.  If you are enabling the cache, you must perform a
+	global invalidate.  If you are disabling the cache, you must
+	flush the cache contents first.  This routine takes care of
+	doing these things.  When first enabling the cache, make sure
+	you pass in the L2CR you want, as well as passing in the
+	global invalidate bit set.  A global invalidate will only be
+	performed if the L2I bit is set in applyThis.  When enabling
+	the cache, you should also set the L2E bit in applyThis.  If
+	you want to modify the L2CR contents after the cache has been
+	enabled, the recommended procedure is to first call
+	__setL2CR(0) to disable the cache and then call it again with
+	the new values for L2CR.  Examples:
+
+	_setL2CR(0)		- disables the cache
+	_setL2CR(0xB3A04000)	- enables my G3 upgrade card:
+				- L2E set to turn on the cache
+				- L2SIZ set to 1MB
+				- L2CLK set to 1:1
+				- L2RAM set to pipelined synchronous late-write
+				- L2I set to perform a global invalidation
+				- L2OH set to 0.5 nS
+				- L2DF set because this upgrade card
+				  requires it
+
+	A similar call should work for your card.  You need to know
+	the correct setting for your card and then place them in the
+	fields I have outlined above.  Other fields support optional
+	features, such as L2DO which caches only data, or L2TS which
+	causes cache pushes from the L1 cache to go to the L2 cache
+	instead of to main memory.
+*/
 
 _GLOBAL(_set_L2CR)
-	/* Usage:
-	
-		When setting the L2CR register, you must do a few special things.  If you are enabling the
-		cache, you must perform a global invalidate.  If you are disabling the cache, you must
-		flush the cache contents first.  This routine takes care of doing these things.  When first
-		enabling the cache, make sure you pass in the L2CR you want, as well as passing in the
-		global invalidate bit set.  A global invalidate will only be performed if the L2I bit is set
-		in applyThis.  When enabling the cache, you should also set the L2E bit in applyThis.  If you
-		want to modify the L2CR contents after the cache has been enabled, the recommended
-		procedure is to first call __setL2CR(0) to disable the cache and then call it again with
-		the new values for L2CR.  Examples:
-	
-			_setL2CR(0)			-	disables the cache
-			_setL2CR(0xB3A04000)		-	enables my G3 upgrade card:
-							-	L2E set to turn on the cache
-							-	L2SIZ set to 1MB
-							-	L2CLK set to 1:1
-							-	L2RAM set to pipelined syncronous late-write
-							-	L2I set to perform a global invalidation
-							-	L2OH set to 0.5 nS
-							-	L2DF set because this upgrade card requires it
-	
-		A similar call should work for your card.  You need to know the correct setting for your
-		card and then place them in the fields I have outlined above.  Other fields support optional
-		features, such as L2DO which caches only data, or L2TS which causes cache pushes from
-		the L1 cache to go to the L2 cache instead of to main memory.
-	*/
-	
 	/* Make sure this is a 750 chip */
 	mfspr	r4,PVR
 	rlwinm	r4,r4,16,16,31
@@ -510,76 +517,74 @@
 thisIs750:
 	/* Get the current enable bit of the L2CR into r4 */
 	mfspr	r4,L2CR
-	rlwinm	r4,r4,0,0,0
+	mfmsr	r7
 	
 	/* See if we want to perform a global inval this time. */
-	rlwinm	r6,r3,0,10,10		/* r6 contains the new invalidate bit */
-	rlwinm.	r5,r3,0,0,0		/* r5 contains the new enable bit */
-	rlwinm	r3,r3,0,11,9		/* Turn off the invalidate bit */
-	rlwinm	r3,r3,0,1,31		/* Turn off the enable bit */
-	or	r3,r3,r4		/* Keep the enable bit the same as it was for now. */
-	bne	dontDisableCache	/* Only disable the cache if L2CRApply has the enable bit off */
+	rlwinm	r6,r3,0,10,10	/* r6 contains the new invalidate bit */
+	rlwinm.	r5,r3,0,0,0	/* r5 contains the new enable bit */
+	rlwinm	r3,r3,0,11,9	/* Turn off the invalidate bit */
+	rlwimi	r3,r4,0,0,0	/* Keep the enable bit the same as it was. */
+	bne	dontDisableCache /* Only disable the cache if L2CRApply
+				    has the enable bit off */
 
 disableCache:
-	/* Disable the cache.  First, we turn off data relocation. */
-	mfmsr	r7
-	rlwinm	r4,r7,0,28,26		/* Turn off DR bit */
-	rlwinm	r4,r4,0,17,15		/* Turn off EE bit - an external exception while we are flushing
-					   the cache is fatal (comment this line and see!) */
+	/* Disable the cache.  First, we turn off interrupts.
+	   An interrupt while we are flushing the cache could bring
+	   in data which may not get properly flushed. */
+	rlwinm	r4,r7,0,17,15	/* Turn off EE bit */
 	sync
 	mtmsr	r4
 	sync
 	
-	/*
-		Now, read the first 2MB of memory to put new data in the cache.
-		(Actually we only need the size of the L2 cache plus
-		the size of the L1 cache, but 2MB will cover everything just to be safe).
-	*/
+/*
+	Now, read the first 2MB of memory to put new data in the cache.
+	(Actually we only need the size of the L2 cache plus the size
+	of the L1 cache, but 2MB will cover everything just to be safe).
+*/
 	lis	r4,0x0001
 	mtctr	r4
-	li	r4,0
-loadLoop:
-	lwzx	r0,r0,r4
+	lis	r4,KERNELBASE@h
+1:	lwzx	r0,r0,r4
 	addi	r4,r4,0x0020		/* Go to start of next cache line */
-	bdnz	loadLoop
+	bdnz	1b
 	
 	/* Now, flush the first 2MB of memory */
 	lis	r4,0x0001
 	mtctr	r4
-	li	r4,0
+	lis	r4,KERNELBASE@h
 	sync
-flushLoop:
-	dcbf	r0,r4
+2:	dcbf	r0,r4
 	addi	r4,r4,0x0020	/* Go to start of next cache line */
-	bdnz	flushLoop
+	bdnz	2b
 	
 	/* Turn off the L2CR enable bit. */
 	rlwinm	r3,r3,0,1,31
 	
-	/* Reenable data relocation. */
-	sync
-	mtmsr	r7
-	sync
-	
 dontDisableCache:
 	/* Set up the L2CR configuration bits */
 	sync
 	mtspr	L2CR,r3
 	sync
+
+	/* Reenable interrupts if necessary. */
+	mtmsr	r7
+	sync
+	
 	cmplwi	r6,0
 	beq	noInval
 	
 	/* Perform a global invalidation */
 	oris	r3,r3,0x0020
 	sync
-	mtspr	1017,r3
+	mtspr	L2CR,r3
 	sync
-invalCompleteLoop:			/* Wait for the invalidation to complete */
-	mfspr	r3,1017
+
+	/* Wait for the invalidation to complete */
+3:	mfspr	r3,L2CR
 	rlwinm.	r4,r3,0,31,31
-	bne	invalCompleteLoop
+	bne	3b
 	
-	rlwinm	r3,r3,0,11,9;		/* Turn off the L2I bit */
+	rlwinm	r3,r3,0,11,9		/* Turn off the L2I bit */
 	sync
 	mtspr	L2CR,r3
 	sync
@@ -588,8 +593,7 @@
 	/* See if we need to enable the cache */
 	cmplwi	r5,0
 	beqlr
-	
-enableCache:
+
 	/* Enable the cache */
 	oris	r3,r3,0x8000
 	mtspr	L2CR,r3
diff -urN linux-2.2.12-pre6/arch/ppc/kernel/pmac_pic.c linux-2.2.12-pre7/arch/ppc/kernel/pmac_pic.c
--- linux-2.2.12-pre6/arch/ppc/kernel/pmac_pic.c	1999-05-12 08:50:08.000000000 -0700
+++ linux-2.2.12-pre7/arch/ppc/kernel/pmac_pic.c	2003-08-15 15:07:07.000000000 -0700
@@ -360,3 +360,41 @@
 	request_irq(20, xmon_irq, 0, "NMI - XMON", 0);
 #endif	/* CONFIG_XMON */
 }
+
+#ifdef CONFIG_PMAC_PBOOK
+/*
+ * These procedures are used in implementing sleep on the powerbooks.
+ * sleep_save_intrs() saves the states of all interrupt enables
+ * and disables all interupts except for the nominated one.
+ * sleep_restore_intrs() restores the states of all interrupt enables.
+ */
+unsigned int sleep_save_mask[2];
+
+void
+sleep_save_intrs(int viaint)
+{
+	sleep_save_mask[0] = ppc_cached_irq_mask[0];
+	sleep_save_mask[1] = ppc_cached_irq_mask[1];
+	ppc_cached_irq_mask[0] = 0;
+	ppc_cached_irq_mask[1] = 0;
+	set_bit(viaint, ppc_cached_irq_mask);
+	out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);
+	if (max_real_irqs > 32)
+		out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
+	mb();
+}
+
+void
+sleep_restore_intrs(void)
+{
+	int i;
+
+	out_le32(&pmac_irq_hw[0]->enable, 0);
+	if (max_real_irqs > 32)
+		out_le32(&pmac_irq_hw[1]->enable, 0);
+	mb();
+	for (i = 0; i < max_real_irqs; ++i)
+		if (test_bit(i, sleep_save_mask))
+			pmac_unmask_irq(i);
+}
+#endif /* CONFIG_PMAC_PBOOK */
diff -urN linux-2.2.12-pre6/arch/ppc/kernel/pmac_setup.c linux-2.2.12-pre7/arch/ppc/kernel/pmac_setup.c
--- linux-2.2.12-pre6/arch/ppc/kernel/pmac_setup.c	1999-08-09 12:04:57.000000000 -0700
+++ linux-2.2.12-pre7/arch/ppc/kernel/pmac_setup.c	2003-08-15 15:07:07.000000000 -0700
@@ -161,16 +161,24 @@
 	/* find ram info */
 	np = find_devices("memory");
 	if (np != 0) {
+		int n;
 		struct reg_property *reg = (struct reg_property *)
-			get_property(np, "reg", NULL);
+			get_property(np, "reg", &n);
+		
 		if (reg != 0) {
-			len += sprintf(buffer+len, "memory\t\t: %dMB\n",
-				       reg->size >> 20);
+			unsigned long total = 0;
+
+			for (n /= sizeof(struct reg_property); n > 0; --n)
+				total += (reg++)->size;
+			len += sprintf(buffer+len, "memory\t\t: %luMB\n",
+				       total >> 20);
 		}
 	}
 
 	/* Checks "l2cr-value" property in the registry */
 	np = find_devices("cpus");		
+	if (np == 0)
+		np = find_type_devices("cpu");		
 	if (np != 0) {
 		unsigned int *l2cr = (unsigned int *)
 			get_property(np, "l2cr-value", NULL);
@@ -261,6 +269,8 @@
 	/* Checks "l2cr-value" property in the registry */
 	if ( (_get_PVR() >> 16) == 8) {
 		struct device_node *np = find_devices("cpus");		
+		if (np == 0)
+			np = find_type_devices("cpu");		
 		if (np != 0) {
 			unsigned int *l2cr = (unsigned int *)
 				get_property(np, "l2cr-value", NULL);
diff -urN linux-2.2.12-pre6/arch/ppc/kernel/pmac_time.c linux-2.2.12-pre7/arch/ppc/kernel/pmac_time.c
--- linux-2.2.12-pre6/arch/ppc/kernel/pmac_time.c	1998-08-04 23:57:51.000000000 -0700
+++ linux-2.2.12-pre7/arch/ppc/kernel/pmac_time.c	2003-08-15 15:07:07.000000000 -0700
@@ -139,13 +139,12 @@
 /*
  * Reset the time after a sleep.
  */
-static int time_sleep_notify(struct notifier_block *this, unsigned long event,
-			     void *x)
+static int time_sleep_notify(struct pmu_sleep_notifier *self, int when)
 {
 	static unsigned long time_diff;
 
-	switch (event) {
-	case PBOOK_SLEEP:
+	switch (when) {
+	case PBOOK_SLEEP_NOW:
 		time_diff = xtime.tv_sec - pmac_get_rtc_time();
 		break;
 	case PBOOK_WAKE:
@@ -155,11 +154,11 @@
 		last_rtc_update = xtime.tv_sec;
 		break;
 	}
-	return NOTIFY_DONE;
+	return PBOOK_SLEEP_OK;
 }
 
-static struct notifier_block time_sleep_notifier = {
-	time_sleep_notify, NULL, 100
+static struct pmu_sleep_notifier time_sleep_notifier = {
+	time_sleep_notify, SLEEP_LEVEL_MISC,
 };
 #endif /* CONFIG_PMAC_PBOOK */
 
@@ -174,7 +173,7 @@
 	int freq, *fp, divisor;
 
 #ifdef CONFIG_PMAC_PBOOK
-	notifier_chain_register(&sleep_notifier_list, &time_sleep_notifier);
+	pmu_register_sleep_notifier(&time_sleep_notifier);
 #endif /* CONFIG_PMAC_PBOOK */
 
 	if (via_calibrate_decr())
diff -urN linux-2.2.12-pre6/arch/ppc/kernel/ppc_ksyms.c linux-2.2.12-pre7/arch/ppc/kernel/ppc_ksyms.c
--- linux-2.2.12-pre6/arch/ppc/kernel/ppc_ksyms.c	2003-08-15 15:07:07.000000000 -0700
+++ linux-2.2.12-pre7/arch/ppc/kernel/ppc_ksyms.c	2003-08-15 15:07:07.000000000 -0700
@@ -188,7 +188,8 @@
 EXPORT_SYMBOL(pmu_request);
 EXPORT_SYMBOL(pmu_poll);
 #ifdef CONFIG_PMAC_PBOOK
-EXPORT_SYMBOL(sleep_notifier_list);
+EXPORT_SYMBOL(pmu_register_sleep_notifier);
+EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
 #endif CONFIG_PMAC_PBOOK
 EXPORT_SYMBOL(abort);
 EXPORT_SYMBOL(find_devices);
diff -urN linux-2.2.12-pre6/arch/ppc/kernel/process.c linux-2.2.12-pre7/arch/ppc/kernel/process.c
--- linux-2.2.12-pre6/arch/ppc/kernel/process.c	2003-08-15 15:07:07.000000000 -0700
+++ linux-2.2.12-pre7/arch/ppc/kernel/process.c	2003-08-15 15:07:07.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- * $Id: process.c,v 1.83.2.6 1999/08/10 03:24:06 cort Exp $
+ * $Id: process.c,v 1.83.2.7 1999/08/16 01:44:58 paulus Exp $
  *
  *  linux/arch/ppc/kernel/process.c
  *
diff -urN linux-2.2.12-pre6/arch/ppc/kernel/prom.c linux-2.2.12-pre7/arch/ppc/kernel/prom.c
--- linux-2.2.12-pre6/arch/ppc/kernel/prom.c	2003-08-15 15:07:07.000000000 -0700
+++ linux-2.2.12-pre7/arch/ppc/kernel/prom.c	2003-08-15 15:07:07.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- * $Id: prom.c,v 1.54.2.6 1999/08/10 21:36:46 cort Exp $
+ * $Id: prom.c,v 1.54.2.7 1999/08/16 01:48:43 paulus Exp $
  *
  * Procedures for interfacing to the Open Firmware PROM on
  * Power Macintosh computers.
@@ -105,9 +105,9 @@
 
 #ifdef CONFIG_BOOTX_TEXT
 
-static void drawchar(char c);
+void drawchar(char c);
+void drawstring(const char *c);
 static void drawhex(unsigned long v);
-static void drawstring(const char *c);
 static void scrollscreen(void);
 
 static void draw_byte(unsigned char c, long locX, long locY);
@@ -294,6 +294,8 @@
 #endif		
 
 		RELOC(boot_infos) = PTRUNRELOC(bi);
+		if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
+			bi->logicalDisplayBase = 0;
 
 		clearscreen();
 
@@ -347,9 +349,13 @@
 			}
 		}
 		
-		space = bi->deviceTreeOffset + bi->deviceTreeSize;
-		if (bi->ramDisk)
-			space = bi->ramDisk + bi->ramDiskSize;
+		/* Move klimit to enclose device tree, args, ramdisk, etc... */
+		if (bi->version < 5) {
+			space = bi->deviceTreeOffset + bi->deviceTreeSize;
+			if (bi->ramDisk)
+				space = bi->ramDisk + bi->ramDiskSize;
+		} else
+			space = bi->totalParamsSize;
 		RELOC(klimit) = PTRUNRELOC((char *) bi + space);
 
 		/* New BootX will have flushed all TLBs and enters kernel with
@@ -1213,6 +1219,22 @@
 }
 
 /*
+ * Indicates whether the root node has a given value in its
+ * compatible property.
+ */
+__openfirmware
+int
+machine_is_compatible(const char *compat)
+{
+	struct device_node *root;
+
+	root = find_path_device("/");
+	if (root == 0)
+		return 0;
+	return device_is_compatible(root, compat);
+}
+
+/*
  * Find the device_node with a given phandle.
  */
 __openfirmware
@@ -1350,19 +1372,41 @@
 	prom_exit();
 }
 
+#ifdef CONFIG_XMON
+__init
+void
+map_bootx_text(void)
+{
+	if (boot_infos == 0)
+		return;
+	boot_infos->logicalDisplayBase =
+		ioremap((unsigned long) boot_infos->dispDeviceBase,
+			boot_infos->dispDeviceRowBytes * boot_infos->dispDeviceRect[3]);
+}
+#endif /* CONFIG_XMON */
+
 /* Calc the base address of a given point (x,y) */
-#define CALC_BASE(x,y)	((BOOT_INFO_IS_V2_COMPATIBLE(bi) ? bi->logicalDisplayBase :	\
-			bi->dispDeviceBase) + (bi->dispDeviceRect[0] + (x)) *		\
-			(bi->dispDeviceDepth >> 3) + bi->dispDeviceRowBytes *		\
-			((y) + bi->dispDeviceRect[1]))
+__pmac
+static unsigned char *
+calc_base(boot_infos_t *bi, int x, int y)
+{
+	unsigned char *base;
 
-__init
+	base = bi->logicalDisplayBase;
+	if (base == 0)
+		base = bi->dispDeviceBase;
+	base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3);
+	base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes;
+	return base;
+}
+
+__pmac
 static void
 clearscreen(void)
 {
 	unsigned long offset	= reloc_offset();
 	boot_infos_t* bi	= PTRRELOC(RELOC(boot_infos));
-	unsigned long *base	= (unsigned long *)CALC_BASE(0,0);
+	unsigned long *base	= (unsigned long *)calc_base(bi, 0, 0);
 	unsigned long width 	= ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
 					(bi->dispDeviceDepth >> 3)) >> 2;
 	int i,j;
@@ -1381,13 +1425,13 @@
 	__asm__ __volatile__ ("dcbst 0,%0" :: "r" (addr));
 }
 
-__init
+__pmac
 static void
 flushscreen(void)
 {
 	unsigned long offset	= reloc_offset();
 	boot_infos_t* bi	= PTRRELOC(RELOC(boot_infos));
-	unsigned long *base	= (unsigned long *)CALC_BASE(0,0);
+	unsigned long *base	= (unsigned long *)calc_base(bi, 0, 0);
 	unsigned long width 	= ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
 					(bi->dispDeviceDepth >> 3)) >> 2;
 	int i,j;
@@ -1405,14 +1449,14 @@
 
 #ifdef CONFIG_BOOTX_TEXT
 
-__init
+__pmac
 static void
 scrollscreen(void)
 {
 	unsigned long offset		= reloc_offset();
 	boot_infos_t* bi		= PTRRELOC(RELOC(boot_infos));
-	unsigned long *src		= (unsigned long *)CALC_BASE(0,16);
-	unsigned long *dst		= (unsigned long *)CALC_BASE(0,0);
+	unsigned long *src		= (unsigned long *)calc_base(bi,0,16);
+	unsigned long *dst		= (unsigned long *)calc_base(bi,0,0);
 	unsigned long width		= ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
 						(bi->dispDeviceDepth >> 3)) >> 2;
 	int i,j;
@@ -1435,21 +1479,33 @@
 	}
 }
 
-__init
-static void
+__pmac
+void
 drawchar(char c)
 {
 	unsigned long offset = reloc_offset();
 
-	switch(c) {
-		case '\r': RELOC(g_loc_X) = 0;			break;
-		case '\n': RELOC(g_loc_X) = 0; RELOC(g_loc_Y)++;	break;
-		default:
-			draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y));
-			if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) {
-				RELOC(g_loc_X) = 0;
-				RELOC(g_loc_Y)++;
-			}
+	switch (c) {
+	case '\b':
+		if (RELOC(g_loc_X) > 0)
+			--RELOC(g_loc_X);
+		break;
+	case '\t':
+		RELOC(g_loc_X) = (RELOC(g_loc_X) & -8) + 8;
+		break;
+	case '\r':
+		RELOC(g_loc_X) = 0;
+		break;
+	case '\n':
+		RELOC(g_loc_X) = 0;
+		RELOC(g_loc_Y)++;
+		break;
+	default:
+		draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y));
+	}
+	if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) {
+		RELOC(g_loc_X) = 0;
+		RELOC(g_loc_Y)++;
 	}
 	while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) {
 		scrollscreen();
@@ -1457,15 +1513,15 @@
 	}
 }
 
-__init
-static void
+__pmac
+void
 drawstring(const char *c)
 {
-	while(*c)
-		drawchar(*(c++));
+	while (*c)
+		drawchar(*c++);
 }
 
-__init
+__pmac
 static void
 drawhex(unsigned long v)
 {
@@ -1483,13 +1539,13 @@
 }
 
 
-__init
+__pmac
 static void
 draw_byte(unsigned char c, long locX, long locY)
 {
 	unsigned long offset	= reloc_offset();
 	boot_infos_t* bi	= PTRRELOC(RELOC(boot_infos));
-	unsigned char *base	= CALC_BASE(locX << 3, locY << 4);
+	unsigned char *base	= calc_base(bi, locX << 3, locY << 4);
 	unsigned char *font	= &RELOC(vga_font)[((unsigned long)c) * 16];
 	
 	switch(bi->dispDeviceDepth) {
@@ -1507,7 +1563,7 @@
 	}
 }
 
-__init
+__pmac
 static unsigned long expand_bits_8[16] = {
 	0x00000000,
 	0x000000ff,
@@ -1527,7 +1583,7 @@
 	0xffffffff
 };
 
-__init
+__pmac
 static unsigned long expand_bits_16[4] = {
 	0x00000000,
 	0x0000ffff,
@@ -1536,7 +1592,7 @@
 };
 
 
-__init
+__pmac
 static void
 draw_byte_32(unsigned char *font, unsigned long *base)
 {
@@ -1562,7 +1618,7 @@
 	}
 }
 
-__init
+__pmac
 static void
 draw_byte_16(unsigned char *font, unsigned long *base)
 {
@@ -1584,7 +1640,7 @@
 	}
 }
 
-__init
+__pmac
 static void
 draw_byte_8(unsigned char *font, unsigned long *base)
 {
@@ -1604,7 +1660,7 @@
 	}
 }
 
-__init
+__pmac
 static unsigned char vga_font[cmapsz] = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 
diff -urN linux-2.2.12-pre6/arch/ppc/kernel/sleep.S linux-2.2.12-pre7/arch/ppc/kernel/sleep.S
--- linux-2.2.12-pre6/arch/ppc/kernel/sleep.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/kernel/sleep.S	2003-08-15 15:07:07.000000000 -0700
@@ -0,0 +1,264 @@
+/*
+ * This file contains sleep low-level functions for PowerBook G3.
+ *    Copyright (C) 1999 Benjamin Herrenschmidt (bh40@calva.net)
+ *    and Paul Mackerras (paulus@cs.anu.edu.au).
+ *
+ * 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.
+ *
+ */
+
+#include "ppc_asm.tmpl"
+#include <asm/processor.h>
+#include <asm/page.h>
+
+#define MAGIC	0x4c617273	/* 'Lars' */
+
+/*
+ * Structure for storing CPU registers on the stack.
+ */
+#define SL_SP		0
+#define SL_PC		4
+#define SL_MSR		8
+#define SL_SDR1		0xc
+#define SL_SPRG0	0x10	/* 4 sprg's */
+#define SL_DBAT0	0x20
+#define SL_IBAT0	0x28
+#define SL_DBAT1	0x30
+#define SL_IBAT1	0x38
+#define SL_DBAT2	0x40
+#define SL_IBAT2	0x48
+#define SL_DBAT3	0x50
+#define SL_IBAT3	0x58
+#define SL_TB		0x60
+#define SL_HID0		0x68
+#define SL_R2		0x6c
+#define SL_R12		0x70	/* r12 to r31 */
+#define SL_SIZE		(SL_R12 + 80)
+
+#define tophys(rd,rs)   addis   rd,rs,-KERNELBASE@h     
+#define tovirt(rd,rs)	addis	rd,rs,KERNELBASE@h
+
+	.text
+
+_GLOBAL(low_sleep_handler)
+	mflr	r0
+	stw	r0,4(r1)
+	stwu	r1,-SL_SIZE(r1)
+	stw	r2,SL_R2(r1)
+	stmw	r12,SL_R12(r1)
+
+	/* Save MSR, SDR1, TB  */
+	mfmsr	r4
+	stw	r4,SL_MSR(r1)
+	mfsdr1	r4
+	stw	r4,SL_SDR1(r1)
+1:	
+	mftbu	r4
+	stw	r4,SL_TB(r1)
+	mftb	r5
+	stw	r5,SL_TB+4(r1)
+	mftbu	r3
+	cmpw	r3,r4
+	bne	1b
+	
+	/* Save SPRGs */
+	mfsprg	r4,0
+	stw	r4,SL_SPRG0(r1)
+	mfsprg	r4,1
+	stw	r4,SL_SPRG0+4(r1)
+	mfsprg	r4,2
+	stw	r4,SL_SPRG0+8(r1)
+	mfsprg	r4,3
+	stw	r4,SL_SPRG0+12(r1)
+
+	/* Save BATs */
+	mfdbatu	r4,0
+	stw	r4,SL_DBAT0(r1)
+	mfdbatl	r4,0
+	stw	r4,SL_DBAT0+4(r1)
+	mfdbatu	r4,1
+	stw	r4,SL_DBAT1(r1)
+	mfdbatl	r4,1
+	stw	r4,SL_DBAT1+4(r1)
+	mfdbatu	r4,2
+	stw	r4,SL_DBAT2(r1)
+	mfdbatl	r4,2
+	stw	r4,SL_DBAT2+4(r1)
+	mfdbatu	r4,3
+	stw	r4,SL_DBAT3(r1)
+	mfdbatl	r4,3
+	stw	r4,SL_DBAT3+4(r1)
+	mfibatu	r4,0
+	stw	r4,SL_IBAT0(r1)
+	mfibatl	r4,0
+	stw	r4,SL_IBAT0+4(r1)
+	mfibatu	r4,1
+	stw	r4,SL_IBAT1(r1)
+	mfibatl	r4,1
+	stw	r4,SL_IBAT1+4(r1)
+	mfibatu	r4,2
+	stw	r4,SL_IBAT2(r1)
+	mfibatl	r4,2
+	stw	r4,SL_IBAT2+4(r1)
+	mfibatu	r4,3
+	stw	r4,SL_IBAT3(r1)
+	mfibatl	r4,3
+	stw	r4,SL_IBAT3+4(r1)
+
+	/* Save HID0 */
+	mfspr	r4,HID0
+	stw	r4,SL_HID0(r1)
+
+	/* Set up stuff at address 0 */
+	lis	r5,wake_up@ha
+	addi	r5,r5,wake_up@l
+	tophys(r5,r5)
+	stw	r5,SL_PC(r1)
+	lis	r4,KERNELBASE@h
+	tophys(r5,r1)
+	addi	r5,r5,SL_PC
+	lis	r6,MAGIC@ha
+	addi	r6,r6,MAGIC@l
+	stw	r5,0(r4)
+	stw	r6,4(r4)
+
+/*
+ * Flush the L1 data cache by reading the first 64kB of RAM
+ * and then flushing the same area with the dcbf instruction.
+ * The L2 cache has already been disabled.
+ */
+	li	r4,0x0800	/* 64kB / 32B */
+	mtctr	r4
+	lis	r4,KERNELBASE@h
+1:
+	lwz	r0,0(r4)
+	addi	r4,r4,0x0020		/* Go to start of next cache line */
+	bdnz	1b
+	sync
+	
+	li	r4,0x0800	/* 64k */
+	mtctr	r4
+	lis	r4,KERNELBASE@h
+1:
+	dcbf	r0,r4
+	addi	r4,r4,0x0020	/* Go to start of next cache line */
+	bdnz	1b
+	sync
+
+/*
+ * Set the HID0 and MSR for sleep.
+ */
+	mfspr	r2,HID0
+	rlwinm	r2,r2,0,10,7	/* clear doze, nap */
+	oris	r2,r2,HID0_SLEEP@h
+	sync
+	mtspr	HID0,r2
+	sync
+	
+	mfmsr	r2
+	oris	r2,r2,MSR_POW@h
+1:	sync
+	mtmsr	r2
+	isync
+	b	1b
+
+/* 
+ * Here is the resume code.
+ * r1 has the physical address of SL_PC(sp).
+ */
+	
+wake_up:
+	/* Restore the HID0 register.  This turns on the L1 caches. */
+	subi	r1,r1,SL_PC
+	lwz	r3,SL_HID0(r1)
+	sync
+	isync
+	mtspr	HID0,r3
+	sync
+
+	/* Restore the kernel's segment registers, the
+	   BATs, and SDR1.  Then we can turn on the MMU. */
+	li	r0,16		/* load up segment register values */
+	mtctr	r0		/* for context 0 */
+	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
+	li	r4,0
+3:	mtsrin	r3,r4
+	addi	r3,r3,1		/* increment VSID */
+	addis	r4,r4,0x1000	/* address of next segment */
+	bdnz	3b
+	
+	lwz	r4,SL_SDR1(r1)
+	mtsdr1	r4
+	lwz	r4,SL_SPRG0(r1)
+	mtsprg	0,r4
+	lwz	r4,SL_SPRG0+4(r1)
+	mtsprg	1,r4
+	lwz	r4,SL_SPRG0+8(r1)
+	mtsprg	2,r4
+	lwz	r4,SL_SPRG0+12(r1)
+	mtsprg	3,r4
+
+	lwz	r4,SL_DBAT0(r1)
+	mtdbatu	0,r4
+	lwz	r4,SL_DBAT0+4(r1)
+	mtdbatl	0,r4
+	lwz	r4,SL_DBAT1(r1)
+	mtdbatu	1,r4
+	lwz	r4,SL_DBAT1+4(r1)
+	mtdbatl	1,r4
+	lwz	r4,SL_DBAT2(r1)
+	mtdbatu	2,r4
+	lwz	r4,SL_DBAT2+4(r1)
+	mtdbatl	2,r4
+	lwz	r4,SL_DBAT3(r1)
+	mtdbatu	3,r4
+	lwz	r4,SL_DBAT3+4(r1)
+	mtdbatl	3,r4
+	lwz	r4,SL_IBAT0(r1)
+	mtibatu	0,r4
+	lwz	r4,SL_IBAT0+4(r1)
+	mtibatl	0,r4
+	lwz	r4,SL_IBAT1(r1)
+	mtibatu	1,r4
+	lwz	r4,SL_IBAT1+4(r1)
+	mtibatl	1,r4
+	lwz	r4,SL_IBAT2(r1)
+	mtibatu	2,r4
+	lwz	r4,SL_IBAT2+4(r1)
+	mtibatl	2,r4
+	lwz	r4,SL_IBAT3(r1)
+	mtibatu	3,r4
+	lwz	r4,SL_IBAT3+4(r1)
+	mtibatl	3,r4
+
+	/* restore the MSR and turn on the MMU */
+	lwz	r3,SL_MSR(r1)
+	bl	turn_on_mmu	
+
+	/* get back the stack pointer */
+	tovirt(r1,r1)
+
+	/* Restore TB */
+	lwz	r3,SL_TB(r1)
+	lwz	r4,SL_TB+4(r1)
+	mttbu	r3
+	mttbl	r4
+
+	/* Restore the callee-saved registers and return */
+	lwz	r2,SL_R2(r1)
+	lmw	r12,SL_R12(r1)
+	addi	r1,r1,SL_SIZE
+	lwz	r0,4(r1)
+	mtlr	r0
+	blr
+
+turn_on_mmu:
+	mflr	r4
+	tovirt(r4,r4)
+	mtsrr0	r4
+	mtsrr1	r3
+	sync
+	rfi
diff -urN linux-2.2.12-pre6/arch/ppc/kernel/time.c linux-2.2.12-pre7/arch/ppc/kernel/time.c
--- linux-2.2.12-pre6/arch/ppc/kernel/time.c	1999-06-04 13:30:47.000000000 -0700
+++ linux-2.2.12-pre7/arch/ppc/kernel/time.c	2003-08-15 15:07:07.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- * $Id: time.c,v 1.47.2.1 1999/05/29 19:10:23 cort Exp $
+ * $Id: time.c,v 1.47.2.2 1999/08/14 21:45:49 cort Exp $
  * Common time routines among all ppc machines.
  *
  * Written by Cort Dougan (cort@cs.nmt.edu) to merge
@@ -110,15 +110,14 @@
 			/*
 			 * update the rtc when needed
 			 */
-			if ( xtime.tv_sec > last_rtc_update + 660 )
+			if ( (time_status & STA_UNSYNC) &&
+			     (xtime.tv_sec > last_rtc_update + 660) )
 			{
-				if (ppc_md.set_rtc_time(xtime.tv_sec) == 0) {
+				if (ppc_md.set_rtc_time(xtime.tv_sec) == 0)
 					last_rtc_update = xtime.tv_sec;
-				}
-				else {
+				else
 					/* do it again in 60 s */
 					last_rtc_update = xtime.tv_sec - 60;
-				}
 			}
 		}
 	}
@@ -168,7 +167,6 @@
 	int frac_tick;
 	
 	last_rtc_update = 0; /* so the rtc gets updated soon */
-	
 	frac_tick = tv->tv_usec % (1000000 / HZ);
 	save_flags(flags);
 	cli();
@@ -332,6 +330,3 @@
 	 */
 	GregorianDay(tm);
 }
-
-
-
diff -urN linux-2.2.12-pre6/arch/ppc/xmon/adb.c linux-2.2.12-pre7/arch/ppc/xmon/adb.c
--- linux-2.2.12-pre6/arch/ppc/xmon/adb.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/xmon/adb.c	2003-08-15 15:07:07.000000000 -0700
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include "nonstdio.h"
+#include "privinst.h"
+
+#define scanhex	xmon_scanhex
+#define skipbl	xmon_skipbl
+
+#define ADB_B		(*(volatile unsigned char *)0xf3016000)
+#define ADB_SR		(*(volatile unsigned char *)0xf3017400)
+#define ADB_ACR		(*(volatile unsigned char *)0xf3017600)
+#define ADB_IFR		(*(volatile unsigned char *)0xf3017a00)
+
+static inline void eieio(void) { asm volatile ("eieio" : :); }
+
+#define N_ADB_LOG	1000
+struct adb_log {
+    unsigned char b;
+    unsigned char ifr;
+    unsigned char acr;
+    unsigned int time;
+} adb_log[N_ADB_LOG];
+int n_adb_log;
+
+void
+init_adb_log(void)
+{
+    adb_log[0].b = ADB_B;
+    adb_log[0].ifr = ADB_IFR;
+    adb_log[0].acr = ADB_ACR;
+    adb_log[0].time = get_dec();
+    n_adb_log = 0;
+}
+
+void
+dump_adb_log(void)
+{
+    unsigned t, t0;
+    struct adb_log *ap;
+    int i;
+
+    ap = adb_log;
+    t0 = ap->time;
+    for (i = 0; i <= n_adb_log; ++i, ++ap) {
+	t = t0 - ap->time;
+	printf("b=%x ifr=%x acr=%x at %d.%.7d\n", ap->b, ap->ifr, ap->acr,
+	       t / 1000000000, (t % 1000000000) / 100);
+    }
+}
+
+void
+adb_chklog(void)
+{
+    struct adb_log *ap = &adb_log[n_adb_log + 1];
+
+    ap->b = ADB_B;
+    ap->ifr = ADB_IFR;
+    ap->acr = ADB_ACR;
+    if (ap->b != ap[-1].b || (ap->ifr & 4) != (ap[-1].ifr & 4)
+	|| ap->acr != ap[-1].acr) {
+	ap->time = get_dec();
+	++n_adb_log;
+    }
+}
+
+int
+adb_bitwait(int bmask, int bval, int fmask, int fval)
+{
+    int i;
+    struct adb_log *ap;
+
+    for (i = 10000; i > 0; --i) {
+	adb_chklog();
+	ap = &adb_log[n_adb_log];
+	if ((ap->b & bmask) == bval && (ap->ifr & fmask) == fval)
+	    return 0;
+    }
+    return -1;
+}
+
+int
+adb_wait(void)
+{
+    if (adb_bitwait(0, 0, 4, 4) < 0) {
+	printf("adb: ready wait timeout\n");
+	return -1;
+    }
+    return 0;
+}
+
+void
+adb_readin(void)
+{
+    int i, j;
+    unsigned char d[64];
+
+    if (ADB_B & 8) {
+	printf("ADB_B: %x\n", ADB_B);
+	return;
+    }
+    i = 0;
+    adb_wait();
+    j = ADB_SR;
+    eieio();
+    ADB_B &= ~0x20;
+    eieio();
+    for (;;) {
+	if (adb_wait() < 0)
+	    break;
+	d[i++] = ADB_SR;
+	eieio();
+	if (ADB_B & 8)
+	    break;
+	ADB_B ^= 0x10;
+	eieio();
+    }
+    ADB_B |= 0x30;
+    if (adb_wait() == 0)
+	j = ADB_SR;
+    for (j = 0; j < i; ++j)
+	printf("%.2x ", d[j]);
+    printf("\n");
+}
+
+int
+adb_write(unsigned char *d, int i)
+{
+    int j;
+    unsigned x;
+
+    if ((ADB_B & 8) == 0) {
+	printf("r: ");
+	adb_readin();
+    }
+    for (;;) {
+	ADB_ACR = 0x1c;
+	eieio();
+	ADB_SR = d[0];
+	eieio();
+	ADB_B &= ~0x20;
+	eieio();
+	if (ADB_B & 8)
+	    break;
+	ADB_ACR = 0xc;
+	eieio();
+	ADB_B |= 0x20;
+	eieio();
+	adb_readin();
+    }
+    adb_wait();
+    for (j = 1; j < i; ++j) {
+	ADB_SR = d[j];
+	eieio();
+	ADB_B ^= 0x10;
+	eieio();
+	if (adb_wait() < 0)
+	    break;
+    }
+    ADB_ACR = 0xc;
+    eieio();
+    x = ADB_SR;
+    eieio();
+    ADB_B |= 0x30;
+    return j;
+}
+
+void
+adbcmds(void)
+{
+    char cmd;
+    unsigned rtcu, rtcl, dec, pdec, x;
+    int i, j;
+    unsigned char d[64];
+
+    cmd = skipbl();
+    switch (cmd) {
+    case 't':
+	for (;;) {
+	    rtcl = get_rtcl();
+	    rtcu = get_rtcu();
+	    dec = get_dec();
+	    printf("rtc u=%u l=%u dec=%x (%d = %d.%.7d)\n",
+		   rtcu, rtcl, dec, pdec - dec, (pdec - dec) / 1000000000,
+		   ((pdec - dec) % 1000000000) / 100);
+	    pdec = dec;
+	    if (cmd == 'x')
+		break;
+	    while (xmon_read(stdin, &cmd, 1) != 1)
+		;
+	}
+	break;
+    case 'r':
+	init_adb_log();
+	while (adb_bitwait(8, 0, 0, 0) == 0)
+	    adb_readin();
+	break;
+    case 'w':
+	i = 0;
+	while (scanhex(&x))
+	    d[i++] = x;
+	init_adb_log();
+	j = adb_write(d, i);
+	printf("sent %d bytes\n", j);
+	while (adb_bitwait(8, 0, 0, 0) == 0)
+	    adb_readin();
+	break;
+    case 'l':
+	dump_adb_log();
+	break;
+    }
+}
diff -urN linux-2.2.12-pre6/arch/ppc/xmon/ansidecl.h linux-2.2.12-pre7/arch/ppc/xmon/ansidecl.h
--- linux-2.2.12-pre6/arch/ppc/xmon/ansidecl.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/xmon/ansidecl.h	2003-08-15 15:07:07.000000000 -0700
@@ -0,0 +1,141 @@
+/* ANSI and traditional C compatability macros
+   Copyright 1991, 1992 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+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.  */
+
+/* ANSI and traditional C compatibility macros
+
+   ANSI C is assumed if __STDC__ is #defined.
+
+   Macro	ANSI C definition	Traditional C definition
+   -----	---- - ----------	----------- - ----------
+   PTR		`void *'		`char *'
+   LONG_DOUBLE	`long double'		`double'
+   VOLATILE	`volatile'		`'
+   SIGNED	`signed'		`'
+   PTRCONST	`void *const'		`char *'
+   ANSI_PROTOTYPES  1			not defined
+
+   CONST is also defined, but is obsolete.  Just use const.
+
+   DEFUN (name, arglist, args)
+
+	Defines function NAME.
+
+	ARGLIST lists the arguments, separated by commas and enclosed in
+	parentheses.  ARGLIST becomes the argument list in traditional C.
+
+	ARGS list the arguments with their types.  It becomes a prototype in
+	ANSI C, and the type declarations in traditional C.  Arguments should
+	be separated with `AND'.  For functions with a variable number of
+	arguments, the last thing listed should be `DOTS'.
+
+   DEFUN_VOID (name)
+
+	Defines a function NAME, which takes no arguments.
+
+   obsolete --     EXFUN (name, (prototype))	-- obsolete.
+
+	Replaced by PARAMS.  Do not use; will disappear someday soon.
+	Was used in external function declarations.
+	In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in
+	parentheses).  In traditional C it is `NAME()'.
+	For a function that takes no arguments, PROTOTYPE should be `(void)'.
+
+    PARAMS ((args))
+
+	We could use the EXFUN macro to handle prototype declarations, but
+	the name is misleading and the result is ugly.  So we just define a
+	simple macro to handle the parameter lists, as in:
+
+	      static int foo PARAMS ((int, char));
+
+	This produces:  `static int foo();' or `static int foo (int, char);'
+
+	EXFUN would have done it like this:
+
+	      static int EXFUN (foo, (int, char));
+
+	but the function is not external...and it's hard to visually parse
+	the function name out of the mess.   EXFUN should be considered
+	obsolete; new code should be written to use PARAMS.
+
+    For example:
+	extern int printf PARAMS ((CONST char *format DOTS));
+	int DEFUN(fprintf, (stream, format),
+		  FILE *stream AND CONST char *format DOTS) { ... }
+	void DEFUN_VOID(abort) { ... }
+*/
+
+#ifndef	_ANSIDECL_H
+
+#define	_ANSIDECL_H	1
+
+
+/* Every source file includes this file,
+   so they will all get the switch for lint.  */
+/* LINTLIBRARY */
+
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32)
+/* All known AIX compilers implement these things (but don't always
+   define __STDC__).  The RISC/OS MIPS compiler defines these things
+   in SVR4 mode, but does not define __STDC__.  */
+
+#define	PTR		void *
+#define	PTRCONST	void *CONST
+#define	LONG_DOUBLE	long double
+
+#define	AND		,
+#define	NOARGS		void
+#define	CONST		const
+#define	VOLATILE	volatile
+#define	SIGNED		signed
+#define	DOTS		, ...
+
+#define	EXFUN(name, proto)		name proto
+#define	DEFUN(name, arglist, args)	name(args)
+#define	DEFUN_VOID(name)		name(void)
+
+#define PROTO(type, name, arglist)	type name arglist
+#define PARAMS(paramlist)		paramlist
+#define ANSI_PROTOTYPES			1
+
+#else	/* Not ANSI C.  */
+
+#define	PTR		char *
+#define	PTRCONST	PTR
+#define	LONG_DOUBLE	double
+
+#define	AND		;
+#define	NOARGS
+#define	CONST
+#ifndef const /* some systems define it in header files for non-ansi mode */
+#define	const
+#endif
+#define	VOLATILE
+#define	SIGNED
+#define	DOTS
+
+#define	EXFUN(name, proto)		name()
+#define	DEFUN(name, arglist, args)	name arglist args;
+#define	DEFUN_VOID(name)		name()
+#define PROTO(type, name, arglist) type name ()
+#define PARAMS(paramlist)		()
+
+#endif	/* ANSI C.  */
+
+#endif	/* ansidecl.h	*/
diff -urN linux-2.2.12-pre6/arch/ppc/xmon/Makefile linux-2.2.12-pre7/arch/ppc/xmon/Makefile
--- linux-2.2.12-pre6/arch/ppc/xmon/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/xmon/Makefile	2003-08-15 15:07:07.000000000 -0700
@@ -0,0 +1,6 @@
+# Makefile for xmon
+
+O_TARGET = x.o
+O_OBJS = start.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.2.12-pre6/arch/ppc/xmon/nonstdio.h linux-2.2.12-pre7/arch/ppc/xmon/nonstdio.h
--- linux-2.2.12-pre6/arch/ppc/xmon/nonstdio.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/xmon/nonstdio.h	2003-08-15 15:07:07.000000000 -0700
@@ -0,0 +1,22 @@
+typedef int	FILE;
+extern FILE *xmon_stdin, *xmon_stdout;
+#define EOF	(-1)
+#define stdin	xmon_stdin
+#define stdout	xmon_stdout
+#define printf	xmon_printf
+#define fprintf	xmon_fprintf
+#define fputs	xmon_fputs
+#define fgets	xmon_fgets
+#define putchar	xmon_putchar
+#define getchar	xmon_getchar
+#define putc	xmon_putc
+#define getc	xmon_getc
+#define fopen(n, m)	NULL
+#define fflush(f)	do {} while (0)
+#define fclose(f)	do {} while (0)
+extern char *fgets(char *, int, void *);
+extern void xmon_printf(const char *, ...);
+extern void xmon_fprintf(void *, const char *, ...);
+extern void xmon_sprintf(char *, const char *, ...);
+
+#define perror(s)	printf("%s: no files!\n", (s))
diff -urN linux-2.2.12-pre6/arch/ppc/xmon/ppc-dis.c linux-2.2.12-pre7/arch/ppc/xmon/ppc-dis.c
--- linux-2.2.12-pre6/arch/ppc/xmon/ppc-dis.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/xmon/ppc-dis.c	2003-08-15 15:07:07.000000000 -0700
@@ -0,0 +1,190 @@
+/* ppc-dis.c -- Disassemble PowerPC instructions
+   Copyright 1994 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them 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.
+
+GDB, GAS, and the 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 file; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "nonstdio.h"
+#include "ansidecl.h"
+#include "ppc.h"
+
+static int print_insn_powerpc PARAMS ((FILE *, unsigned long insn,
+				       unsigned memaddr, int dialect));
+
+extern void print_address PARAMS((unsigned memaddr));
+
+/* Print a big endian PowerPC instruction.  For convenience, also
+   disassemble instructions supported by the Motorola PowerPC 601.  */
+
+int
+print_insn_big_powerpc (FILE *out, unsigned long insn, unsigned memaddr)
+{
+  return print_insn_powerpc (out, insn, memaddr,
+			     PPC_OPCODE_PPC | PPC_OPCODE_601);
+}
+
+/* Print a PowerPC or POWER instruction.  */
+
+static int
+print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
+		    int dialect)
+{
+  const struct powerpc_opcode *opcode;
+  const struct powerpc_opcode *opcode_end;
+  unsigned long op;
+
+  /* Get the major opcode of the instruction.  */
+  op = PPC_OP (insn);
+
+  /* Find the first match in the opcode table.  We could speed this up
+     a bit by doing a binary search on the major opcode.  */
+  opcode_end = powerpc_opcodes + powerpc_num_opcodes;
+  for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
+    {
+      unsigned long table_op;
+      const unsigned char *opindex;
+      const struct powerpc_operand *operand;
+      int invalid;
+      int need_comma;
+      int need_paren;
+
+      table_op = PPC_OP (opcode->opcode);
+      if (op < table_op)
+		break;
+      if (op > table_op)
+		continue;
+
+      if ((insn & opcode->mask) != opcode->opcode
+	  || (opcode->flags & dialect) == 0)
+		continue;
+
+      /* Make two passes over the operands.  First see if any of them
+		 have extraction functions, and, if they do, make sure the
+		 instruction is valid.  */
+      invalid = 0;
+      for (opindex = opcode->operands; *opindex != 0; opindex++)
+		{
+		  operand = powerpc_operands + *opindex;
+		  if (operand->extract)
+		    (*operand->extract) (insn, &invalid);
+		}
+      if (invalid)
+		continue;
+
+      /* The instruction is valid.  */
+      fprintf(out, "%s", opcode->name);
+      if (opcode->operands[0] != 0)
+		fprintf(out, "\t");
+
+      /* Now extract and print the operands.  */
+      need_comma = 0;
+      need_paren = 0;
+      for (opindex = opcode->operands; *opindex != 0; opindex++)
+		{
+		  long value;
+
+		  operand = powerpc_operands + *opindex;
+
+		  /* Operands that are marked FAKE are simply ignored.  We
+		     already made sure that the extract function considered
+		     the instruction to be valid.  */
+		  if ((operand->flags & PPC_OPERAND_FAKE) != 0)
+		    continue;
+
+		  /* Extract the value from the instruction.  */
+		  if (operand->extract)
+		    value = (*operand->extract) (insn, (int *) 0);
+		  else
+		    {
+		      value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
+		      if ((operand->flags & PPC_OPERAND_SIGNED) != 0
+			  && (value & (1 << (operand->bits - 1))) != 0)
+			value -= 1 << operand->bits;
+		    }
+
+		  /* If the operand is optional, and the value is zero, don't
+		     print anything.  */
+		  if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
+		      && (operand->flags & PPC_OPERAND_NEXT) == 0
+		      && value == 0)
+		    continue;
+
+		  if (need_comma)
+		    {
+		      fprintf(out, ",");
+		      need_comma = 0;
+		    }
+
+		  /* Print the operand as directed by the flags.  */
+		  if ((operand->flags & PPC_OPERAND_GPR) != 0)
+		    fprintf(out, "r%ld", value);
+		  else if ((operand->flags & PPC_OPERAND_FPR) != 0)
+		    fprintf(out, "f%ld", value);
+		  else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
+		    print_address (memaddr + value);
+		  else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
+		    print_address (value & 0xffffffff);
+		  else if ((operand->flags & PPC_OPERAND_CR) == 0
+			   || (dialect & PPC_OPCODE_PPC) == 0)
+		    fprintf(out, "%ld", value);
+		  else
+		    {
+		      if (operand->bits == 3)
+				fprintf(out, "cr%d", value);
+		      else
+			{
+			  static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
+			  int cr;
+			  int cc;
+
+			  cr = value >> 2;
+			  if (cr != 0)
+			    fprintf(out, "4*cr%d", cr);
+			  cc = value & 3;
+			  if (cc != 0)
+			    {
+			      if (cr != 0)
+					fprintf(out, "+");
+			      fprintf(out, "%s", cbnames[cc]);
+			    }
+			}
+	    }
+
+	  if (need_paren)
+	    {
+	      fprintf(out, ")");
+	      need_paren = 0;
+	    }
+
+	  if ((operand->flags & PPC_OPERAND_PARENS) == 0)
+	    need_comma = 1;
+	  else
+	    {
+	      fprintf(out, "(");
+	      need_paren = 1;
+	    }
+	}
+
+      /* We have found and printed an instruction; return.  */
+      return 4;
+    }
+
+  /* We could not find a match.  */
+  fprintf(out, ".long 0x%lx", insn);
+
+  return 4;
+}
diff -urN linux-2.2.12-pre6/arch/ppc/xmon/ppc.h linux-2.2.12-pre7/arch/ppc/xmon/ppc.h
--- linux-2.2.12-pre6/arch/ppc/xmon/ppc.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/xmon/ppc.h	2003-08-15 15:07:07.000000000 -0700
@@ -0,0 +1,240 @@
+/* ppc.h -- Header file for PowerPC opcode table
+   Copyright 1994 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+1, or (at your option) any later version.
+
+GDB, GAS, and the 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 file; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef PPC_H
+#define PPC_H
+
+/* The opcode table is an array of struct powerpc_opcode.  */
+
+struct powerpc_opcode
+{
+  /* The opcode name.  */
+  const char *name;
+
+  /* The opcode itself.  Those bits which will be filled in with
+     operands are zeroes.  */
+  unsigned long opcode;
+
+  /* The opcode mask.  This is used by the disassembler.  This is a
+     mask containing ones indicating those bits which must match the
+     opcode field, and zeroes indicating those bits which need not
+     match (and are presumably filled in by operands).  */
+  unsigned long mask;
+
+  /* One bit flags for the opcode.  These are used to indicate which
+     specific processors support the instructions.  The defined values
+     are listed below.  */
+  unsigned long flags;
+
+  /* An array of operand codes.  Each code is an index into the
+     operand table.  They appear in the order which the operands must
+     appear in assembly code, and are terminated by a zero.  */
+  unsigned char operands[8];
+};
+
+/* The table itself is sorted by major opcode number, and is otherwise
+   in the order in which the disassembler should consider
+   instructions.  */
+extern const struct powerpc_opcode powerpc_opcodes[];
+extern const int powerpc_num_opcodes;
+
+/* Values defined for the flags field of a struct powerpc_opcode.  */
+
+/* Opcode is defined for the PowerPC architecture.  */
+#define PPC_OPCODE_PPC (01)
+
+/* Opcode is defined for the POWER (RS/6000) architecture.  */
+#define PPC_OPCODE_POWER (02)
+
+/* Opcode is defined for the POWER2 (Rios 2) architecture.  */
+#define PPC_OPCODE_POWER2 (04)
+
+/* Opcode is only defined on 32 bit architectures.  */
+#define PPC_OPCODE_32 (010)
+
+/* Opcode is only defined on 64 bit architectures.  */
+#define PPC_OPCODE_64 (020)
+
+/* Opcode is supported by the Motorola PowerPC 601 processor.  The 601
+   is assumed to support all PowerPC (PPC_OPCODE_PPC) instructions,
+   but it also supports many additional POWER instructions.  */
+#define PPC_OPCODE_601 (040)
+
+/* A macro to extract the major opcode from an instruction.  */
+#define PPC_OP(i) (((i) >> 26) & 0x3f)
+
+/* The operands table is an array of struct powerpc_operand.  */
+
+struct powerpc_operand
+{
+  /* The number of bits in the operand.  */
+  int bits;
+
+  /* How far the operand is left shifted in the instruction.  */
+  int shift;
+
+  /* Insertion function.  This is used by the assembler.  To insert an
+     operand value into an instruction, check this field.
+
+     If it is NULL, execute
+         i |= (op & ((1 << o->bits) - 1)) << o->shift;
+     (i is the instruction which we are filling in, o is a pointer to
+     this structure, and op is the opcode value; this assumes twos
+     complement arithmetic).
+
+     If this field is not NULL, then simply call it with the
+     instruction and the operand value.  It will return the new value
+     of the instruction.  If the ERRMSG argument is not NULL, then if
+     the operand value is illegal, *ERRMSG will be set to a warning
+     string (the operand will be inserted in any case).  If the
+     operand value is legal, *ERRMSG will be unchanged (most operands
+     can accept any value).  */
+  unsigned long (*insert) PARAMS ((unsigned long instruction, long op,
+				   const char **errmsg));
+
+  /* Extraction function.  This is used by the disassembler.  To
+     extract this operand type from an instruction, check this field.
+
+     If it is NULL, compute
+         op = ((i) >> o->shift) & ((1 << o->bits) - 1);
+	 if ((o->flags & PPC_OPERAND_SIGNED) != 0
+	     && (op & (1 << (o->bits - 1))) != 0)
+	   op -= 1 << o->bits;
+     (i is the instruction, o is a pointer to this structure, and op
+     is the result; this assumes twos complement arithmetic).
+
+     If this field is not NULL, then simply call it with the
+     instruction value.  It will return the value of the operand.  If
+     the INVALID argument is not NULL, *INVALID will be set to
+     non-zero if this operand type can not actually be extracted from
+     this operand (i.e., the instruction does not match).  If the
+     operand is valid, *INVALID will not be changed.  */
+  long (*extract) PARAMS ((unsigned long instruction, int *invalid));
+
+  /* One bit syntax flags.  */
+  unsigned long flags;
+};
+
+/* Elements in the table are retrieved by indexing with values from
+   the operands field of the powerpc_opcodes table.  */
+
+extern const struct powerpc_operand powerpc_operands[];
+
+/* Values defined for the flags field of a struct powerpc_operand.  */
+
+/* This operand takes signed values.  */
+#define PPC_OPERAND_SIGNED (01)
+
+/* This operand takes signed values, but also accepts a full positive
+   range of values when running in 32 bit mode.  That is, if bits is
+   16, it takes any value from -0x8000 to 0xffff.  In 64 bit mode,
+   this flag is ignored.  */
+#define PPC_OPERAND_SIGNOPT (02)
+
+/* This operand does not actually exist in the assembler input.  This
+   is used to support extended mnemonics such as mr, for which two
+   operands fields are identical.  The assembler should call the
+   insert function with any op value.  The disassembler should call
+   the extract function, ignore the return value, and check the value
+   placed in the valid argument.  */
+#define PPC_OPERAND_FAKE (04)
+
+/* The next operand should be wrapped in parentheses rather than
+   separated from this one by a comma.  This is used for the load and
+   store instructions which want their operands to look like
+       reg,displacement(reg)
+   */
+#define PPC_OPERAND_PARENS (010)
+
+/* This operand may use the symbolic names for the CR fields, which
+   are
+       lt  0	gt  1	eq  2	so  3	un  3
+       cr0 0	cr1 1	cr2 2	cr3 3
+       cr4 4	cr5 5	cr6 6	cr7 7
+   These may be combined arithmetically, as in cr2*4+gt.  These are
+   only supported on the PowerPC, not the POWER.  */
+#define PPC_OPERAND_CR (020)
+
+/* This operand names a register.  The disassembler uses this to print
+   register names with a leading 'r'.  */
+#define PPC_OPERAND_GPR (040)
+
+/* This operand names a floating point register.  The disassembler
+   prints these with a leading 'f'.  */
+#define PPC_OPERAND_FPR (0100)
+
+/* This operand is a relative branch displacement.  The disassembler
+   prints these symbolically if possible.  */
+#define PPC_OPERAND_RELATIVE (0200)
+
+/* This operand is an absolute branch address.  The disassembler
+   prints these symbolically if possible.  */
+#define PPC_OPERAND_ABSOLUTE (0400)
+
+/* This operand is optional, and is zero if omitted.  This is used for
+   the optional BF and L fields in the comparison instructions.  The
+   assembler must count the number of operands remaining on the line,
+   and the number of operands remaining for the opcode, and decide
+   whether this operand is present or not.  The disassembler should
+   print this operand out only if it is not zero.  */
+#define PPC_OPERAND_OPTIONAL (01000)
+
+/* This flag is only used with PPC_OPERAND_OPTIONAL.  If this operand
+   is omitted, then for the next operand use this operand value plus
+   1, ignoring the next operand field for the opcode.  This wretched
+   hack is needed because the Power rotate instructions can take
+   either 4 or 5 operands.  The disassembler should print this operand
+   out regardless of the PPC_OPERAND_OPTIONAL field.  */
+#define PPC_OPERAND_NEXT (02000)
+
+/* This operand should be regarded as a negative number for the
+   purposes of overflow checking (i.e., the normal most negative
+   number is disallowed and one more than the normal most positive
+   number is allowed).  This flag will only be set for a signed
+   operand.  */
+#define PPC_OPERAND_NEGATIVE (04000)
+
+/* The POWER and PowerPC assemblers use a few macros.  We keep them
+   with the operands table for simplicity.  The macro table is an
+   array of struct powerpc_macro.  */
+
+struct powerpc_macro
+{
+  /* The macro name.  */
+  const char *name;
+
+  /* The number of operands the macro takes.  */
+  unsigned int operands;
+
+  /* One bit flags for the opcode.  These are used to indicate which
+     specific processors support the instructions.  The values are the
+     same as those for the struct powerpc_opcode flags field.  */
+  unsigned long flags;
+
+  /* A format string to turn the macro into a normal instruction.
+     Each %N in the string is replaced with operand number N (zero
+     based).  */
+  const char *format;
+};
+
+extern const struct powerpc_macro powerpc_macros[];
+extern const int powerpc_num_macros;
+
+#endif /* PPC_H */
diff -urN linux-2.2.12-pre6/arch/ppc/xmon/ppc-opc.c linux-2.2.12-pre7/arch/ppc/xmon/ppc-opc.c
--- linux-2.2.12-pre6/arch/ppc/xmon/ppc-opc.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/xmon/ppc-opc.c	2003-08-15 15:07:07.000000000 -0700
@@ -0,0 +1,2816 @@
+/* ppc-opc.c -- PowerPC opcode list
+   Copyright 1994 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them 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.
+
+GDB, GAS, and the 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 file; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include <linux/posix_types.h>
+#include "ansidecl.h"
+#include "ppc.h"
+
+/* This file holds the PowerPC opcode table.  The opcode table
+   includes almost all of the extended instruction mnemonics.  This
+   permits the disassembler to use them, and simplifies the assembler
+   logic, at the cost of increasing the table size.  The table is
+   strictly constant data, so the compiler should be able to put it in
+   the .text section.
+
+   This file also holds the operand table.  All knowledge about
+   inserting operands into instructions and vice-versa is kept in this
+   file.  */
+
+/* Local insertion and extraction functions.  */
+
+static unsigned long insert_bat PARAMS ((unsigned long, long, const char **));
+static long extract_bat PARAMS ((unsigned long, int *));
+static unsigned long insert_bba PARAMS ((unsigned long, long, const char **));
+static long extract_bba PARAMS ((unsigned long, int *));
+static unsigned long insert_bd PARAMS ((unsigned long, long, const char **));
+static long extract_bd PARAMS ((unsigned long, int *));
+static unsigned long insert_bdm PARAMS ((unsigned long, long, const char **));
+static long extract_bdm PARAMS ((unsigned long, int *));
+static unsigned long insert_bdp PARAMS ((unsigned long, long, const char **));
+static long extract_bdp PARAMS ((unsigned long, int *));
+static unsigned long insert_bo PARAMS ((unsigned long, long, const char **));
+static long extract_bo PARAMS ((unsigned long, int *));
+static unsigned long insert_boe PARAMS ((unsigned long, long, const char **));
+static long extract_boe PARAMS ((unsigned long, int *));
+static unsigned long insert_ds PARAMS ((unsigned long, long, const char **));
+static long extract_ds PARAMS ((unsigned long, int *));
+static unsigned long insert_li PARAMS ((unsigned long, long, const char **));
+static long extract_li PARAMS ((unsigned long, int *));
+static unsigned long insert_mbe PARAMS ((unsigned long, long, const char **));
+static long extract_mbe PARAMS ((unsigned long, int *));
+static unsigned long insert_mb6 PARAMS ((unsigned long, long, const char **));
+static long extract_mb6 PARAMS ((unsigned long, int *));
+static unsigned long insert_nb PARAMS ((unsigned long, long, const char **));
+static long extract_nb PARAMS ((unsigned long, int *));
+static unsigned long insert_nsi PARAMS ((unsigned long, long, const char **));
+static long extract_nsi PARAMS ((unsigned long, int *));
+static unsigned long insert_ral PARAMS ((unsigned long, long, const char **));
+static unsigned long insert_ram PARAMS ((unsigned long, long, const char **));
+static unsigned long insert_ras PARAMS ((unsigned long, long, const char **));
+static unsigned long insert_rbs PARAMS ((unsigned long, long, const char **));
+static long extract_rbs PARAMS ((unsigned long, int *));
+static unsigned long insert_sh6 PARAMS ((unsigned long, long, const char **));
+static long extract_sh6 PARAMS ((unsigned long, int *));
+static unsigned long insert_spr PARAMS ((unsigned long, long, const char **));
+static long extract_spr PARAMS ((unsigned long, int *));
+static unsigned long insert_tbr PARAMS ((unsigned long, long, const char **));
+static long extract_tbr PARAMS ((unsigned long, int *));
+
+/* The operands table.
+
+   The fields are bits, shift, signed, insert, extract, flags.  */
+
+const struct powerpc_operand powerpc_operands[] =
+{
+  /* The zero index is used to indicate the end of the list of
+     operands.  */
+#define UNUSED (0)
+  { 0, 0, 0, 0, 0 },
+
+  /* The BA field in an XL form instruction.  */
+#define BA (1)
+#define BA_MASK (0x1f << 16)
+  { 5, 16, 0, 0, PPC_OPERAND_CR },
+
+  /* The BA field in an XL form instruction when it must be the same
+     as the BT field in the same instruction.  */
+#define BAT (2)
+  { 5, 16, insert_bat, extract_bat, PPC_OPERAND_FAKE },
+
+  /* The BB field in an XL form instruction.  */
+#define BB (3)
+#define BB_MASK (0x1f << 11)
+  { 5, 11, 0, 0, PPC_OPERAND_CR },
+
+  /* The BB field in an XL form instruction when it must be the same
+     as the BA field in the same instruction.  */
+#define BBA (4)
+  { 5, 11, insert_bba, extract_bba, PPC_OPERAND_FAKE },
+
+  /* The BD field in a B form instruction.  The lower two bits are
+     forced to zero.  */
+#define BD (5)
+  { 16, 0, insert_bd, extract_bd, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+  /* The BD field in a B form instruction when absolute addressing is
+     used.  */
+#define BDA (6)
+  { 16, 0, insert_bd, extract_bd, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+  /* The BD field in a B form instruction when the - modifier is used.
+     This sets the y bit of the BO field appropriately.  */
+#define BDM (7)
+  { 16, 0, insert_bdm, extract_bdm,
+      PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+  /* The BD field in a B form instruction when the - modifier is used
+     and absolute address is used.  */
+#define BDMA (8)
+  { 16, 0, insert_bdm, extract_bdm,
+      PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+  /* The BD field in a B form instruction when the + modifier is used.
+     This sets the y bit of the BO field appropriately.  */
+#define BDP (9)
+  { 16, 0, insert_bdp, extract_bdp,
+      PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+  /* The BD field in a B form instruction when the + modifier is used
+     and absolute addressing is used.  */
+#define BDPA (10)
+  { 16, 0, insert_bdp, extract_bdp,
+      PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+  /* The BF field in an X or XL form instruction.  */
+#define BF (11)
+  { 3, 23, 0, 0, PPC_OPERAND_CR },
+
+  /* An optional BF field.  This is used for comparison instructions,
+     in which an omitted BF field is taken as zero.  */
+#define OBF (12)
+  { 3, 23, 0, 0, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+
+  /* The BFA field in an X or XL form instruction.  */
+#define BFA (13)
+  { 3, 18, 0, 0, PPC_OPERAND_CR },
+
+  /* The BI field in a B form or XL form instruction.  */
+#define BI (14)
+#define BI_MASK (0x1f << 16)
+  { 5, 16, 0, 0, PPC_OPERAND_CR },
+
+  /* The BO field in a B form instruction.  Certain values are
+     illegal.  */
+#define BO (15)
+#define BO_MASK (0x1f << 21)
+  { 5, 21, insert_bo, extract_bo, 0 },
+
+  /* The BO field in a B form instruction when the + or - modifier is
+     used.  This is like the BO field, but it must be even.  */
+#define BOE (16)
+  { 5, 21, insert_boe, extract_boe, 0 },
+
+  /* The BT field in an X or XL form instruction.  */
+#define BT (17)
+  { 5, 21, 0, 0, PPC_OPERAND_CR },
+
+  /* The condition register number portion of the BI field in a B form
+     or XL form instruction.  This is used for the extended
+     conditional branch mnemonics, which set the lower two bits of the
+     BI field.  This field is optional.  */
+#define CR (18)
+  { 3, 18, 0, 0, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+
+  /* The D field in a D form instruction.  This is a displacement off
+     a register, and implies that the next operand is a register in
+     parentheses.  */
+#define D (19)
+  { 16, 0, 0, 0, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
+
+  /* The DS field in a DS form instruction.  This is like D, but the
+     lower two bits are forced to zero.  */
+#define DS (20)
+  { 16, 0, insert_ds, extract_ds, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
+
+  /* The FL1 field in a POWER SC form instruction.  */
+#define FL1 (21)
+  { 4, 12, 0, 0, 0 },
+
+  /* The FL2 field in a POWER SC form instruction.  */
+#define FL2 (22)
+  { 3, 2, 0, 0, 0 },
+
+  /* The FLM field in an XFL form instruction.  */
+#define FLM (23)
+  { 8, 17, 0, 0, 0 },
+
+  /* The FRA field in an X or A form instruction.  */
+#define FRA (24)
+#define FRA_MASK (0x1f << 16)
+  { 5, 16, 0, 0, PPC_OPERAND_FPR },
+
+  /* The FRB field in an X or A form instruction.  */
+#define FRB (25)
+#define FRB_MASK (0x1f << 11)
+  { 5, 11, 0, 0, PPC_OPERAND_FPR },
+
+  /* The FRC field in an A form instruction.  */
+#define FRC (26)
+#define FRC_MASK (0x1f << 6)
+  { 5, 6, 0, 0, PPC_OPERAND_FPR },
+
+  /* The FRS field in an X form instruction or the FRT field in a D, X
+     or A form instruction.  */
+#define FRS (27)
+#define FRT (FRS)
+  { 5, 21, 0, 0, PPC_OPERAND_FPR },
+
+  /* The FXM field in an XFX instruction.  */
+#define FXM (28)
+#define FXM_MASK (0xff << 12)
+  { 8, 12, 0, 0, 0 },
+
+  /* The L field in a D or X form instruction.  */
+#define L (29)
+  { 1, 21, 0, 0, PPC_OPERAND_OPTIONAL },
+
+  /* The LEV field in a POWER SC form instruction.  */
+#define LEV (30)
+  { 7, 5, 0, 0, 0 },
+
+  /* The LI field in an I form instruction.  The lower two bits are
+     forced to zero.  */
+#define LI (31)
+  { 26, 0, insert_li, extract_li, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+  /* The LI field in an I form instruction when used as an absolute
+     address.  */
+#define LIA (32)
+  { 26, 0, insert_li, extract_li, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+  /* The MB field in an M form instruction.  */
+#define MB (33)
+#define MB_MASK (0x1f << 6)
+  { 5, 6, 0, 0, 0 },
+
+  /* The ME field in an M form instruction.  */
+#define ME (34)
+#define ME_MASK (0x1f << 1)
+  { 5, 1, 0, 0, 0 },
+
+  /* The MB and ME fields in an M form instruction expressed a single
+     operand which is a bitmask indicating which bits to select.  This
+     is a two operand form using PPC_OPERAND_NEXT.  See the
+     description in opcode/ppc.h for what this means.  */
+#define MBE (35)
+  { 5, 6, 0, 0, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT },
+  { 32, 0, insert_mbe, extract_mbe, 0 },
+
+  /* The MB or ME field in an MD or MDS form instruction.  The high
+     bit is wrapped to the low end.  */
+#define MB6 (37)
+#define ME6 (MB6)
+#define MB6_MASK (0x3f << 5)
+  { 6, 5, insert_mb6, extract_mb6, 0 },
+
+  /* The NB field in an X form instruction.  The value 32 is stored as
+     0.  */
+#define NB (38)
+  { 6, 11, insert_nb, extract_nb, 0 },
+
+  /* The NSI field in a D form instruction.  This is the same as the
+     SI field, only negated.  */
+#define NSI (39)
+  { 16, 0, insert_nsi, extract_nsi,
+      PPC_OPERAND_NEGATIVE | PPC_OPERAND_SIGNED },
+
+  /* The RA field in an D, DS, X, XO, M, or MDS form instruction.  */
+#define RA (40)
+#define RA_MASK (0x1f << 16)
+  { 5, 16, 0, 0, PPC_OPERAND_GPR },
+
+  /* The RA field in a D or X form instruction which is an updating
+     load, which means that the RA field may not be zero and may not
+     equal the RT field.  */
+#define RAL (41)
+  { 5, 16, insert_ral, 0, PPC_OPERAND_GPR },
+
+  /* The RA field in an lmw instruction, which has special value
+     restrictions.  */
+#define RAM (42)
+  { 5, 16, insert_ram, 0, PPC_OPERAND_GPR },
+
+  /* The RA field in a D or X form instruction which is an updating
+     store or an updating floating point load, which means that the RA
+     field may not be zero.  */
+#define RAS (43)
+  { 5, 16, insert_ras, 0, PPC_OPERAND_GPR },
+
+  /* The RB field in an X, XO, M, or MDS form instruction.  */
+#define RB (44)
+#define RB_MASK (0x1f << 11)
+  { 5, 11, 0, 0, PPC_OPERAND_GPR },
+
+  /* The RB field in an X form instruction when it must be the same as
+     the RS field in the instruction.  This is used for extended
+     mnemonics like mr.  */
+#define RBS (45)
+  { 5, 1, insert_rbs, extract_rbs, PPC_OPERAND_FAKE },
+
+  /* The RS field in a D, DS, X, XFX, XS, M, MD or MDS form
+     instruction or the RT field in a D, DS, X, XFX or XO form
+     instruction.  */
+#define RS (46)
+#define RT (RS)
+#define RT_MASK (0x1f << 21)
+  { 5, 21, 0, 0, PPC_OPERAND_GPR },
+
+  /* The SH field in an X or M form instruction.  */
+#define SH (47)
+#define SH_MASK (0x1f << 11)
+  { 5, 11, 0, 0, 0 },
+
+  /* The SH field in an MD form instruction.  This is split.  */
+#define SH6 (48)
+#define SH6_MASK ((0x1f << 11) | (1 << 1))
+  { 6, 1, insert_sh6, extract_sh6, 0 },
+
+  /* The SI field in a D form instruction.  */
+#define SI (49)
+  { 16, 0, 0, 0, PPC_OPERAND_SIGNED },
+
+  /* The SI field in a D form instruction when we accept a wide range
+     of positive values.  */
+#define SISIGNOPT (50)
+  { 16, 0, 0, 0, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT },
+
+  /* The SPR field in an XFX form instruction.  This is flipped--the
+     lower 5 bits are stored in the upper 5 and vice- versa.  */
+#define SPR (51)
+#define SPR_MASK (0x3ff << 11)
+  { 10, 11, insert_spr, extract_spr, 0 },
+
+  /* The BAT index number in an XFX form m[ft]ibat[lu] instruction.  */
+#define SPRBAT (52)
+#define SPRBAT_MASK (0x3 << 17)
+  { 2, 17, 0, 0, 0 },
+
+  /* The SPRG register number in an XFX form m[ft]sprg instruction.  */
+#define SPRG (53)
+#define SPRG_MASK (0x3 << 16)
+  { 2, 16, 0, 0, 0 },
+
+  /* The SR field in an X form instruction.  */
+#define SR (54)
+  { 4, 16, 0, 0, 0 },
+
+  /* The SV field in a POWER SC form instruction.  */
+#define SV (55)
+  { 14, 2, 0, 0, 0 },
+
+  /* The TBR field in an XFX form instruction.  This is like the SPR
+     field, but it is optional.  */
+#define TBR (56)
+  { 10, 11, insert_tbr, extract_tbr, PPC_OPERAND_OPTIONAL },
+
+  /* The TO field in a D or X form instruction.  */
+#define TO (57)
+#define TO_MASK (0x1f << 21)
+  { 5, 21, 0, 0, 0 },
+
+  /* The U field in an X form instruction.  */
+#define U (58)
+  { 4, 12, 0, 0, 0 },
+
+  /* The UI field in a D form instruction.  */
+#define UI (59)
+  { 16, 0, 0, 0, 0 },
+};
+
+/* The functions used to insert and extract complicated operands.  */
+
+/* The BA field in an XL form instruction when it must be the same as
+   the BT field in the same instruction.  This operand is marked FAKE.
+   The insertion function just copies the BT field into the BA field,
+   and the extraction function just checks that the fields are the
+   same.  */
+
+/*ARGSUSED*/
+static unsigned long 
+insert_bat (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | (((insn >> 21) & 0x1f) << 16);
+}
+
+static long
+extract_bat (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if (invalid != (int *) NULL
+      && ((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f))
+    *invalid = 1;
+  return 0;
+}
+
+/* The BB field in an XL form instruction when it must be the same as
+   the BA field in the same instruction.  This operand is marked FAKE.
+   The insertion function just copies the BA field into the BB field,
+   and the extraction function just checks that the fields are the
+   same.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_bba (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | (((insn >> 16) & 0x1f) << 11);
+}
+
+static long
+extract_bba (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if (invalid != (int *) NULL
+      && ((insn >> 16) & 0x1f) != ((insn >> 11) & 0x1f))
+    *invalid = 1;
+  return 0;
+}
+
+/* The BD field in a B form instruction.  The lower two bits are
+   forced to zero.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_bd (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | (value & 0xfffc);
+}
+
+/*ARGSUSED*/
+static long
+extract_bd (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if ((insn & 0x8000) != 0)
+    return (insn & 0xfffc) - 0x10000;
+  else
+    return insn & 0xfffc;
+}
+
+/* The BD field in a B form instruction when the - modifier is used.
+   This modifier means that the branch is not expected to be taken.
+   We must set the y bit of the BO field to 1 if the offset is
+   negative.  When extracting, we require that the y bit be 1 and that
+   the offset be positive, since if the y bit is 0 we just want to
+   print the normal form of the instruction.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_bdm (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if ((value & 0x8000) != 0)
+    insn |= 1 << 21;
+  return insn | (value & 0xfffc);
+}
+
+static long
+extract_bdm (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if (invalid != (int *) NULL
+      && ((insn & (1 << 21)) == 0
+	  || (insn & (1 << 15)) == 0))
+    *invalid = 1;
+  if ((insn & 0x8000) != 0)
+    return (insn & 0xfffc) - 0x10000;
+  else
+    return insn & 0xfffc;
+}
+
+/* The BD field in a B form instruction when the + modifier is used.
+   This is like BDM, above, except that the branch is expected to be
+   taken.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_bdp (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if ((value & 0x8000) == 0)
+    insn |= 1 << 21;
+  return insn | (value & 0xfffc);
+}
+
+static long
+extract_bdp (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if (invalid != (int *) NULL
+      && ((insn & (1 << 21)) == 0
+	  || (insn & (1 << 15)) != 0))
+    *invalid = 1;
+  if ((insn & 0x8000) != 0)
+    return (insn & 0xfffc) - 0x10000;
+  else
+    return insn & 0xfffc;
+}
+
+/* Check for legal values of a BO field.  */
+
+static int
+valid_bo (value)
+     long value;
+{
+  /* Certain encodings have bits that are required to be zero.  These
+     are (z must be zero, y may be anything):
+         001zy
+	 011zy
+	 1z00y
+	 1z01y
+	 1z1zz
+     */
+  switch (value & 0x14)
+    {
+    default:
+    case 0:
+      return 1;
+    case 0x4:
+      return (value & 0x2) == 0;
+    case 0x10:
+      return (value & 0x8) == 0;
+    case 0x14:
+      return value == 0x14;
+    }
+}
+
+/* The BO field in a B form instruction.  Warn about attempts to set
+   the field to an illegal value.  */
+
+static unsigned long
+insert_bo (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (errmsg != (const char **) NULL
+      && ! valid_bo (value))
+    *errmsg = "invalid conditional option";
+  return insn | ((value & 0x1f) << 21);
+}
+
+static long
+extract_bo (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  long value;
+
+  value = (insn >> 21) & 0x1f;
+  if (invalid != (int *) NULL
+      && ! valid_bo (value))
+    *invalid = 1;
+  return value;
+}
+
+/* The BO field in a B form instruction when the + or - modifier is
+   used.  This is like the BO field, but it must be even.  When
+   extracting it, we force it to be even.  */
+
+static unsigned long
+insert_boe (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (errmsg != (const char **) NULL)
+    {
+      if (! valid_bo (value))
+	*errmsg = "invalid conditional option";
+      else if ((value & 1) != 0)
+	*errmsg = "attempt to set y bit when using + or - modifier";
+    }
+  return insn | ((value & 0x1f) << 21);
+}
+
+static long
+extract_boe (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  long value;
+
+  value = (insn >> 21) & 0x1f;
+  if (invalid != (int *) NULL
+      && ! valid_bo (value))
+    *invalid = 1;
+  return value & 0x1e;
+}
+
+/* The DS field in a DS form instruction.  This is like D, but the
+   lower two bits are forced to zero.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_ds (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | (value & 0xfffc);
+}
+
+/*ARGSUSED*/
+static long
+extract_ds (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if ((insn & 0x8000) != 0)
+    return (insn & 0xfffc) - 0x10000;
+  else
+    return insn & 0xfffc;
+}
+
+/* The LI field in an I form instruction.  The lower two bits are
+   forced to zero.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_li (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | (value & 0x3fffffc);
+}
+
+/*ARGSUSED*/
+static long
+extract_li (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if ((insn & 0x2000000) != 0)
+    return (insn & 0x3fffffc) - 0x4000000;
+  else
+    return insn & 0x3fffffc;
+}
+
+/* The MB and ME fields in an M form instruction expressed as a single
+   operand which is itself a bitmask.  The extraction function always
+   marks it as invalid, since we never want to recognize an
+   instruction which uses a field of this type.  */
+
+static unsigned long
+insert_mbe (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  unsigned long uval;
+  int mb, me;
+
+  uval = value;
+
+  if (uval == 0)
+    {
+      if (errmsg != (const char **) NULL)
+	*errmsg = "illegal bitmask";
+      return insn;
+    }
+
+  me = 31;
+  while ((uval & 1) == 0)
+    {
+      uval >>= 1;
+      --me;
+    }
+
+  mb = me;
+  uval >>= 1;
+  while ((uval & 1) != 0)
+    {
+      uval >>= 1;
+      --mb;
+    }
+
+  if (uval != 0)
+    {
+      if (errmsg != (const char **) NULL)
+	*errmsg = "illegal bitmask";
+    }
+
+  return insn | (mb << 6) | (me << 1);
+}
+
+static long
+extract_mbe (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  long ret;
+  int mb, me;
+  int i;
+
+  if (invalid != (int *) NULL)
+    *invalid = 1;
+
+  ret = 0;
+  mb = (insn >> 6) & 0x1f;
+  me = (insn >> 1) & 0x1f;
+  for (i = mb; i < me; i++)
+    ret |= 1 << (31 - i);
+  return ret;
+}
+
+/* The MB or ME field in an MD or MDS form instruction.  The high bit
+   is wrapped to the low end.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_mb6 (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | ((value & 0x1f) << 6) | (value & 0x20);
+}
+
+/*ARGSUSED*/
+static long
+extract_mb6 (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  return ((insn >> 6) & 0x1f) | (insn & 0x20);
+}
+
+/* The NB field in an X form instruction.  The value 32 is stored as
+   0.  */
+
+static unsigned long
+insert_nb (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (value < 0 || value > 32)
+    *errmsg = "value out of range";
+  if (value == 32)
+    value = 0;
+  return insn | ((value & 0x1f) << 11);
+}
+
+/*ARGSUSED*/
+static long
+extract_nb (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  long ret;
+
+  ret = (insn >> 11) & 0x1f;
+  if (ret == 0)
+    ret = 32;
+  return ret;
+}
+
+/* The NSI field in a D form instruction.  This is the same as the SI
+   field, only negated.  The extraction function always marks it as
+   invalid, since we never want to recognize an instruction which uses
+   a field of this type.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_nsi (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | ((- value) & 0xffff);
+}
+
+static long
+extract_nsi (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if (invalid != (int *) NULL)
+    *invalid = 1;
+  if ((insn & 0x8000) != 0)
+    return - ((insn & 0xffff) - 0x10000);
+  else
+    return - (insn & 0xffff);
+}
+
+/* The RA field in a D or X form instruction which is an updating
+   load, which means that the RA field may not be zero and may not
+   equal the RT field.  */
+
+static unsigned long
+insert_ral (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (value == 0
+      || value == ((insn >> 21) & 0x1f))
+    *errmsg = "invalid register operand when updating";
+  return insn | ((value & 0x1f) << 16);
+}
+
+/* The RA field in an lmw instruction, which has special value
+   restrictions.  */
+
+static unsigned long
+insert_ram (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (value >= ((insn >> 21) & 0x1f))
+    *errmsg = "index register in load range";
+  return insn | ((value & 0x1f) << 16);
+}
+
+/* The RA field in a D or X form instruction which is an updating
+   store or an updating floating point load, which means that the RA
+   field may not be zero.  */
+
+static unsigned long
+insert_ras (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (value == 0)
+    *errmsg = "invalid register operand when updating";
+  return insn | ((value & 0x1f) << 16);
+}
+
+/* The RB field in an X form instruction when it must be the same as
+   the RS field in the instruction.  This is used for extended
+   mnemonics like mr.  This operand is marked FAKE.  The insertion
+   function just copies the BT field into the BA field, and the
+   extraction function just checks that the fields are the same.  */
+
+/*ARGSUSED*/
+static unsigned long 
+insert_rbs (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | (((insn >> 21) & 0x1f) << 11);
+}
+
+static long
+extract_rbs (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  if (invalid != (int *) NULL
+      && ((insn >> 21) & 0x1f) != ((insn >> 11) & 0x1f))
+    *invalid = 1;
+  return 0;
+}
+
+/* The SH field in an MD form instruction.  This is split.  */
+
+/*ARGSUSED*/
+static unsigned long
+insert_sh6 (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4);
+}
+
+/*ARGSUSED*/
+static long
+extract_sh6 (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  return ((insn >> 11) & 0x1f) | ((insn << 4) & 0x20);
+}
+
+/* The SPR field in an XFX form instruction.  This is flipped--the
+   lower 5 bits are stored in the upper 5 and vice- versa.  */
+
+static unsigned long
+insert_spr (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
+}
+
+static long
+extract_spr (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
+}
+
+/* The TBR field in an XFX instruction.  This is just like SPR, but it
+   is optional.  When TBR is omitted, it must be inserted as 268 (the
+   magic number of the TB register).  These functions treat 0
+   (indicating an omitted optional operand) as 268.  This means that
+   ``mftb 4,0'' is not handled correctly.  This does not matter very
+   much, since the architecture manual does not define mftb as
+   accepting any values other than 268 or 269.  */
+
+#define TB (268)
+
+static unsigned long
+insert_tbr (insn, value, errmsg)
+     unsigned long insn;
+     long value;
+     const char **errmsg;
+{
+  if (value == 0)
+    value = TB;
+  return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
+}
+
+static long
+extract_tbr (insn, invalid)
+     unsigned long insn;
+     int *invalid;
+{
+  long ret;
+
+  ret = ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
+  if (ret == TB)
+    ret = 0;
+  return ret;
+}
+
+/* Macros used to form opcodes.  */
+
+/* The main opcode.  */
+#define OP(x) (((x) & 0x3f) << 26)
+#define OP_MASK OP (0x3f)
+
+/* The main opcode combined with a trap code in the TO field of a D
+   form instruction.  Used for extended mnemonics for the trap
+   instructions.  */
+#define OPTO(x,to) (OP (x) | (((to) & 0x1f) << 21))
+#define OPTO_MASK (OP_MASK | TO_MASK)
+
+/* The main opcode combined with a comparison size bit in the L field
+   of a D form or X form instruction.  Used for extended mnemonics for
+   the comparison instructions.  */
+#define OPL(x,l) (OP (x) | (((l) & 1) << 21))
+#define OPL_MASK OPL (0x3f,1)
+
+/* An A form instruction.  */
+#define A(op, xop, rc) (OP (op) | (((xop) & 0x1f) << 1) | ((rc) & 1))
+#define A_MASK A (0x3f, 0x1f, 1)
+
+/* An A_MASK with the FRB field fixed.  */
+#define AFRB_MASK (A_MASK | FRB_MASK)
+
+/* An A_MASK with the FRC field fixed.  */
+#define AFRC_MASK (A_MASK | FRC_MASK)
+
+/* An A_MASK with the FRA and FRC fields fixed.  */
+#define AFRAFRC_MASK (A_MASK | FRA_MASK | FRC_MASK)
+
+/* A B form instruction.  */
+#define B(op, aa, lk) (OP (op) | (((aa) & 1) << 1) | ((lk) & 1))
+#define B_MASK B (0x3f, 1, 1)
+
+/* A B form instruction setting the BO field.  */
+#define BBO(op, bo, aa, lk) (B ((op), (aa), (lk)) | (((bo) & 0x1f) << 21))
+#define BBO_MASK BBO (0x3f, 0x1f, 1, 1)
+
+/* A BBO_MASK with the y bit of the BO field removed.  This permits
+   matching a conditional branch regardless of the setting of the y
+   bit.  */
+#define Y_MASK (1 << 21)
+#define BBOY_MASK (BBO_MASK &~ Y_MASK)
+
+/* A B form instruction setting the BO field and the condition bits of
+   the BI field.  */
+#define BBOCB(op, bo, cb, aa, lk) \
+  (BBO ((op), (bo), (aa), (lk)) | (((cb) & 0x3) << 16))
+#define BBOCB_MASK BBOCB (0x3f, 0x1f, 0x3, 1, 1)
+
+/* A BBOCB_MASK with the y bit of the BO field removed.  */
+#define BBOYCB_MASK (BBOCB_MASK &~ Y_MASK)
+
+/* A BBOYCB_MASK in which the BI field is fixed.  */
+#define BBOYBI_MASK (BBOYCB_MASK | BI_MASK)
+
+/* The main opcode mask with the RA field clear.  */
+#define DRA_MASK (OP_MASK | RA_MASK)
+
+/* A DS form instruction.  */
+#define DSO(op, xop) (OP (op) | ((xop) & 0x3))
+#define DS_MASK DSO (0x3f, 3)
+
+/* An M form instruction.  */
+#define M(op, rc) (OP (op) | ((rc) & 1))
+#define M_MASK M (0x3f, 1)
+
+/* An M form instruction with the ME field specified.  */
+#define MME(op, me, rc) (M ((op), (rc)) | (((me) & 0x1f) << 1))
+
+/* An M_MASK with the MB and ME fields fixed.  */
+#define MMBME_MASK (M_MASK | MB_MASK | ME_MASK)
+
+/* An M_MASK with the SH and ME fields fixed.  */
+#define MSHME_MASK (M_MASK | SH_MASK | ME_MASK)
+
+/* An MD form instruction.  */
+#define MD(op, xop, rc) (OP (op) | (((xop) & 0x7) << 2) | ((rc) & 1))
+#define MD_MASK MD (0x3f, 0x7, 1)
+
+/* An MD_MASK with the MB field fixed.  */
+#define MDMB_MASK (MD_MASK | MB6_MASK)
+
+/* An MD_MASK with the SH field fixed.  */
+#define MDSH_MASK (MD_MASK | SH6_MASK)
+
+/* An MDS form instruction.  */
+#define MDS(op, xop, rc) (OP (op) | (((xop) & 0xf) << 1) | ((rc) & 1))
+#define MDS_MASK MDS (0x3f, 0xf, 1)
+
+/* An MDS_MASK with the MB field fixed.  */
+#define MDSMB_MASK (MDS_MASK | MB6_MASK)
+
+/* An SC form instruction.  */
+#define SC(op, sa, lk) (OP (op) | (((sa) & 1) << 1) | ((lk) & 1))
+#define SC_MASK (OP_MASK | (0x3ff << 16) | (1 << 1) | 1)
+
+/* An X form instruction.  */
+#define X(op, xop) (OP (op) | (((xop) & 0x3ff) << 1))
+
+/* An X form instruction with the RC bit specified.  */
+#define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1))
+
+/* The mask for an X form instruction.  */
+#define X_MASK XRC (0x3f, 0x3ff, 1)
+
+/* An X_MASK with the RA field fixed.  */
+#define XRA_MASK (X_MASK | RA_MASK)
+
+/* An X_MASK with the RB field fixed.  */
+#define XRB_MASK (X_MASK | RB_MASK)
+
+/* An X_MASK with the RT field fixed.  */
+#define XRT_MASK (X_MASK | RT_MASK)
+
+/* An X_MASK with the RA and RB fields fixed.  */
+#define XRARB_MASK (X_MASK | RA_MASK | RB_MASK)
+
+/* An X_MASK with the RT and RA fields fixed.  */
+#define XRTRA_MASK (X_MASK | RT_MASK | RA_MASK)
+
+/* An X form comparison instruction.  */
+#define XCMPL(op, xop, l) (X ((op), (xop)) | (((l) & 1) << 21))
+
+/* The mask for an X form comparison instruction.  */
+#define XCMP_MASK (X_MASK | (1 << 22))
+
+/* The mask for an X form comparison instruction with the L field
+   fixed.  */
+#define XCMPL_MASK (XCMP_MASK | (1 << 21))
+
+/* An X form trap instruction with the TO field specified.  */
+#define XTO(op, xop, to) (X ((op), (xop)) | (((to) & 0x1f) << 21))
+#define XTO_MASK (X_MASK | TO_MASK)
+
+/* An XFL form instruction.  */
+#define XFL(op, xop, rc) (OP (op) | (((xop) & 0x3ff) << 1) | ((rc) & 1))
+#define XFL_MASK (XFL (0x3f, 0x3ff, 1) | (1 << 25) | (1 << 16))
+
+/* An XL form instruction with the LK field set to 0.  */
+#define XL(op, xop) (OP (op) | (((xop) & 0x3ff) << 1))
+
+/* An XL form instruction which uses the LK field.  */
+#define XLLK(op, xop, lk) (XL ((op), (xop)) | ((lk) & 1))
+
+/* The mask for an XL form instruction.  */
+#define XL_MASK XLLK (0x3f, 0x3ff, 1)
+
+/* An XL form instruction which explicitly sets the BO field.  */
+#define XLO(op, bo, xop, lk) \
+  (XLLK ((op), (xop), (lk)) | (((bo) & 0x1f) << 21))
+#define XLO_MASK (XL_MASK | BO_MASK)
+
+/* An XL form instruction which explicitly sets the y bit of the BO
+   field.  */
+#define XLYLK(op, xop, y, lk) (XLLK ((op), (xop), (lk)) | (((y) & 1) << 21))
+#define XLYLK_MASK (XL_MASK | Y_MASK)
+
+/* An XL form instruction which sets the BO field and the condition
+   bits of the BI field.  */
+#define XLOCB(op, bo, cb, xop, lk) \
+  (XLO ((op), (bo), (xop), (lk)) | (((cb) & 3) << 16))
+#define XLOCB_MASK XLOCB (0x3f, 0x1f, 0x3, 0x3ff, 1)
+
+/* An XL_MASK or XLYLK_MASK or XLOCB_MASK with the BB field fixed.  */
+#define XLBB_MASK (XL_MASK | BB_MASK)
+#define XLYBB_MASK (XLYLK_MASK | BB_MASK)
+#define XLBOCBBB_MASK (XLOCB_MASK | BB_MASK)
+
+/* An XL_MASK with the BO and BB fields fixed.  */
+#define XLBOBB_MASK (XL_MASK | BO_MASK | BB_MASK)
+
+/* An XL_MASK with the BO, BI and BB fields fixed.  */
+#define XLBOBIBB_MASK (XL_MASK | BO_MASK | BI_MASK | BB_MASK)
+
+/* An XO form instruction.  */
+#define XO(op, xop, oe, rc) \
+  (OP (op) | (((xop) & 0x1ff) << 1) | (((oe) & 1) << 10) | ((rc) & 1))
+#define XO_MASK XO (0x3f, 0x1ff, 1, 1)
+
+/* An XO_MASK with the RB field fixed.  */
+#define XORB_MASK (XO_MASK | RB_MASK)
+
+/* An XS form instruction.  */
+#define XS(op, xop, rc) (OP (op) | (((xop) & 0x1ff) << 2) | ((rc) & 1))
+#define XS_MASK XS (0x3f, 0x1ff, 1)
+
+/* A mask for the FXM version of an XFX form instruction.  */
+#define XFXFXM_MASK (X_MASK | (1 << 20) | (1 << 11))
+
+/* An XFX form instruction with the FXM field filled in.  */
+#define XFXM(op, xop, fxm) \
+  (X ((op), (xop)) | (((fxm) & 0xff) << 12))
+
+/* An XFX form instruction with the SPR field filled in.  */
+#define XSPR(op, xop, spr) \
+  (X ((op), (xop)) | (((spr) & 0x1f) << 16) | (((spr) & 0x3e0) << 6))
+#define XSPR_MASK (X_MASK | SPR_MASK)
+
+/* An XFX form instruction with the SPR field filled in except for the
+   SPRBAT field.  */
+#define XSPRBAT_MASK (XSPR_MASK &~ SPRBAT_MASK)
+
+/* An XFX form instruction with the SPR field filled in except for the
+   SPRG field.  */
+#define XSPRG_MASK (XSPR_MASK &~ SPRG_MASK)
+
+/* The BO encodings used in extended conditional branch mnemonics.  */
+#define BODNZF	(0x0)
+#define BODNZFP	(0x1)
+#define BODZF	(0x2)
+#define BODZFP	(0x3)
+#define BOF	(0x4)
+#define BOFP	(0x5)
+#define BODNZT	(0x8)
+#define BODNZTP	(0x9)
+#define BODZT	(0xa)
+#define BODZTP	(0xb)
+#define BOT	(0xc)
+#define BOTP	(0xd)
+#define BODNZ	(0x10)
+#define BODNZP	(0x11)
+#define BODZ	(0x12)
+#define BODZP	(0x13)
+#define BOU	(0x14)
+
+/* The BI condition bit encodings used in extended conditional branch
+   mnemonics.  */
+#define CBLT	(0)
+#define CBGT	(1)
+#define CBEQ	(2)
+#define CBSO	(3)
+
+/* The TO encodings used in extended trap mnemonics.  */
+#define TOLGT	(0x1)
+#define TOLLT	(0x2)
+#define TOEQ	(0x4)
+#define TOLGE	(0x5)
+#define TOLNL	(0x5)
+#define TOLLE	(0x6)
+#define TOLNG	(0x6)
+#define TOGT	(0x8)
+#define TOGE	(0xc)
+#define TONL	(0xc)
+#define TOLT	(0x10)
+#define TOLE	(0x14)
+#define TONG	(0x14)
+#define TONE	(0x18)
+#define TOU	(0x1f)
+
+/* Smaller names for the flags so each entry in the opcodes table will
+   fit on a single line.  */
+#undef PPC
+#define PPC PPC_OPCODE_PPC
+#define POWER PPC_OPCODE_POWER
+#define POWER2 PPC_OPCODE_POWER2
+#define B32 PPC_OPCODE_32
+#define B64 PPC_OPCODE_64
+#define M601 PPC_OPCODE_601
+
+/* The opcode table.
+
+   The format of the opcode table is:
+
+   NAME	     OPCODE	MASK		FLAGS		{ OPERANDS }
+
+   NAME is the name of the instruction.
+   OPCODE is the instruction opcode.
+   MASK is the opcode mask; this is used to tell the disassembler
+     which bits in the actual opcode must match OPCODE.
+   FLAGS are flags indicated what processors support the instruction.
+   OPERANDS is the list of operands.
+
+   The disassembler reads the table in order and prints the first
+   instruction which matches, so this table is sorted to put more
+   specific instructions before more general instructions.  It is also
+   sorted by major opcode.  */
+
+const struct powerpc_opcode powerpc_opcodes[] = {
+{ "tdlgti",  OPTO(2,TOLGT), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdllti",  OPTO(2,TOLLT), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdeqi",   OPTO(2,TOEQ), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdlgei",  OPTO(2,TOLGE), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdlnli",  OPTO(2,TOLNL), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdllei",  OPTO(2,TOLLE), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdlngi",  OPTO(2,TOLNG), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdgti",   OPTO(2,TOGT), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdgei",   OPTO(2,TOGE), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdnli",   OPTO(2,TONL), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdlti",   OPTO(2,TOLT), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdlei",   OPTO(2,TOLE), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdngi",   OPTO(2,TONG), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdnei",   OPTO(2,TONE), OPTO_MASK,	PPC|B64,	{ RA, SI } },
+{ "tdi",     OP(2),	OP_MASK,	PPC|B64,	{ TO, RA, SI } },
+
+{ "twlgti",  OPTO(3,TOLGT), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tlgti",   OPTO(3,TOLGT), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twllti",  OPTO(3,TOLLT), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tllti",   OPTO(3,TOLLT), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "tweqi",   OPTO(3,TOEQ), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "teqi",    OPTO(3,TOEQ), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twlgei",  OPTO(3,TOLGE), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tlgei",   OPTO(3,TOLGE), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twlnli",  OPTO(3,TOLNL), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tlnli",   OPTO(3,TOLNL), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twllei",  OPTO(3,TOLLE), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tllei",   OPTO(3,TOLLE), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twlngi",  OPTO(3,TOLNG), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tlngi",   OPTO(3,TOLNG), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twgti",   OPTO(3,TOGT), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tgti",    OPTO(3,TOGT), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twgei",   OPTO(3,TOGE), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tgei",    OPTO(3,TOGE), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twnli",   OPTO(3,TONL), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tnli",    OPTO(3,TONL), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twlti",   OPTO(3,TOLT), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tlti",    OPTO(3,TOLT), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twlei",   OPTO(3,TOLE), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tlei",    OPTO(3,TOLE), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twngi",   OPTO(3,TONG), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tngi",    OPTO(3,TONG), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twnei",   OPTO(3,TONE), OPTO_MASK,	PPC,		{ RA, SI } },
+{ "tnei",    OPTO(3,TONE), OPTO_MASK,	POWER,		{ RA, SI } },
+{ "twi",     OP(3),	OP_MASK,	PPC,		{ TO, RA, SI } },
+{ "ti",      OP(3),	OP_MASK,	POWER,		{ TO, RA, SI } },
+
+{ "mulli",   OP(7),	OP_MASK,	PPC,		{ RT, RA, SI } },
+{ "muli",    OP(7),	OP_MASK,	POWER,		{ RT, RA, SI } },
+
+{ "subfic",  OP(8),	OP_MASK,	PPC,		{ RT, RA, SI } },
+{ "sfi",     OP(8),	OP_MASK,	POWER,		{ RT, RA, SI } },
+
+{ "dozi",    OP(9),	OP_MASK,	POWER|M601,	{ RT, RA, SI } },
+
+{ "cmplwi",  OPL(10,0),	OPL_MASK,	PPC,		{ OBF, RA, UI } },
+{ "cmpldi",  OPL(10,1), OPL_MASK,	PPC|B64,	{ OBF, RA, UI } },
+{ "cmpli",   OP(10),	OP_MASK,	PPC,		{ BF, L, RA, UI } },
+{ "cmpli",   OP(10),	OP_MASK,	POWER,		{ BF, RA, UI } },
+
+{ "cmpwi",   OPL(11,0),	OPL_MASK,	PPC,		{ OBF, RA, SI } },
+{ "cmpdi",   OPL(11,1),	OPL_MASK,	PPC|B64,	{ OBF, RA, SI } },
+{ "cmpi",    OP(11),	OP_MASK,	PPC,		{ BF, L, RA, SI } },
+{ "cmpi",    OP(11),	OP_MASK,	POWER,		{ BF, RA, SI } },
+
+{ "addic",   OP(12),	OP_MASK,	PPC,		{ RT, RA, SI } },
+{ "ai",	     OP(12),	OP_MASK,	POWER,		{ RT, RA, SI } },
+{ "subic",   OP(12),	OP_MASK,	PPC,		{ RT, RA, NSI } },
+
+{ "addic.",  OP(13),	OP_MASK,	PPC,		{ RT, RA, SI } },
+{ "ai.",     OP(13),	OP_MASK,	POWER,		{ RT, RA, SI } },
+{ "subic.",  OP(13),	OP_MASK,	PPC,		{ RT, RA, NSI } },
+
+{ "li",	     OP(14),	DRA_MASK,	PPC,		{ RT, SI } },
+{ "lil",     OP(14),	DRA_MASK,	POWER,		{ RT, SI } },
+{ "addi",    OP(14),	OP_MASK,	PPC,		{ RT, RA, SI } },
+{ "cal",     OP(14),	OP_MASK,	POWER,		{ RT, D, RA } },
+{ "subi",    OP(14),	OP_MASK,	PPC,		{ RT, RA, NSI } },
+{ "la",	     OP(14),	OP_MASK,	PPC,		{ RT, D, RA } },
+
+{ "lis",     OP(15),	DRA_MASK,	PPC,		{ RT, SISIGNOPT } },
+{ "liu",     OP(15),	DRA_MASK,	POWER,		{ RT, SISIGNOPT } },
+{ "addis",   OP(15),	OP_MASK,	PPC,		{ RT,RA,SISIGNOPT } },
+{ "cau",     OP(15),	OP_MASK,	POWER,		{ RT,RA,SISIGNOPT } },
+{ "subis",   OP(15),	OP_MASK,	PPC,		{ RT, RA, NSI } },
+
+{ "bdnz-",   BBO(16,BODNZ,0,0), BBOYBI_MASK, PPC,	{ BDM } },
+{ "bdnz+",   BBO(16,BODNZ,0,0), BBOYBI_MASK, PPC,	{ BDP } },
+{ "bdnz",    BBO(16,BODNZ,0,0), BBOYBI_MASK, PPC,	{ BD } },
+{ "bdn",     BBO(16,BODNZ,0,0), BBOYBI_MASK, POWER,	{ BD } },
+{ "bdnzl-",  BBO(16,BODNZ,0,1), BBOYBI_MASK, PPC,	{ BDM } },
+{ "bdnzl+",  BBO(16,BODNZ,0,1), BBOYBI_MASK, PPC,	{ BDP } },
+{ "bdnzl",   BBO(16,BODNZ,0,1), BBOYBI_MASK, PPC,	{ BD } },
+{ "bdnl",    BBO(16,BODNZ,0,1), BBOYBI_MASK, POWER,	{ BD } },
+{ "bdnza-",  BBO(16,BODNZ,1,0), BBOYBI_MASK, PPC,	{ BDMA } },
+{ "bdnza+",  BBO(16,BODNZ,1,0), BBOYBI_MASK, PPC,	{ BDPA } },
+{ "bdnza",   BBO(16,BODNZ,1,0), BBOYBI_MASK, PPC,	{ BDA } },
+{ "bdna",    BBO(16,BODNZ,1,0), BBOYBI_MASK, POWER,	{ BDA } },
+{ "bdnzla-", BBO(16,BODNZ,1,1), BBOYBI_MASK, PPC,	{ BDMA } },
+{ "bdnzla+", BBO(16,BODNZ,1,1), BBOYBI_MASK, PPC,	{ BDPA } },
+{ "bdnzla",  BBO(16,BODNZ,1,1), BBOYBI_MASK, PPC,	{ BDA } },
+{ "bdnla",   BBO(16,BODNZ,1,1), BBOYBI_MASK, POWER,	{ BDA } },
+{ "bdz-",    BBO(16,BODZ,0,0), BBOYBI_MASK, PPC,	{ BDM } },
+{ "bdz+",    BBO(16,BODZ,0,0), BBOYBI_MASK, PPC,	{ BDP } },
+{ "bdz",     BBO(16,BODZ,0,0), BBOYBI_MASK, PPC|POWER,	{ BD } },
+{ "bdzl-",   BBO(16,BODZ,0,1), BBOYBI_MASK, PPC,	{ BDM } },
+{ "bdzl+",   BBO(16,BODZ,0,1), BBOYBI_MASK, PPC,	{ BDP } },
+{ "bdzl",    BBO(16,BODZ,0,1), BBOYBI_MASK, PPC|POWER,	{ BD } },
+{ "bdza-",   BBO(16,BODZ,1,0), BBOYBI_MASK, PPC,	{ BDMA } },
+{ "bdza+",   BBO(16,BODZ,1,0), BBOYBI_MASK, PPC,	{ BDPA } },
+{ "bdza",    BBO(16,BODZ,1,0), BBOYBI_MASK, PPC|POWER,	{ BDA } },
+{ "bdzla-",  BBO(16,BODZ,1,1), BBOYBI_MASK, PPC,	{ BDMA } },
+{ "bdzla+",  BBO(16,BODZ,1,1), BBOYBI_MASK, PPC,	{ BDPA } },
+{ "bdzla",   BBO(16,BODZ,1,1), BBOYBI_MASK, PPC|POWER,	{ BDA } },
+{ "blt-",    BBOCB(16,BOT,CBLT,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "blt+",    BBOCB(16,BOT,CBLT,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "blt",     BBOCB(16,BOT,CBLT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bltl-",   BBOCB(16,BOT,CBLT,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bltl+",   BBOCB(16,BOT,CBLT,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bltl",    BBOCB(16,BOT,CBLT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "blta-",   BBOCB(16,BOT,CBLT,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "blta+",   BBOCB(16,BOT,CBLT,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "blta",    BBOCB(16,BOT,CBLT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bltla-",  BBOCB(16,BOT,CBLT,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bltla+",  BBOCB(16,BOT,CBLT,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bltla",   BBOCB(16,BOT,CBLT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bgt-",    BBOCB(16,BOT,CBGT,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bgt+",    BBOCB(16,BOT,CBGT,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bgt",     BBOCB(16,BOT,CBGT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bgtl-",   BBOCB(16,BOT,CBGT,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bgtl+",   BBOCB(16,BOT,CBGT,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bgtl",    BBOCB(16,BOT,CBGT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bgta-",   BBOCB(16,BOT,CBGT,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bgta+",   BBOCB(16,BOT,CBGT,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bgta",    BBOCB(16,BOT,CBGT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bgtla-",  BBOCB(16,BOT,CBGT,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bgtla+",  BBOCB(16,BOT,CBGT,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bgtla",   BBOCB(16,BOT,CBGT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "beq-",    BBOCB(16,BOT,CBEQ,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "beq+",    BBOCB(16,BOT,CBEQ,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "beq",     BBOCB(16,BOT,CBEQ,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "beql-",   BBOCB(16,BOT,CBEQ,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "beql+",   BBOCB(16,BOT,CBEQ,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "beql",    BBOCB(16,BOT,CBEQ,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "beqa-",   BBOCB(16,BOT,CBEQ,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "beqa+",   BBOCB(16,BOT,CBEQ,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "beqa",    BBOCB(16,BOT,CBEQ,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "beqla-",  BBOCB(16,BOT,CBEQ,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "beqla+",  BBOCB(16,BOT,CBEQ,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "beqla",   BBOCB(16,BOT,CBEQ,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bso-",    BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bso+",    BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bso",     BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bsol-",   BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bsol+",   BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bsol",    BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bsoa-",   BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bsoa+",   BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bsoa",    BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bsola-",  BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bsola+",  BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bsola",   BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bun-",    BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bun+",    BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bun",     BBOCB(16,BOT,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BD } },
+{ "bunl-",   BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bunl+",   BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bunl",    BBOCB(16,BOT,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BD } },
+{ "buna-",   BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "buna+",   BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "buna",    BBOCB(16,BOT,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDA } },
+{ "bunla-",  BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bunla+",  BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bunla",   BBOCB(16,BOT,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDA } },
+{ "bge-",    BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bge+",    BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bge",     BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bgel-",   BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bgel+",   BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bgel",    BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bgea-",   BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bgea+",   BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bgea",    BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bgela-",  BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bgela+",  BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bgela",   BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnl-",    BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bnl+",    BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bnl",     BBOCB(16,BOF,CBLT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnll-",   BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bnll+",   BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bnll",    BBOCB(16,BOF,CBLT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnla-",   BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnla+",   BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnla",    BBOCB(16,BOF,CBLT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnlla-",  BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnlla+",  BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnlla",   BBOCB(16,BOF,CBLT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "ble-",    BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "ble+",    BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "ble",     BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "blel-",   BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "blel+",   BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "blel",    BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "blea-",   BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "blea+",   BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "blea",    BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "blela-",  BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "blela+",  BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "blela",   BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bng-",    BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bng+",    BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bng",     BBOCB(16,BOF,CBGT,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bngl-",   BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bngl+",   BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bngl",    BBOCB(16,BOF,CBGT,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnga-",   BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnga+",   BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnga",    BBOCB(16,BOF,CBGT,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bngla-",  BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bngla+",  BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bngla",   BBOCB(16,BOF,CBGT,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bne-",    BBOCB(16,BOF,CBEQ,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bne+",    BBOCB(16,BOF,CBEQ,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bne",     BBOCB(16,BOF,CBEQ,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnel-",   BBOCB(16,BOF,CBEQ,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bnel+",   BBOCB(16,BOF,CBEQ,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bnel",    BBOCB(16,BOF,CBEQ,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnea-",   BBOCB(16,BOF,CBEQ,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnea+",   BBOCB(16,BOF,CBEQ,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnea",    BBOCB(16,BOF,CBEQ,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnela-",  BBOCB(16,BOF,CBEQ,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnela+",  BBOCB(16,BOF,CBEQ,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnela",   BBOCB(16,BOF,CBEQ,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bns-",    BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bns+",    BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bns",     BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnsl-",   BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bnsl+",   BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bnsl",    BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC|POWER, { CR, BD } },
+{ "bnsa-",   BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnsa+",   BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnsa",    BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnsla-",  BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnsla+",  BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnsla",   BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC|POWER, { CR, BDA } },
+{ "bnu-",    BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bnu+",    BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bnu",     BBOCB(16,BOF,CBSO,0,0), BBOYCB_MASK, PPC,	{ CR, BD } },
+{ "bnul-",   BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDM } },
+{ "bnul+",   BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BDP } },
+{ "bnul",    BBOCB(16,BOF,CBSO,0,1), BBOYCB_MASK, PPC,	{ CR, BD } },
+{ "bnua-",   BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnua+",   BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnua",    BBOCB(16,BOF,CBSO,1,0), BBOYCB_MASK, PPC,	{ CR, BDA } },
+{ "bnula-",  BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDMA } },
+{ "bnula+",  BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDPA } },
+{ "bnula",   BBOCB(16,BOF,CBSO,1,1), BBOYCB_MASK, PPC,	{ CR, BDA } },
+{ "bdnzt-",  BBO(16,BODNZT,0,0), BBOY_MASK, PPC,	{ BI, BDM } },
+{ "bdnzt+",  BBO(16,BODNZT,0,0), BBOY_MASK, PPC,	{ BI, BDP } },
+{ "bdnzt",   BBO(16,BODNZT,0,0), BBOY_MASK, PPC,	{ BI, BD } },
+{ "bdnztl-", BBO(16,BODNZT,0,1), BBOY_MASK, PPC,	{ BI, BDM } },
+{ "bdnztl+", BBO(16,BODNZT,0,1), BBOY_MASK, PPC,	{ BI, BDP } },
+{ "bdnztl",  BBO(16,BODNZT,0,1), BBOY_MASK, PPC,	{ BI, BD } },
+{ "bdnzta-", BBO(16,BODNZT,1,0), BBOY_MASK, PPC,	{ BI, BDMA } },
+{ "bdnzta+", BBO(16,BODNZT,1,0), BBOY_MASK, PPC,	{ BI, BDPA } },
+{ "bdnzta",  BBO(16,BODNZT,1,0), BBOY_MASK, PPC,	{ BI, BDA } },
+{ "bdnztla-",BBO(16,BODNZT,1,1), BBOY_MASK, PPC,	{ BI, BDMA } },
+{ "bdnztla+",BBO(16,BODNZT,1,1), BBOY_MASK, PPC,	{ BI, BDPA } },
+{ "bdnztla", BBO(16,BODNZT,1,1), BBOY_MASK, PPC,	{ BI, BDA } },
+{ "bdnzf-",  BBO(16,BODNZF,0,0), BBOY_MASK, PPC,	{ BI, BDM } },
+{ "bdnzf+",  BBO(16,BODNZF,0,0), BBOY_MASK, PPC,	{ BI, BDP } },
+{ "bdnzf",   BBO(16,BODNZF,0,0), BBOY_MASK, PPC,	{ BI, BD } },
+{ "bdnzfl-", BBO(16,BODNZF,0,1), BBOY_MASK, PPC,	{ BI, BDM } },
+{ "bdnzfl+", BBO(16,BODNZF,0,1), BBOY_MASK, PPC,	{ BI, BDP } },
+{ "bdnzfl",  BBO(16,BODNZF,0,1), BBOY_MASK, PPC,	{ BI, BD } },
+{ "bdnzfa-", BBO(16,BODNZF,1,0), BBOY_MASK, PPC,	{ BI, BDMA } },
+{ "bdnzfa+", BBO(16,BODNZF,1,0), BBOY_MASK, PPC,	{ BI, BDPA } },
+{ "bdnzfa",  BBO(16,BODNZF,1,0), BBOY_MASK, PPC,	{ BI, BDA } },
+{ "bdnzfla-",BBO(16,BODNZF,1,1), BBOY_MASK, PPC,	{ BI, BDMA } },
+{ "bdnzfla+",BBO(16,BODNZF,1,1), BBOY_MASK, PPC,	{ BI, BDPA } },
+{ "bdnzfla", BBO(16,BODNZF,1,1), BBOY_MASK, PPC,	{ BI, BDA } },
+{ "bt-",     BBO(16,BOT,0,0), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bt+",     BBO(16,BOT,0,0), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bt",	     BBO(16,BOT,0,0), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bbt",     BBO(16,BOT,0,0), BBOY_MASK, POWER,		{ BI, BD } },
+{ "btl-",    BBO(16,BOT,0,1), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "btl+",    BBO(16,BOT,0,1), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "btl",     BBO(16,BOT,0,1), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bbtl",    BBO(16,BOT,0,1), BBOY_MASK, POWER,		{ BI, BD } },
+{ "bta-",    BBO(16,BOT,1,0), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bta+",    BBO(16,BOT,1,0), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bta",     BBO(16,BOT,1,0), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bbta",    BBO(16,BOT,1,0), BBOY_MASK, POWER,		{ BI, BDA } },
+{ "btla-",   BBO(16,BOT,1,1), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "btla+",   BBO(16,BOT,1,1), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "btla",    BBO(16,BOT,1,1), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bbtla",   BBO(16,BOT,1,1), BBOY_MASK, POWER,		{ BI, BDA } },
+{ "bf-",     BBO(16,BOF,0,0), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bf+",     BBO(16,BOF,0,0), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bf",	     BBO(16,BOF,0,0), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bbf",     BBO(16,BOF,0,0), BBOY_MASK, POWER,		{ BI, BD } },
+{ "bfl-",    BBO(16,BOF,0,1), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bfl+",    BBO(16,BOF,0,1), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bfl",     BBO(16,BOF,0,1), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bbfl",    BBO(16,BOF,0,1), BBOY_MASK, POWER,		{ BI, BD } },
+{ "bfa-",    BBO(16,BOF,1,0), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bfa+",    BBO(16,BOF,1,0), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bfa",     BBO(16,BOF,1,0), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bbfa",    BBO(16,BOF,1,0), BBOY_MASK, POWER,		{ BI, BDA } },
+{ "bfla-",   BBO(16,BOF,1,1), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bfla+",   BBO(16,BOF,1,1), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bfla",    BBO(16,BOF,1,1), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bbfla",   BBO(16,BOF,1,1), BBOY_MASK, POWER,		{ BI, BDA } },
+{ "bdzt-",   BBO(16,BODZT,0,0), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bdzt+",   BBO(16,BODZT,0,0), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bdzt",    BBO(16,BODZT,0,0), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bdztl-",  BBO(16,BODZT,0,1), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bdztl+",  BBO(16,BODZT,0,1), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bdztl",   BBO(16,BODZT,0,1), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bdzta-",  BBO(16,BODZT,1,0), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bdzta+",  BBO(16,BODZT,1,0), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bdzta",   BBO(16,BODZT,1,0), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bdztla-", BBO(16,BODZT,1,1), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bdztla+", BBO(16,BODZT,1,1), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bdztla",  BBO(16,BODZT,1,1), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bdzf-",   BBO(16,BODZF,0,0), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bdzf+",   BBO(16,BODZF,0,0), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bdzf",    BBO(16,BODZF,0,0), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bdzfl-",  BBO(16,BODZF,0,1), BBOY_MASK, PPC,		{ BI, BDM } },
+{ "bdzfl+",  BBO(16,BODZF,0,1), BBOY_MASK, PPC,		{ BI, BDP } },
+{ "bdzfl",   BBO(16,BODZF,0,1), BBOY_MASK, PPC,		{ BI, BD } },
+{ "bdzfa-",  BBO(16,BODZF,1,0), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bdzfa+",  BBO(16,BODZF,1,0), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bdzfa",   BBO(16,BODZF,1,0), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bdzfla-", BBO(16,BODZF,1,1), BBOY_MASK, PPC,		{ BI, BDMA } },
+{ "bdzfla+", BBO(16,BODZF,1,1), BBOY_MASK, PPC,		{ BI, BDPA } },
+{ "bdzfla",  BBO(16,BODZF,1,1), BBOY_MASK, PPC,		{ BI, BDA } },
+{ "bc-",     B(16,0,0),	B_MASK,		PPC,		{ BOE, BI, BDM } },
+{ "bc+",     B(16,0,0),	B_MASK,		PPC,		{ BOE, BI, BDP } },
+{ "bc",	     B(16,0,0),	B_MASK,		PPC|POWER,	{ BO, BI, BD } },
+{ "bcl-",    B(16,0,1),	B_MASK,		PPC,		{ BOE, BI, BDM } },
+{ "bcl+",    B(16,0,1),	B_MASK,		PPC,		{ BOE, BI, BDP } },
+{ "bcl",     B(16,0,1),	B_MASK,		PPC|POWER,	{ BO, BI, BD } },
+{ "bca-",    B(16,1,0),	B_MASK,		PPC,		{ BOE, BI, BDMA } },
+{ "bca+",    B(16,1,0),	B_MASK,		PPC,		{ BOE, BI, BDPA } },
+{ "bca",     B(16,1,0),	B_MASK,		PPC|POWER,	{ BO, BI, BDA } },
+{ "bcla-",   B(16,1,1),	B_MASK,		PPC,		{ BOE, BI, BDMA } },
+{ "bcla+",   B(16,1,1),	B_MASK,		PPC,		{ BOE, BI, BDPA } },
+{ "bcla",    B(16,1,1),	B_MASK,		PPC|POWER,	{ BO, BI, BDA } },
+
+{ "sc",      SC(17,1,0), 0xffffffff,	PPC,		{ 0 } },
+{ "svc",     SC(17,0,0), SC_MASK,	POWER,		{ LEV, FL1, FL2 } },
+{ "svcl",    SC(17,0,1), SC_MASK,	POWER,		{ LEV, FL1, FL2 } },
+{ "svca",    SC(17,1,0), SC_MASK,	POWER,		{ SV } },
+{ "svcla",   SC(17,1,1), SC_MASK,	POWER,		{ SV } },
+
+{ "b",	     B(18,0,0),	B_MASK,		PPC|POWER,	{ LI } },
+{ "bl",      B(18,0,1),	B_MASK,		PPC|POWER,	{ LI } },
+{ "ba",      B(18,1,0),	B_MASK,		PPC|POWER,	{ LIA } },
+{ "bla",     B(18,1,1),	B_MASK,		PPC|POWER,	{ LIA } },
+
+{ "mcrf",    XL(19,0),	XLBB_MASK|(3<<21)|(3<<16), PPC|POWER, { BF, BFA } },
+
+{ "blr",     XLO(19,BOU,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "br",      XLO(19,BOU,16,0), XLBOBIBB_MASK, POWER,	{ 0 } },
+{ "blrl",    XLO(19,BOU,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "brl",     XLO(19,BOU,16,1), XLBOBIBB_MASK, POWER,	{ 0 } },
+{ "bdnzlr",  XLO(19,BODNZ,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdnzlr-", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdnzlr+", XLO(19,BODNZP,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdnzlrl", XLO(19,BODNZ,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdnzlrl-",XLO(19,BODNZ,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdnzlrl+",XLO(19,BODNZP,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdzlr",   XLO(19,BODZ,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdzlr-",  XLO(19,BODZ,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdzlr+",  XLO(19,BODZP,16,0), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdzlrl",  XLO(19,BODZ,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdzlrl-", XLO(19,BODZ,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bdzlrl+", XLO(19,BODZP,16,1), XLBOBIBB_MASK, PPC,	{ 0 } },
+{ "bltlr",   XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltlr-",  XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltlr+",  XLOCB(19,BOTP,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltr",    XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bltlrl",  XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltlrl-", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltlrl+", XLOCB(19,BOTP,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltrl",   XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bgtlr",   XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtlr-",  XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtlr+",  XLOCB(19,BOTP,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtr",    XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bgtlrl",  XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtlrl-", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtlrl+", XLOCB(19,BOTP,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtrl",   XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "beqlr",   XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqlr-",  XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqlr+",  XLOCB(19,BOTP,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqr",    XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "beqlrl",  XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqlrl-", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqlrl+", XLOCB(19,BOTP,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqrl",   XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bsolr",   XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsolr-",  XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsolr+",  XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsor",    XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bsolrl",  XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsolrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsolrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsorl",   XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bunlr",   XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlr-",  XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlr+",  XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlrl",  XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunlrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelr",   XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelr-",  XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelr+",  XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bger",    XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bgelrl",  XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgelrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgerl",   XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnllr",   XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnllr-",  XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnllr+",  XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlr",    XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnllrl",  XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnllrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnllrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlrl",   XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "blelr",   XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blelr-",  XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blelr+",  XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bler",    XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "blelrl",  XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blelrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blelrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blerl",   XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnglr",   XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnglr-",  XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnglr+",  XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngr",    XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnglrl",  XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnglrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnglrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngrl",   XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnelr",   XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnelr-",  XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnelr+",  XLOCB(19,BOFP,CBEQ,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bner",    XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnelrl",  XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnelrl-", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnelrl+", XLOCB(19,BOFP,CBEQ,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnerl",   XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnslr",   XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnslr-",  XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnslr+",  XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsr",    XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnslrl",  XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnslrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnslrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsrl",   XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, POWER, { CR } },
+{ "bnulr",   XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulr-",  XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulr+",  XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulrl",  XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnulrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "btlr",    XLO(19,BOT,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "btlr-",   XLO(19,BOT,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "btlr+",   XLO(19,BOTP,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bbtr",    XLO(19,BOT,16,0), XLBOBB_MASK, POWER,	{ BI } },
+{ "btlrl",   XLO(19,BOT,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "btlrl-",  XLO(19,BOT,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "btlrl+",  XLO(19,BOTP,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bbtrl",   XLO(19,BOT,16,1), XLBOBB_MASK, POWER,	{ BI } },
+{ "bflr",    XLO(19,BOF,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bflr-",   XLO(19,BOF,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bflr+",   XLO(19,BOFP,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bbfr",    XLO(19,BOF,16,0), XLBOBB_MASK, POWER,	{ BI } },
+{ "bflrl",   XLO(19,BOF,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bflrl-",  XLO(19,BOF,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bflrl+",  XLO(19,BOFP,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bbfrl",   XLO(19,BOF,16,1), XLBOBB_MASK, POWER,	{ BI } },
+{ "bdnztlr", XLO(19,BODNZT,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnztlr-",XLO(19,BODNZT,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnztlr+",XLO(19,BODNZTP,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnztlrl",XLO(19,BODNZT,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnztlrl-",XLO(19,BODNZT,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnztlrl+",XLO(19,BODNZTP,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnzflr", XLO(19,BODNZF,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnzflr-",XLO(19,BODNZF,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnzflr+",XLO(19,BODNZFP,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnzflrl",XLO(19,BODNZF,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnzflrl-",XLO(19,BODNZF,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdnzflrl+",XLO(19,BODNZFP,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdztlr",  XLO(19,BODZT,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdztlr-", XLO(19,BODZT,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdztlr+", XLO(19,BODZTP,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdztlrl", XLO(19,BODZT,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdztlrl-",XLO(19,BODZT,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdztlrl+",XLO(19,BODZTP,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdzflr",  XLO(19,BODZF,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdzflr-", XLO(19,BODZF,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdzflr+", XLO(19,BODZFP,16,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdzflrl", XLO(19,BODZF,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdzflrl-",XLO(19,BODZF,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bdzflrl+",XLO(19,BODZFP,16,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bclr",    XLLK(19,16,0), XLYBB_MASK,	PPC,		{ BO, BI } },
+{ "bclrl",   XLLK(19,16,1), XLYBB_MASK,	PPC,		{ BO, BI } },
+{ "bclr+",   XLYLK(19,16,1,0), XLYBB_MASK, PPC,		{ BOE, BI } },
+{ "bclrl+",  XLYLK(19,16,1,1), XLYBB_MASK, PPC,		{ BOE, BI } },
+{ "bclr-",   XLYLK(19,16,0,0), XLYBB_MASK, PPC,		{ BOE, BI } },
+{ "bclrl-",  XLYLK(19,16,0,1), XLYBB_MASK, PPC,		{ BOE, BI } },
+{ "bcr",     XLLK(19,16,0), XLBB_MASK,	POWER,		{ BO, BI } },
+{ "bcrl",    XLLK(19,16,1), XLBB_MASK,	POWER,		{ BO, BI } },
+
+{ "crnot",   XL(19,33), XL_MASK,	PPC,		{ BT, BA, BBA } },
+{ "crnor",   XL(19,33),	XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "rfi",     XL(19,50),	0xffffffff,	PPC|POWER,	{ 0 } },
+{ "rfci",    XL(19,51),	0xffffffff,	PPC,		{ 0 } },
+
+{ "rfsvc",   XL(19,82),	0xffffffff,	POWER,		{ 0 } },
+
+{ "crandc",  XL(19,129), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "isync",   XL(19,150), 0xffffffff,	PPC,		{ 0 } },
+{ "ics",     XL(19,150), 0xffffffff,	POWER,		{ 0 } },
+
+{ "crclr",   XL(19,193), XL_MASK,	PPC,		{ BT, BAT, BBA } },
+{ "crxor",   XL(19,193), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "crnand",  XL(19,225), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "crand",   XL(19,257), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "crset",   XL(19,289), XL_MASK,	PPC,		{ BT, BAT, BBA } },
+{ "creqv",   XL(19,289), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "crorc",   XL(19,417), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "crmove",  XL(19,449), XL_MASK,	PPC,		{ BT, BA, BBA } },
+{ "cror",    XL(19,449), XL_MASK,	PPC|POWER,	{ BT, BA, BB } },
+
+{ "bctr",    XLO(19,BOU,528,0), XLBOBIBB_MASK, PPC|POWER, { 0 } },
+{ "bctrl",   XLO(19,BOU,528,1), XLBOBIBB_MASK, PPC|POWER, { 0 } },
+{ "bltctr",  XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctr-", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctr+", XLOCB(19,BOTP,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctrl", XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctrl-",XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bltctrl+",XLOCB(19,BOTP,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctr",  XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctr-", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctr+", XLOCB(19,BOTP,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctrl", XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctrl-",XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgtctrl+",XLOCB(19,BOTP,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctr",  XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctr-", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctr+", XLOCB(19,BOTP,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctrl", XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctrl-",XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "beqctrl+",XLOCB(19,BOTP,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctr",  XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bsoctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctr",  XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bunctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectr",  XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bgectrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctr",  XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnlctrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectr",  XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "blectrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctr",  XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bngctrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectr",  XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectr-", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectr+", XLOCB(19,BOFP,CBEQ,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectrl", XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectrl-",XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnectrl+",XLOCB(19,BOFP,CBEQ,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctr",  XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnsctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctr",  XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "bnuctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, PPC, { CR } },
+{ "btctr",   XLO(19,BOT,528,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "btctr-",  XLO(19,BOT,528,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "btctr+",  XLO(19,BOTP,528,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "btctrl",  XLO(19,BOT,528,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "btctrl-", XLO(19,BOT,528,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "btctrl+", XLO(19,BOTP,528,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bfctr",   XLO(19,BOF,528,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bfctr-",  XLO(19,BOF,528,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bfctr+",  XLO(19,BOFP,528,0), XLBOBB_MASK, PPC,	{ BI } },
+{ "bfctrl",  XLO(19,BOF,528,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bfctrl-", XLO(19,BOF,528,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bfctrl+", XLO(19,BOFP,528,1), XLBOBB_MASK, PPC,	{ BI } },
+{ "bcctr",   XLLK(19,528,0), XLYBB_MASK, PPC,		{ BO, BI } },
+{ "bcctr-",  XLYLK(19,528,0,0), XLYBB_MASK, PPC,	{ BOE, BI } },
+{ "bcctr+",  XLYLK(19,528,1,0), XLYBB_MASK, PPC,	{ BOE, BI } },
+{ "bcctrl",  XLLK(19,528,1), XLYBB_MASK, PPC,		{ BO, BI } },
+{ "bcctrl-", XLYLK(19,528,0,1), XLYBB_MASK, PPC,	{ BOE, BI } },
+{ "bcctrl+", XLYLK(19,528,1,1), XLYBB_MASK, PPC,	{ BOE, BI } },
+{ "bcc",     XLLK(19,528,0), XLBB_MASK,	POWER,		{ BO, BI } },
+{ "bccl",    XLLK(19,528,1), XLBB_MASK,	POWER,		{ BO, BI } },
+
+{ "rlwimi",  M(20,0),	M_MASK,		PPC,		{ RA,RS,SH,MBE,ME } },
+{ "rlimi",   M(20,0),	M_MASK,		POWER,		{ RA,RS,SH,MBE,ME } },
+
+{ "rlwimi.", M(20,1),	M_MASK,		PPC,		{ RA,RS,SH,MBE,ME } },
+{ "rlimi.",  M(20,1),	M_MASK,		POWER,		{ RA,RS,SH,MBE,ME } },
+
+{ "rotlwi",  MME(21,31,0), MMBME_MASK,	PPC,		{ RA, RS, SH } },
+{ "clrlwi",  MME(21,31,0), MSHME_MASK,	PPC,		{ RA, RS, MB } },
+{ "rlwinm",  M(21,0),	M_MASK,		PPC,		{ RA,RS,SH,MBE,ME } },
+{ "rlinm",   M(21,0),	M_MASK,		POWER,		{ RA,RS,SH,MBE,ME } },
+{ "rotlwi.", MME(21,31,1), MMBME_MASK,	PPC,		{ RA,RS,SH } },
+{ "clrlwi.", MME(21,31,1), MSHME_MASK,	PPC,		{ RA, RS, MB } },
+{ "rlwinm.", M(21,1),	M_MASK,		PPC,		{ RA,RS,SH,MBE,ME } },
+{ "rlinm.",  M(21,1),	M_MASK,		POWER,		{ RA,RS,SH,MBE,ME } },
+
+{ "rlmi",    M(22,0),	M_MASK,		POWER|M601,	{ RA,RS,RB,MBE,ME } },
+{ "rlmi.",   M(22,1),	M_MASK,		POWER|M601,	{ RA,RS,RB,MBE,ME } },
+
+{ "rotlw",   MME(23,31,0), MMBME_MASK,	PPC,		{ RA, RS, RB } },
+{ "rlwnm",   M(23,0),	M_MASK,		PPC,		{ RA,RS,RB,MBE,ME } },
+{ "rlnm",    M(23,0),	M_MASK,		POWER,		{ RA,RS,RB,MBE,ME } },
+{ "rotlw.",  MME(23,31,1), MMBME_MASK,	PPC,		{ RA, RS, RB } },
+{ "rlwnm.",  M(23,1),	M_MASK,		PPC,		{ RA,RS,RB,MBE,ME } },
+{ "rlnm.",   M(23,1),	M_MASK,		POWER,		{ RA,RS,RB,MBE,ME } },
+
+{ "nop",     OP(24),	0xffffffff,	PPC,		{ 0 } },
+{ "ori",     OP(24),	OP_MASK,	PPC,		{ RA, RS, UI } },
+{ "oril",    OP(24),	OP_MASK,	POWER,		{ RA, RS, UI } },
+
+{ "oris",    OP(25),	OP_MASK,	PPC,		{ RA, RS, UI } },
+{ "oriu",    OP(25),	OP_MASK,	POWER,		{ RA, RS, UI } },
+
+{ "xori",    OP(26),	OP_MASK,	PPC,		{ RA, RS, UI } },
+{ "xoril",   OP(26),	OP_MASK,	POWER,		{ RA, RS, UI } },
+
+{ "xoris",   OP(27),	OP_MASK,	PPC,		{ RA, RS, UI } },
+{ "xoriu",   OP(27),	OP_MASK,	POWER,		{ RA, RS, UI } },
+
+{ "andi.",   OP(28),	OP_MASK,	PPC,		{ RA, RS, UI } },
+{ "andil.",  OP(28),	OP_MASK,	POWER,		{ RA, RS, UI } },
+
+{ "andis.",  OP(29),	OP_MASK,	PPC,		{ RA, RS, UI } },
+{ "andiu.",  OP(29),	OP_MASK,	POWER,		{ RA, RS, UI } },
+
+{ "rotldi",  MD(30,0,0), MDMB_MASK,	PPC|B64,	{ RA, RS, SH6 } },
+{ "clrldi",  MD(30,0,0), MDSH_MASK,	PPC|B64,	{ RA, RS, MB6 } },
+{ "rldicl",  MD(30,0,0), MD_MASK,	PPC|B64,	{ RA, RS, SH6, MB6 } },
+{ "rotldi.", MD(30,0,1), MDMB_MASK,	PPC|B64,	{ RA, RS, SH6 } },
+{ "clrldi.", MD(30,0,1), MDSH_MASK,	PPC|B64,	{ RA, RS, MB6 } },
+{ "rldicl.", MD(30,0,1), MD_MASK,	PPC|B64,	{ RA, RS, SH6, MB6 } },
+
+{ "rldicr",  MD(30,1,0), MD_MASK,	PPC|B64,	{ RA, RS, SH6, ME6 } },
+{ "rldicr.", MD(30,1,1), MD_MASK,	PPC|B64,	{ RA, RS, SH6, ME6 } },
+
+{ "rldic",   MD(30,2,0), MD_MASK,	PPC|B64,	{ RA, RS, SH6, MB6 } },
+{ "rldic.",  MD(30,2,1), MD_MASK,	PPC|B64,	{ RA, RS, SH6, MB6 } },
+
+{ "rldimi",  MD(30,3,0), MD_MASK,	PPC|B64,	{ RA, RS, SH6, MB6 } },
+{ "rldimi.", MD(30,3,1), MD_MASK,	PPC|B64,	{ RA, RS, SH6, MB6 } },
+
+{ "rotld",   MDS(30,8,0), MDSMB_MASK,	PPC|B64,	{ RA, RS, RB } },
+{ "rldcl",   MDS(30,8,0), MDS_MASK,	PPC|B64,	{ RA, RS, RB, MB6 } },
+{ "rotld.",  MDS(30,8,1), MDSMB_MASK,	PPC|B64,	{ RA, RS, RB } },
+{ "rldcl.",  MDS(30,8,1), MDS_MASK,	PPC|B64,	{ RA, RS, RB, MB6 } },
+
+{ "rldcr",   MDS(30,9,0), MDS_MASK,	PPC|B64,	{ RA, RS, RB, ME6 } },
+{ "rldcr.",  MDS(30,9,1), MDS_MASK,	PPC|B64,	{ RA, RS, RB, ME6 } },
+
+{ "cmpw",    XCMPL(31,0,0), XCMPL_MASK, PPC,		{ OBF, RA, RB } },
+{ "cmpd",    XCMPL(31,0,1), XCMPL_MASK, PPC|B64,	{ OBF, RA, RB } },
+{ "cmp",     X(31,0),	XCMP_MASK,	PPC,		{ BF, L, RA, RB } },
+{ "cmp",     X(31,0),	XCMPL_MASK,	POWER,		{ BF, RA, RB } },
+
+{ "twlgt",   XTO(31,4,TOLGT), XTO_MASK, PPC,		{ RA, RB } },
+{ "tlgt",    XTO(31,4,TOLGT), XTO_MASK, POWER,		{ RA, RB } },
+{ "twllt",   XTO(31,4,TOLLT), XTO_MASK, PPC,		{ RA, RB } },
+{ "tllt",    XTO(31,4,TOLLT), XTO_MASK, POWER,		{ RA, RB } },
+{ "tweq",    XTO(31,4,TOEQ), XTO_MASK,	PPC,		{ RA, RB } },
+{ "teq",     XTO(31,4,TOEQ), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twlge",   XTO(31,4,TOLGE), XTO_MASK, PPC,		{ RA, RB } },
+{ "tlge",    XTO(31,4,TOLGE), XTO_MASK, POWER,		{ RA, RB } },
+{ "twlnl",   XTO(31,4,TOLNL), XTO_MASK, PPC,		{ RA, RB } },
+{ "tlnl",    XTO(31,4,TOLNL), XTO_MASK, POWER,		{ RA, RB } },
+{ "twlle",   XTO(31,4,TOLLE), XTO_MASK, PPC,		{ RA, RB } },
+{ "tlle",    XTO(31,4,TOLLE), XTO_MASK, POWER,		{ RA, RB } },
+{ "twlng",   XTO(31,4,TOLNG), XTO_MASK, PPC,		{ RA, RB } },
+{ "tlng",    XTO(31,4,TOLNG), XTO_MASK, POWER,		{ RA, RB } },
+{ "twgt",    XTO(31,4,TOGT), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tgt",     XTO(31,4,TOGT), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twge",    XTO(31,4,TOGE), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tge",     XTO(31,4,TOGE), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twnl",    XTO(31,4,TONL), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tnl",     XTO(31,4,TONL), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twlt",    XTO(31,4,TOLT), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tlt",     XTO(31,4,TOLT), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twle",    XTO(31,4,TOLE), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tle",     XTO(31,4,TOLE), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twng",    XTO(31,4,TONG), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tng",     XTO(31,4,TONG), XTO_MASK,	POWER,		{ RA, RB } },
+{ "twne",    XTO(31,4,TONE), XTO_MASK,	PPC,		{ RA, RB } },
+{ "tne",     XTO(31,4,TONE), XTO_MASK,	POWER,		{ RA, RB } },
+{ "trap",    XTO(31,4,TOU), 0xffffffff,	PPC,		{ 0 } },
+{ "tw",      X(31,4),	X_MASK,		PPC,		{ TO, RA, RB } },
+{ "t",       X(31,4),	X_MASK,		POWER,		{ TO, RA, RB } },
+
+{ "subfc",   XO(31,8,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sf",      XO(31,8,0,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subc",    XO(31,8,0,0), XO_MASK,	PPC,		{ RT, RB, RA } },
+{ "subfc.",  XO(31,8,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sf.",     XO(31,8,0,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subc.",   XO(31,8,0,1), XO_MASK,	PPC,		{ RT, RB, RA } },
+{ "subfco",  XO(31,8,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sfo",     XO(31,8,1,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subco",   XO(31,8,1,0), XO_MASK,	PPC,		{ RT, RB, RA } },
+{ "subfco.", XO(31,8,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sfo.",    XO(31,8,1,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subco.",  XO(31,8,1,1), XO_MASK,	PPC,		{ RT, RB, RA } },
+
+{ "mulhdu",  XO(31,9,0,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "mulhdu.", XO(31,9,0,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+
+{ "addc",    XO(31,10,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "a",       XO(31,10,0,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addc.",   XO(31,10,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "a.",      XO(31,10,0,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addco",   XO(31,10,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "ao",      XO(31,10,1,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addco.",  XO(31,10,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "ao.",     XO(31,10,1,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+
+{ "mulhwu",  XO(31,11,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "mulhwu.", XO(31,11,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+
+{ "mfcr",    X(31,19),	XRARB_MASK,	POWER|PPC,	{ RT } },
+
+{ "lwarx",   X(31,20),	X_MASK,		PPC,		{ RT, RA, RB } },
+
+{ "ldx",     X(31,21),	X_MASK,		PPC|B64,	{ RT, RA, RB } },
+
+{ "lwzx",    X(31,23),	X_MASK,		PPC,		{ RT, RA, RB } },
+{ "lx",      X(31,23),	X_MASK,		POWER,		{ RT, RA, RB } },
+
+{ "slw",     XRC(31,24,0), X_MASK,	PPC,		{ RA, RS, RB } },
+{ "sl",      XRC(31,24,0), X_MASK,	POWER,		{ RA, RS, RB } },
+{ "slw.",    XRC(31,24,1), X_MASK,	PPC,		{ RA, RS, RB } },
+{ "sl.",     XRC(31,24,1), X_MASK,	POWER,		{ RA, RS, RB } },
+
+{ "cntlzw",  XRC(31,26,0), XRB_MASK,	PPC,		{ RA, RS } },
+{ "cntlz",   XRC(31,26,0), XRB_MASK,	POWER,		{ RA, RS } },
+{ "cntlzw.", XRC(31,26,1), XRB_MASK,	PPC,		{ RA, RS } },
+{ "cntlz.",  XRC(31,26,1), XRB_MASK, 	POWER,		{ RA, RS } },
+
+{ "sld",     XRC(31,27,0), X_MASK,	PPC|B64,	{ RA, RS, RB } },
+{ "sld.",    XRC(31,27,1), X_MASK,	PPC|B64,	{ RA, RS, RB } },
+
+{ "and",     XRC(31,28,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "and.",    XRC(31,28,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "maskg",   XRC(31,29,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "maskg.",  XRC(31,29,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "cmplw",   XCMPL(31,32,0), XCMPL_MASK, PPC,		{ OBF, RA, RB } },
+{ "cmpld",   XCMPL(31,32,1), XCMPL_MASK, PPC|B64,	{ OBF, RA, RB } },
+{ "cmpl",    X(31,32),	XCMP_MASK,	PPC,		{ BF, L, RA, RB } },
+{ "cmpl",    X(31,32),	XCMPL_MASK,	POWER,		{ BF, RA, RB } },
+
+{ "subf",    XO(31,40,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sub",     XO(31,40,0,0), XO_MASK,	PPC,		{ RT, RB, RA } },
+{ "subf.",   XO(31,40,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sub.",    XO(31,40,0,1), XO_MASK,	PPC,		{ RT, RB, RA } },
+{ "subfo",   XO(31,40,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "subo",    XO(31,40,1,0), XO_MASK,	PPC,		{ RT, RB, RA } },
+{ "subfo.",  XO(31,40,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "subo.",   XO(31,40,1,1), XO_MASK,	PPC,		{ RT, RB, RA } },
+
+{ "ldux",    X(31,53),	X_MASK,		PPC|B64,	{ RT, RAL, RB } },
+
+{ "dcbst",   X(31,54),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "lwzux",   X(31,55),	X_MASK,		PPC,		{ RT, RAL, RB } },
+{ "lux",     X(31,55),	X_MASK,		POWER,		{ RT, RA, RB } },
+
+{ "cntlzd",  XRC(31,58,0), XRB_MASK,	PPC|B64,	{ RA, RS } },
+{ "cntlzd.", XRC(31,58,1), XRB_MASK,	PPC|B64,	{ RA, RS } },
+
+{ "andc",    XRC(31,60,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "andc.",   XRC(31,60,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "tdlgt",   XTO(31,68,TOLGT), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdllt",   XTO(31,68,TOLLT), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdeq",    XTO(31,68,TOEQ), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdlge",   XTO(31,68,TOLGE), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdlnl",   XTO(31,68,TOLNL), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdlle",   XTO(31,68,TOLLE), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdlng",   XTO(31,68,TOLNG), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdgt",    XTO(31,68,TOGT), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdge",    XTO(31,68,TOGE), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdnl",    XTO(31,68,TONL), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdlt",    XTO(31,68,TOLT), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdle",    XTO(31,68,TOLE), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdng",    XTO(31,68,TONG), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "tdne",    XTO(31,68,TONE), XTO_MASK, PPC|B64,	{ RA, RB } },
+{ "td",	     X(31,68),	X_MASK,		PPC|B64,	{ TO, RA, RB } },
+
+{ "mulhd",   XO(31,73,0,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "mulhd.",  XO(31,73,0,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+
+{ "mulhw",   XO(31,75,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "mulhw.",  XO(31,75,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+
+{ "mfmsr",   X(31,83),	XRARB_MASK,	PPC|POWER,	{ RT } },
+
+{ "ldarx",   X(31,84),	X_MASK,		PPC|B64,	{ RT, RA, RB } },
+
+{ "dcbf",    X(31,86),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "lbzx",    X(31,87),	X_MASK,		PPC|POWER,	{ RT, RA, RB } },
+
+{ "neg",     XO(31,104,0,0), XORB_MASK,	PPC|POWER,	{ RT, RA } },
+{ "neg.",    XO(31,104,0,1), XORB_MASK,	PPC|POWER,	{ RT, RA } },
+{ "nego",    XO(31,104,1,0), XORB_MASK,	PPC|POWER,	{ RT, RA } },
+{ "nego.",   XO(31,104,1,1), XORB_MASK,	PPC|POWER,	{ RT, RA } },
+
+{ "mul",     XO(31,107,0,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "mul.",    XO(31,107,0,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "mulo",    XO(31,107,1,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "mulo.",   XO(31,107,1,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+
+{ "clf",     X(31,118), XRB_MASK,	POWER,		{ RT, RA } },
+
+{ "lbzux",   X(31,119),	X_MASK,		PPC|POWER,	{ RT, RAL, RB } },
+
+{ "not",     XRC(31,124,0), X_MASK,	PPC|POWER,	{ RA, RS, RBS } },
+{ "nor",     XRC(31,124,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "not.",    XRC(31,124,1), X_MASK,	PPC|POWER,	{ RA, RS, RBS } },
+{ "nor.",    XRC(31,124,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "subfe",   XO(31,136,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sfe",     XO(31,136,0,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subfe.",  XO(31,136,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sfe.",    XO(31,136,0,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subfeo",  XO(31,136,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sfeo",    XO(31,136,1,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "subfeo.", XO(31,136,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "sfeo.",   XO(31,136,1,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+
+{ "adde",    XO(31,138,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "ae",      XO(31,138,0,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "adde.",   XO(31,138,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "ae.",     XO(31,138,0,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addeo",   XO(31,138,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "aeo",     XO(31,138,1,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addeo.",  XO(31,138,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "aeo.",    XO(31,138,1,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+
+{ "mtcr",    XFXM(31,144,0xff), XFXFXM_MASK|FXM_MASK, PPC|POWER, { RS }},
+{ "mtcrf",   X(31,144),	XFXFXM_MASK,	PPC|POWER,	{ FXM, RS } },
+
+{ "mtmsr",   X(31,146),	XRARB_MASK,	PPC|POWER,	{ RS } },
+
+{ "stdx",    X(31,149), X_MASK,		PPC|B64,	{ RS, RA, RB } },
+
+{ "stwcx.",  XRC(31,150,1), X_MASK,	PPC,		{ RS, RA, RB } },
+
+{ "stwx",    X(31,151), X_MASK,		PPC,		{ RS, RA, RB } },
+{ "stx",     X(31,151), X_MASK,		POWER,		{ RS, RA, RB } },
+
+{ "slq",     XRC(31,152,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "slq.",    XRC(31,152,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "sle",     XRC(31,153,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "sle.",    XRC(31,153,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "stdux",   X(31,181),	X_MASK,		PPC|B64,	{ RS, RAS, RB } },
+
+{ "stwux",   X(31,183),	X_MASK,		PPC,		{ RS, RAS, RB } },
+{ "stux",    X(31,183),	X_MASK,		POWER,		{ RS, RA, RB } },
+
+{ "sliq",    XRC(31,184,0), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+{ "sliq.",   XRC(31,184,1), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+
+{ "subfze",  XO(31,200,0,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfze",    XO(31,200,0,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "subfze.", XO(31,200,0,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfze.",   XO(31,200,0,1), XORB_MASK, POWER,		{ RT, RA } },
+{ "subfzeo", XO(31,200,1,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfzeo",   XO(31,200,1,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "subfzeo.",XO(31,200,1,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfzeo.",  XO(31,200,1,1), XORB_MASK, POWER,		{ RT, RA } },
+
+{ "addze",   XO(31,202,0,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "aze",     XO(31,202,0,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "addze.",  XO(31,202,0,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "aze.",    XO(31,202,0,1), XORB_MASK, POWER,		{ RT, RA } },
+{ "addzeo",  XO(31,202,1,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "azeo",    XO(31,202,1,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "addzeo.", XO(31,202,1,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "azeo.",   XO(31,202,1,1), XORB_MASK, POWER,		{ RT, RA } },
+
+{ "mtsr",    X(31,210),	XRB_MASK|(1<<20), PPC|POWER|B32, { SR, RS } },
+
+{ "stdcx.",  XRC(31,214,1), X_MASK,	PPC|B64,	{ RS, RA, RB } },
+
+{ "stbx",    X(31,215),	X_MASK,		PPC|POWER,	{ RS, RA, RB } },
+
+{ "sllq",    XRC(31,216,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "sllq.",   XRC(31,216,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "sleq",    XRC(31,217,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "sleq.",   XRC(31,217,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "subfme",  XO(31,232,0,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfme",    XO(31,232,0,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "subfme.", XO(31,232,0,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfme.",   XO(31,232,0,1), XORB_MASK, POWER,		{ RT, RA } },
+{ "subfmeo", XO(31,232,1,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfmeo",   XO(31,232,1,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "subfmeo.",XO(31,232,1,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "sfmeo.",  XO(31,232,1,1), XORB_MASK, POWER,		{ RT, RA } },
+
+{ "mulld",   XO(31,233,0,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "mulld.",  XO(31,233,0,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "mulldo",  XO(31,233,1,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "mulldo.", XO(31,233,1,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+
+{ "addme",   XO(31,234,0,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "ame",     XO(31,234,0,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "addme.",  XO(31,234,0,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "ame.",    XO(31,234,0,1), XORB_MASK, POWER,		{ RT, RA } },
+{ "addmeo",  XO(31,234,1,0), XORB_MASK, PPC,		{ RT, RA } },
+{ "ameo",    XO(31,234,1,0), XORB_MASK, POWER,		{ RT, RA } },
+{ "addmeo.", XO(31,234,1,1), XORB_MASK, PPC,		{ RT, RA } },
+{ "ameo.",   XO(31,234,1,1), XORB_MASK, POWER,		{ RT, RA } },
+
+{ "mullw",   XO(31,235,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "muls",    XO(31,235,0,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "mullw.",  XO(31,235,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "muls.",   XO(31,235,0,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "mullwo",  XO(31,235,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "mulso",   XO(31,235,1,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "mullwo.", XO(31,235,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "mulso.",  XO(31,235,1,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+
+{ "mtsrin",  X(31,242),	XRA_MASK,	PPC|B32,	{ RS, RB } },
+{ "mtsri",   X(31,242),	XRA_MASK,	POWER|B32,	{ RS, RB } },
+
+{ "dcbtst",  X(31,246),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "stbux",   X(31,247),	X_MASK,		PPC|POWER,	{ RS, RAS, RB } },
+
+{ "slliq",   XRC(31,248,0), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+{ "slliq.",  XRC(31,248,1), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+
+{ "doz",     XO(31,264,0,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "doz.",    XO(31,264,0,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "dozo",    XO(31,264,1,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "dozo.",   XO(31,264,1,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+
+{ "add",     XO(31,266,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "cax",     XO(31,266,0,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "add.",    XO(31,266,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "cax.",    XO(31,266,0,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addo",    XO(31,266,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "caxo",    XO(31,266,1,0), XO_MASK,	POWER,		{ RT, RA, RB } },
+{ "addo.",   XO(31,266,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "caxo.",   XO(31,266,1,1), XO_MASK,	POWER,		{ RT, RA, RB } },
+
+{ "lscbx",   XRC(31,277,0), X_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "lscbx.",  XRC(31,277,1), X_MASK,	POWER|M601,	{ RT, RA, RB } },
+
+{ "dcbt",    X(31,278),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "lhzx",    X(31,279),	X_MASK,		PPC|POWER,	{ RT, RA, RB } },
+
+{ "icbt",    X(31,262),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "eqv",     XRC(31,284,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "eqv.",    XRC(31,284,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "tlbie",   X(31,306),	XRTRA_MASK,	PPC,		{ RB } },
+{ "tlbi",    X(31,306),	XRTRA_MASK,	POWER,		{ RB } },
+
+{ "eciwx",   X(31,310), X_MASK,		PPC,		{ RT, RA, RB } },
+
+{ "lhzux",   X(31,311),	X_MASK,		PPC|POWER,	{ RT, RAL, RB } },
+
+{ "xor",     XRC(31,316,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "xor.",    XRC(31,316,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "mfdcr",   X(31,323),	X_MASK,		PPC,		{ RT, SPR } },
+
+{ "div",     XO(31,331,0,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "div.",    XO(31,331,0,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "divo",    XO(31,331,1,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "divo.",   XO(31,331,1,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+
+{ "mfmq",    XSPR(31,339,0), XSPR_MASK,	POWER|M601,	{ RT } },
+{ "mfxer",   XSPR(31,339,1), XSPR_MASK,	PPC|POWER,	{ RT } },
+{ "mfrtcu",  XSPR(31,339,4), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfrtcl",  XSPR(31,339,5), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfdec",   XSPR(31,339,6), XSPR_MASK, POWER|M601,	{ RT } },
+{ "mflr",    XSPR(31,339,8), XSPR_MASK,	PPC|POWER,	{ RT } },
+{ "mfctr",   XSPR(31,339,9), XSPR_MASK,	PPC|POWER,	{ RT } },
+{ "mftid",   XSPR(31,339,17), XSPR_MASK, POWER,		{ RT } },
+{ "mfdsisr", XSPR(31,339,18), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfdar",   XSPR(31,339,19), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfdec",   XSPR(31,339,22), XSPR_MASK, PPC,		{ RT } },
+{ "mfsdr0",  XSPR(31,339,24), XSPR_MASK, POWER,		{ RT } },
+{ "mfsdr1",  XSPR(31,339,25), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfsrr0",  XSPR(31,339,26), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfsrr1",  XSPR(31,339,27), XSPR_MASK, PPC|POWER,	{ RT } },
+{ "mfsprg",  XSPR(31,339,272), XSPRG_MASK, PPC,		{ RT, SPRG } },
+{ "mfasr",   XSPR(31,339,280), XSPR_MASK, PPC|B64,	{ RT } },
+{ "mfear",   XSPR(31,339,282), XSPR_MASK, PPC,		{ RT } },
+{ "mfpvr",   XSPR(31,339,287), XSPR_MASK, PPC,		{ RT } },
+{ "mfibatu", XSPR(31,339,528), XSPRBAT_MASK, PPC,	{ RT, SPRBAT } },
+{ "mfibatl", XSPR(31,339,529), XSPRBAT_MASK, PPC,	{ RT, SPRBAT } },
+{ "mfdbatu", XSPR(31,339,536), XSPRBAT_MASK, PPC,	{ RT, SPRBAT } },
+{ "mfdbatl", XSPR(31,339,537), XSPRBAT_MASK, PPC,	{ RT, SPRBAT } },
+{ "mfspr",   X(31,339),	X_MASK,		PPC|POWER,	{ RT, SPR } },
+
+{ "lwax",    X(31,341),	X_MASK,		PPC|B64,	{ RT, RA, RB } },
+
+{ "lhax",    X(31,343),	X_MASK,		PPC|POWER,	{ RT, RA, RB } },
+
+{ "dccci",   X(31,454),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "abs",     XO(31,360,0,0), XORB_MASK, POWER|M601,	{ RT, RA } },
+{ "abs.",    XO(31,360,0,1), XORB_MASK, POWER|M601,	{ RT, RA } },
+{ "abso",    XO(31,360,1,0), XORB_MASK, POWER|M601,	{ RT, RA } },
+{ "abso.",   XO(31,360,1,1), XORB_MASK, POWER|M601,	{ RT, RA } },
+
+{ "divs",    XO(31,363,0,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "divs.",   XO(31,363,0,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "divso",   XO(31,363,1,0), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+{ "divso.",  XO(31,363,1,1), XO_MASK,	POWER|M601,	{ RT, RA, RB } },
+
+{ "tlbia",   X(31,370),	0xffffffff,	PPC,		{ 0 } },
+
+{ "mftbu",   XSPR(31,371,269), XSPR_MASK, PPC,		{ RT } },
+{ "mftb",    X(31,371),	X_MASK,		PPC,		{ RT, TBR } },
+
+{ "lwaux",   X(31,373),	X_MASK,		PPC|B64,	{ RT, RAL, RB } },
+
+{ "lhaux",   X(31,375),	X_MASK,		PPC|POWER,	{ RT, RAL, RB } },
+
+{ "sthx",    X(31,407),	X_MASK,		PPC|POWER,	{ RS, RA, RB } },
+
+{ "lfqx",    X(31,791),	X_MASK,		POWER2,		{ FRT, RA, RB } },
+
+{ "lfqux",   X(31,823),	X_MASK,		POWER2,		{ FRT, RA, RB } },
+
+{ "stfqx",   X(31,919),	X_MASK,		POWER2,		{ FRS, RA, RB } },
+
+{ "stfqux",  X(31,951),	X_MASK,		POWER2,		{ FRS, RA, RB } },
+
+{ "orc",     XRC(31,412,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "orc.",    XRC(31,412,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "sradi",   XS(31,413,0), XS_MASK,	PPC|B64,	{ RA, RS, SH6 } },
+{ "sradi.",  XS(31,413,1), XS_MASK,	PPC|B64,	{ RA, RS, SH6 } },
+
+{ "slbie",   X(31,434),	XRTRA_MASK,	PPC|B64,	{ RB } },
+
+{ "ecowx",   X(31,438),	X_MASK,		PPC,		{ RT, RA, RB } },
+
+{ "sthux",   X(31,439),	X_MASK,		PPC|POWER,	{ RS, RAS, RB } },
+
+{ "mr",	     XRC(31,444,0), X_MASK,	PPC|POWER,	{ RA, RS, RBS } },
+{ "or",      XRC(31,444,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "mr.",     XRC(31,444,1), X_MASK,	PPC|POWER,	{ RA, RS, RBS } },
+{ "or.",     XRC(31,444,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "mtdcr",   X(31,451),	X_MASK,		PPC,		{ SPR, RS } },
+
+{ "divdu",   XO(31,457,0,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "divdu.",  XO(31,457,0,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "divduo",  XO(31,457,1,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "divduo.", XO(31,457,1,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+
+{ "divwu",   XO(31,459,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "divwu.",  XO(31,459,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "divwuo",  XO(31,459,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "divwuo.", XO(31,459,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+
+{ "mtmq",    XSPR(31,467,0), XSPR_MASK,	POWER|M601,	{ RS } },
+{ "mtxer",   XSPR(31,467,1), XSPR_MASK,	PPC|POWER,	{ RS } },
+{ "mtlr",    XSPR(31,467,8), XSPR_MASK,	PPC|POWER,	{ RS } },
+{ "mtctr",   XSPR(31,467,9), XSPR_MASK,	PPC|POWER,	{ RS } },
+{ "mttid",   XSPR(31,467,17), XSPR_MASK, POWER,		{ RS } },
+{ "mtdsisr", XSPR(31,467,18), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtdar",   XSPR(31,467,19), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtrtcu",  XSPR(31,467,20), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtrtcl",  XSPR(31,467,21), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtdec",   XSPR(31,467,22), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtsdr0",  XSPR(31,467,24), XSPR_MASK, POWER,		{ RS } },
+{ "mtsdr1",  XSPR(31,467,25), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtsrr0",  XSPR(31,467,26), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtsrr1",  XSPR(31,467,27), XSPR_MASK, PPC|POWER,	{ RS } },
+{ "mtsprg",  XSPR(31,467,272), XSPRG_MASK, PPC,		{ SPRG, RS } },
+{ "mtasr",   XSPR(31,467,280), XSPR_MASK, PPC|B64,	{ RS } },
+{ "mtear",   XSPR(31,467,282), XSPR_MASK, PPC,		{ RS } },
+{ "mttbl",   XSPR(31,467,284), XSPR_MASK, PPC,		{ RS } },
+{ "mttbu",   XSPR(31,467,285), XSPR_MASK, PPC,		{ RS } },
+{ "mtibatu", XSPR(31,467,528), XSPRBAT_MASK, PPC,	{ SPRBAT, RS } },
+{ "mtibatl", XSPR(31,467,529), XSPRBAT_MASK, PPC,	{ SPRBAT, RS } },
+{ "mtdbatu", XSPR(31,467,536), XSPRBAT_MASK, PPC,	{ SPRBAT, RS } },
+{ "mtdbatl", XSPR(31,467,537), XSPRBAT_MASK, PPC,	{ SPRBAT, RS } },
+{ "mtspr",   X(31,467),	X_MASK,		PPC|POWER,	{ SPR, RS } },
+
+{ "dcbi",    X(31,470),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "nand",    XRC(31,476,0), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+{ "nand.",   XRC(31,476,1), X_MASK,	PPC|POWER,	{ RA, RS, RB } },
+
+{ "nabs",    XO(31,488,0,0), XORB_MASK, POWER|M601,	{ RT, RA } },
+{ "nabs.",   XO(31,488,0,1), XORB_MASK, POWER|M601,	{ RT, RA } },
+{ "nabso",   XO(31,488,1,0), XORB_MASK, POWER|M601,	{ RT, RA } },
+{ "nabso.",  XO(31,488,1,1), XORB_MASK, POWER|M601,	{ RT, RA } },
+
+{ "divd",    XO(31,489,0,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "divd.",   XO(31,489,0,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "divdo",   XO(31,489,1,0), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+{ "divdo.",  XO(31,489,1,1), XO_MASK,	PPC|B64,	{ RT, RA, RB } },
+
+{ "divw",    XO(31,491,0,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "divw.",   XO(31,491,0,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "divwo",   XO(31,491,1,0), XO_MASK,	PPC,		{ RT, RA, RB } },
+{ "divwo.",  XO(31,491,1,1), XO_MASK,	PPC,		{ RT, RA, RB } },
+
+{ "slbia",   X(31,498),	0xffffffff,	PPC|B64,	{ 0 } },
+
+{ "cli",     X(31,502), XRB_MASK,	POWER,		{ RT, RA } },
+
+{ "mcrxr",   X(31,512),	XRARB_MASK|(3<<21), PPC|POWER,	{ BF } },
+
+{ "clcs",    X(31,531), XRB_MASK,	POWER|M601,	{ RT, RA } },
+
+{ "lswx",    X(31,533),	X_MASK,		PPC,		{ RT, RA, RB } },
+{ "lsx",     X(31,533),	X_MASK,		POWER,		{ RT, RA, RB } },
+
+{ "lwbrx",   X(31,534),	X_MASK,		PPC,		{ RT, RA, RB } },
+{ "lbrx",    X(31,534),	X_MASK,		POWER,		{ RT, RA, RB } },
+
+{ "lfsx",    X(31,535),	X_MASK,		PPC|POWER,	{ FRT, RA, RB } },
+
+{ "srw",     XRC(31,536,0), X_MASK,	PPC,		{ RA, RS, RB } },
+{ "sr",      XRC(31,536,0), X_MASK,	POWER,		{ RA, RS, RB } },
+{ "srw.",    XRC(31,536,1), X_MASK,	PPC,		{ RA, RS, RB } },
+{ "sr.",     XRC(31,536,1), X_MASK,	POWER,		{ RA, RS, RB } },
+
+{ "rrib",    XRC(31,537,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "rrib.",   XRC(31,537,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "srd",     XRC(31,539,0), X_MASK,	PPC|B64,	{ RA, RS, RB } },
+{ "srd.",    XRC(31,539,1), X_MASK,	PPC|B64,	{ RA, RS, RB } },
+
+{ "maskir",  XRC(31,541,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "maskir.", XRC(31,541,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "tlbsync", X(31,566),	0xffffffff,	PPC,		{ 0 } },
+
+{ "lfsux",   X(31,567),	X_MASK,		PPC|POWER,	{ FRT, RAS, RB } },
+
+{ "mfsr",    X(31,595),	XRB_MASK|(1<<20), PPC|POWER|B32, { RT, SR } },
+
+{ "lswi",    X(31,597),	X_MASK,		PPC,		{ RT, RA, NB } },
+{ "lsi",     X(31,597),	X_MASK,		POWER,		{ RT, RA, NB } },
+
+{ "sync",    X(31,598), 0xffffffff,	PPC,		{ 0 } },
+{ "dcs",     X(31,598), 0xffffffff,	POWER,		{ 0 } },
+
+{ "lfdx",    X(31,599), X_MASK,		PPC|POWER,	{ FRT, RA, RB } },
+
+{ "mfsri",   X(31,627), X_MASK,		POWER,		{ RT, RA, RB } },
+
+{ "dclst",   X(31,630), XRB_MASK,	POWER,		{ RS, RA } },
+
+{ "lfdux",   X(31,631), X_MASK,		PPC|POWER,	{ FRT, RAS, RB } },
+
+{ "mfsrin",  X(31,659), XRA_MASK,	PPC|B32,	{ RT, RB } },
+
+{ "stswx",   X(31,661), X_MASK,		PPC,		{ RS, RA, RB } },
+{ "stsx",    X(31,661), X_MASK,		POWER,		{ RS, RA, RB } },
+
+{ "stwbrx",  X(31,662), X_MASK,		PPC,		{ RS, RA, RB } },
+{ "stbrx",   X(31,662), X_MASK,		POWER,		{ RS, RA, RB } },
+
+{ "stfsx",   X(31,663), X_MASK,		PPC|POWER,	{ FRS, RA, RB } },
+
+{ "srq",     XRC(31,664,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "srq.",    XRC(31,664,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "sre",     XRC(31,665,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "sre.",    XRC(31,665,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "stfsux",  X(31,695),	X_MASK,		PPC|POWER,	{ FRS, RAS, RB } },
+
+{ "sriq",    XRC(31,696,0), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+{ "sriq.",   XRC(31,696,1), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+
+{ "stswi",   X(31,725),	X_MASK,		PPC,		{ RS, RA, NB } },
+{ "stsi",    X(31,725),	X_MASK,		POWER,		{ RS, RA, NB } },
+
+{ "stfdx",   X(31,727),	X_MASK,		PPC|POWER,	{ FRS, RA, RB } },
+
+{ "srlq",    XRC(31,728,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "srlq.",   XRC(31,728,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "sreq",    XRC(31,729,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "sreq.",   XRC(31,729,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "stfdux",  X(31,759),	X_MASK,		PPC|POWER,	{ FRS, RAS, RB } },
+
+{ "srliq",   XRC(31,760,0), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+{ "srliq.",  XRC(31,760,1), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+
+{ "lhbrx",   X(31,790),	X_MASK,		PPC|POWER,	{ RT, RA, RB } },
+
+{ "sraw",    XRC(31,792,0), X_MASK,	PPC,		{ RA, RS, RB } },
+{ "sra",     XRC(31,792,0), X_MASK,	POWER,		{ RA, RS, RB } },
+{ "sraw.",   XRC(31,792,1), X_MASK,	PPC,		{ RA, RS, RB } },
+{ "sra.",    XRC(31,792,1), X_MASK,	POWER,		{ RA, RS, RB } },
+
+{ "srad",    XRC(31,794,0), X_MASK,	PPC|B64,	{ RA, RS, RB } },
+{ "srad.",   XRC(31,794,1), X_MASK,	PPC|B64,	{ RA, RS, RB } },
+
+{ "rac",     X(31,818),	X_MASK,		POWER,		{ RT, RA, RB } },
+
+{ "srawi",   XRC(31,824,0), X_MASK,	PPC,		{ RA, RS, SH } },
+{ "srai",    XRC(31,824,0), X_MASK,	POWER,		{ RA, RS, SH } },
+{ "srawi.",  XRC(31,824,1), X_MASK,	PPC,		{ RA, RS, SH } },
+{ "srai.",   XRC(31,824,1), X_MASK,	POWER,		{ RA, RS, SH } },
+
+{ "eieio",   X(31,854),	0xffffffff,	PPC,		{ 0 } },
+
+{ "sthbrx",  X(31,918),	X_MASK,		PPC|POWER,	{ RS, RA, RB } },
+
+{ "sraq",    XRC(31,920,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "sraq.",   XRC(31,920,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "srea",    XRC(31,921,0), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+{ "srea.",   XRC(31,921,1), X_MASK,	POWER|M601,	{ RA, RS, RB } },
+
+{ "extsh",   XRC(31,922,0), XRB_MASK,	PPC,		{ RA, RS } },
+{ "exts",    XRC(31,922,0), XRB_MASK,	POWER,		{ RA, RS } },
+{ "extsh.",  XRC(31,922,1), XRB_MASK,	PPC,		{ RA, RS } },
+{ "exts.",   XRC(31,922,1), XRB_MASK,	POWER,		{ RA, RS } },
+
+{ "sraiq",   XRC(31,952,0), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+{ "sraiq.",  XRC(31,952,1), X_MASK,	POWER|M601,	{ RA, RS, SH } },
+
+{ "extsb",   XRC(31,954,0), XRB_MASK,	PPC,		{ RA, RS} },
+{ "extsb.",  XRC(31,954,1), XRB_MASK,	PPC,		{ RA, RS} },
+
+{ "iccci",   X(31,966),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "icbi",    X(31,982),	XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "stfiwx",  X(31,983),	X_MASK,		PPC,		{ FRS, RA, RB } },
+
+{ "extsw",   XRC(31,986,0), XRB_MASK,	PPC,		{ RA, RS } },
+{ "extsw.",  XRC(31,986,1), XRB_MASK,	PPC,		{ RA, RS } },
+
+{ "dcbz",    X(31,1014), XRT_MASK,	PPC,		{ RA, RB } },
+{ "dclz",    X(31,1014), XRT_MASK,	PPC,		{ RA, RB } },
+
+{ "lwz",     OP(32),	OP_MASK,	PPC,		{ RT, D, RA } },
+{ "l",	     OP(32),	OP_MASK,	POWER,		{ RT, D, RA } },
+
+{ "lwzu",    OP(33),	OP_MASK,	PPC,		{ RT, D, RAL } },
+{ "lu",      OP(33),	OP_MASK,	POWER,		{ RT, D, RA } },
+
+{ "lbz",     OP(34),	OP_MASK,	PPC|POWER,	{ RT, D, RA } },
+
+{ "lbzu",    OP(35),	OP_MASK,	PPC|POWER,	{ RT, D, RAL } },
+
+{ "stw",     OP(36),	OP_MASK,	PPC,		{ RS, D, RA } },
+{ "st",      OP(36),	OP_MASK,	POWER,		{ RS, D, RA } },
+
+{ "stwu",    OP(37),	OP_MASK,	PPC,		{ RS, D, RAS } },
+{ "stu",     OP(37),	OP_MASK,	POWER,		{ RS, D, RA } },
+
+{ "stb",     OP(38),	OP_MASK,	PPC|POWER,	{ RS, D, RA } },
+
+{ "stbu",    OP(39),	OP_MASK,	PPC|POWER,	{ RS, D, RAS } },
+
+{ "lhz",     OP(40),	OP_MASK,	PPC|POWER,	{ RT, D, RA } },
+
+{ "lhzu",    OP(41),	OP_MASK,	PPC|POWER,	{ RT, D, RAL } },
+
+{ "lha",     OP(42),	OP_MASK,	PPC|POWER,	{ RT, D, RA } },
+
+{ "lhau",    OP(43),	OP_MASK,	PPC|POWER,	{ RT, D, RAL } },
+
+{ "sth",     OP(44),	OP_MASK,	PPC|POWER,	{ RS, D, RA } },
+
+{ "sthu",    OP(45),	OP_MASK,	PPC|POWER,	{ RS, D, RAS } },
+
+{ "lmw",     OP(46),	OP_MASK,	PPC,		{ RT, D, RAM } },
+{ "lm",      OP(46),	OP_MASK,	POWER,		{ RT, D, RA } },
+
+{ "stmw",    OP(47),	OP_MASK,	PPC,		{ RS, D, RA } },
+{ "stm",     OP(47),	OP_MASK,	POWER,		{ RS, D, RA } },
+
+{ "lfs",     OP(48),	OP_MASK,	PPC|POWER,	{ FRT, D, RA } },
+
+{ "lfsu",    OP(49),	OP_MASK,	PPC|POWER,	{ FRT, D, RAS } },
+
+{ "lfd",     OP(50),	OP_MASK,	PPC|POWER,	{ FRT, D, RA } },
+
+{ "lfdu",    OP(51),	OP_MASK,	PPC|POWER,	{ FRT, D, RAS } },
+
+{ "stfs",    OP(52),	OP_MASK,	PPC|POWER,	{ FRS, D, RA } },
+
+{ "stfsu",   OP(53),	OP_MASK,	PPC|POWER,	{ FRS, D, RAS } },
+
+{ "stfd",    OP(54),	OP_MASK,	PPC|POWER,	{ FRS, D, RA } },
+
+{ "stfdu",   OP(55),	OP_MASK,	PPC|POWER,	{ FRS, D, RAS } },
+
+{ "lfq",     OP(56),	OP_MASK,	POWER2,		{ FRT, D, RA } },
+
+{ "lfqu",    OP(57),	OP_MASK,	POWER2,		{ FRT, D, RA } },
+
+{ "ld",      DSO(58,0),	DS_MASK,	PPC|B64,	{ RT, DS, RA } },
+
+{ "ldu",     DSO(58,1), DS_MASK,	PPC|B64,	{ RT, DS, RAL } },
+
+{ "lwa",     DSO(58,2), DS_MASK,	PPC|B64,	{ RT, DS, RA } },
+
+{ "fdivs",   A(59,18,0), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fdivs.",  A(59,18,1), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+
+{ "fsubs",   A(59,20,0), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fsubs.",  A(59,20,1), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+
+{ "fadds",   A(59,21,0), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fadds.",  A(59,21,1), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+
+{ "fsqrts",  A(59,22,0), AFRAFRC_MASK,	PPC,		{ FRT, FRB } },
+{ "fsqrts.", A(59,22,1), AFRAFRC_MASK,	PPC,		{ FRT, FRB } },
+
+{ "fres",    A(59,24,0), AFRAFRC_MASK,	PPC,		{ FRT, FRB } },
+{ "fres.",   A(59,24,1), AFRAFRC_MASK,	PPC,		{ FRT, FRB } },
+
+{ "fmuls",   A(59,25,0), AFRB_MASK,	PPC,		{ FRT, FRA, FRC } },
+{ "fmuls.",  A(59,25,1), AFRB_MASK,	PPC,		{ FRT, FRA, FRC } },
+
+{ "fmsubs",  A(59,28,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fmsubs.", A(59,28,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+
+{ "fmadds",  A(59,29,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fmadds.", A(59,29,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+
+{ "fnmsubs", A(59,30,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fnmsubs.",A(59,30,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+
+{ "fnmadds", A(59,31,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fnmadds.",A(59,31,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+
+{ "stfq",    OP(60),	OP_MASK,	POWER2,		{ FRS, D, RA } },
+
+{ "stfqu",   OP(61),	OP_MASK,	POWER2,		{ FRS, D, RA } },
+
+{ "std",     DSO(62,0),	DS_MASK,	PPC|B64,	{ RS, DS, RA } },
+
+{ "stdu",    DSO(62,1),	DS_MASK,	PPC|B64,	{ RS, DS, RAS } },
+
+{ "fcmpu",   X(63,0),	X_MASK|(3<<21),	PPC|POWER,	{ BF, FRA, FRB } },
+
+{ "frsp",    XRC(63,12,0), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+{ "frsp.",   XRC(63,12,1), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+
+{ "fctiw",   XRC(63,14,0), XRA_MASK,	PPC,		{ FRT, FRB } },
+{ "fcir",    XRC(63,14,0), XRA_MASK,	POWER2,		{ FRT, FRB } },
+{ "fctiw.",  XRC(63,14,1), XRA_MASK,	PPC,		{ FRT, FRB } },
+{ "fcir.",   XRC(63,14,1), XRA_MASK,	POWER2,		{ FRT, FRB } },
+
+{ "fctiwz",  XRC(63,15,0), XRA_MASK,	PPC,		{ FRT, FRB } },
+{ "fcirz",   XRC(63,15,0), XRA_MASK,	POWER2,		{ FRT, FRB } },
+{ "fctiwz.", XRC(63,15,1), XRA_MASK,	PPC,		{ FRT, FRB } },
+{ "fcirz.",  XRC(63,15,1), XRA_MASK,	POWER2,		{ FRT, FRB } },
+
+{ "fdiv",    A(63,18,0), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fd",      A(63,18,0), AFRC_MASK,	POWER,		{ FRT, FRA, FRB } },
+{ "fdiv.",   A(63,18,1), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fd.",     A(63,18,1), AFRC_MASK,	POWER,		{ FRT, FRA, FRB } },
+
+{ "fsub",    A(63,20,0), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fs",      A(63,20,0), AFRC_MASK,	POWER,		{ FRT, FRA, FRB } },
+{ "fsub.",   A(63,20,1), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fs.",     A(63,20,1), AFRC_MASK,	POWER,		{ FRT, FRA, FRB } },
+
+{ "fadd",    A(63,21,0), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fa",      A(63,21,0), AFRC_MASK,	POWER,		{ FRT, FRA, FRB } },
+{ "fadd.",   A(63,21,1), AFRC_MASK,	PPC,		{ FRT, FRA, FRB } },
+{ "fa.",     A(63,21,1), AFRC_MASK,	POWER,		{ FRT, FRA, FRB } },
+
+{ "fsqrt",   A(63,22,0), AFRAFRC_MASK,	PPC|POWER2,	{ FRT, FRB } },
+{ "fsqrt.",  A(63,22,1), AFRAFRC_MASK,	PPC|POWER2,	{ FRT, FRB } },
+
+{ "fsel",    A(63,23,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fsel.",   A(63,23,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+
+{ "fmul",    A(63,25,0), AFRB_MASK,	PPC,		{ FRT, FRA, FRC } },
+{ "fm",      A(63,25,0), AFRB_MASK,	POWER,		{ FRT, FRA, FRC } },
+{ "fmul.",   A(63,25,1), AFRB_MASK,	PPC,		{ FRT, FRA, FRC } },
+{ "fm.",     A(63,25,1), AFRB_MASK,	POWER,		{ FRT, FRA, FRC } },
+
+{ "frsqrte", A(63,26,0), AFRAFRC_MASK,	PPC,		{ FRT, FRB } },
+{ "frsqrte.",A(63,26,1), AFRAFRC_MASK,	PPC,		{ FRT, FRB } },
+
+{ "fmsub",   A(63,28,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fms",     A(63,28,0), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+{ "fmsub.",  A(63,28,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fms.",    A(63,28,1), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+
+{ "fmadd",   A(63,29,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fma",     A(63,29,0), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+{ "fmadd.",  A(63,29,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fma.",    A(63,29,1), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+
+{ "fnmsub",  A(63,30,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fnms",    A(63,30,0), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+{ "fnmsub.", A(63,30,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fnms.",   A(63,30,1), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+
+{ "fnmadd",  A(63,31,0), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fnma",    A(63,31,0), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+{ "fnmadd.", A(63,31,1), A_MASK,	PPC,		{ FRT,FRA,FRC,FRB } },
+{ "fnma.",   A(63,31,1), A_MASK,	POWER,		{ FRT,FRA,FRC,FRB } },
+
+{ "fcmpo",   X(63,30),	X_MASK|(3<<21),	PPC|POWER,	{ BF, FRA, FRB } },
+
+{ "mtfsb1",  XRC(63,38,0), XRARB_MASK,	PPC|POWER,	{ BT } },
+{ "mtfsb1.", XRC(63,38,1), XRARB_MASK,	PPC|POWER,	{ BT } },
+
+{ "fneg",    XRC(63,40,0), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+{ "fneg.",   XRC(63,40,1), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+
+{ "mcrfs",   X(63,64),	XRB_MASK|(3<<21)|(3<<16), PPC|POWER, { BF, BFA } },
+
+{ "mtfsb0",  XRC(63,70,0), XRARB_MASK,	PPC|POWER,	{ BT } },
+{ "mtfsb0.", XRC(63,70,1), XRARB_MASK,	PPC|POWER,	{ BT } },
+
+{ "fmr",     XRC(63,72,0), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+{ "fmr.",    XRC(63,72,1), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+
+{ "mtfsfi",  XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), PPC|POWER, { BF, U } },
+{ "mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), PPC|POWER, { BF, U } },
+
+{ "fnabs",   XRC(63,136,0), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+{ "fnabs.",  XRC(63,136,1), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+
+{ "fabs",    XRC(63,264,0), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+{ "fabs.",   XRC(63,264,1), XRA_MASK,	PPC|POWER,	{ FRT, FRB } },
+
+{ "mffs",    XRC(63,583,0), XRARB_MASK,	PPC|POWER,	{ FRT } },
+{ "mffs.",   XRC(63,583,1), XRARB_MASK,	PPC|POWER,	{ FRT } },
+
+{ "mtfsf",   XFL(63,711,0), XFL_MASK,	PPC|POWER,	{ FLM, FRB } },
+{ "mtfsf.",  XFL(63,711,1), XFL_MASK,	PPC|POWER,	{ FLM, FRB } },
+
+{ "fctid",   XRC(63,814,0), XRA_MASK,	PPC|B64,	{ FRT, FRB } },
+{ "fctid.",  XRC(63,814,1), XRA_MASK,	PPC|B64,	{ FRT, FRB } },
+
+{ "fctidz",  XRC(63,815,0), XRA_MASK,	PPC|B64,	{ FRT, FRB } },
+{ "fctidz.", XRC(63,815,1), XRA_MASK,	PPC|B64,	{ FRT, FRB } },
+
+{ "fcfid",   XRC(63,846,0), XRA_MASK,	PPC|B64,	{ FRT, FRB } },
+{ "fcfid.",  XRC(63,846,1), XRA_MASK,	PPC|B64,	{ FRT, FRB } },
+
+};
+
+const int powerpc_num_opcodes =
+  sizeof (powerpc_opcodes) / sizeof (powerpc_opcodes[0]);
+
+/* The macro table.  This is only used by the assembler.  */
+
+const struct powerpc_macro powerpc_macros[] = {
+{ "extldi",  4,   PPC|B64,	"rldicr %0,%1,%3,(%2)-1" },
+{ "extldi.", 4,   PPC|B64,	"rldicr. %0,%1,%3,(%2)-1" },
+{ "extrdi",  4,   PPC|B64,	"rldicl %0,%1,(%2)+(%3),64-(%2)" },
+{ "extrdi.", 4,   PPC|B64,	"rldicl. %0,%1,(%2)+(%3),64-(%2)" },
+{ "insrdi",  4,   PPC|B64,	"rldimi %0,%1,64-((%2)+(%3)),%3" },
+{ "insrdi.", 4,   PPC|B64,	"rldimi. %0,%1,64-((%2)+(%3)),%3" },
+{ "rotrdi",  3,   PPC|B64,	"rldicl %0,%1,64-(%2),0" },
+{ "rotrdi.", 3,   PPC|B64,	"rldicl. %0,%1,64-(%2),0" },
+{ "sldi",    3,   PPC|B64,	"rldicr %0,%1,%2,63-(%2)" },
+{ "sldi.",   3,   PPC|B64,	"rldicr. %0,%1,%2,63-(%2)" },
+{ "srdi",    3,   PPC|B64,	"rldicl %0,%1,64-(%2),%2" },
+{ "srdi.",   3,   PPC|B64,	"rldicl. %0,%1,64-(%2),%2" },
+{ "clrrdi",  3,   PPC|B64,	"rldicr %0,%1,0,63-(%2)" },
+{ "clrrdi.", 3,   PPC|B64,	"rldicr. %0,%1,0,63-(%2)" },
+{ "clrlsldi",4,   PPC|B64,	"rldic %0,%1,%3,(%2)-(%3)" },
+{ "clrlsldi.",4,  PPC|B64,	"rldic. %0,%1,%3,(%2)-(%3)" },
+
+{ "extlwi",  4,   PPC,		"rlwinm %0,%1,%3,0,(%2)-1" },
+{ "extlwi.", 4,   PPC,		"rlwinm. %0,%1,%3,0,(%2)-1" },
+{ "extrwi",  4,   PPC,		"rlwinm %0,%1,(%2)+(%3),32-(%2),31" },
+{ "extrwi.", 4,   PPC,		"rlwinm. %0,%1,(%2)+(%3),32-(%2),31" },
+{ "inslwi",  4,   PPC,		"rlwimi %0,%1,32-(%3),%3,(%2)+(%3)-1" },
+{ "inslwi.", 4,   PPC,		"rlwimi. %0,%1,32-(%3),%3,(%2)+(%3)-1" },
+{ "insrwi",  4,   PPC,		"rlwimi %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1" },
+{ "insrwi.", 4,   PPC,		"rlwimi. %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1"},
+{ "rotrwi",  3,   PPC,		"rlwinm %0,%1,32-(%2),0,31" },
+{ "rotrwi.", 3,   PPC,		"rlwinm. %0,%1,32-(%2),0,31" },
+{ "slwi",    3,   PPC,		"rlwinm %0,%1,%2,0,31-(%2)" },
+{ "sli",     3,   POWER,	"rlinm %0,%1,%2,0,31-(%2)" },
+{ "slwi.",   3,   PPC,		"rlwinm. %0,%1,%2,0,31-(%2)" },
+{ "sli.",    3,   POWER,	"rlinm. %0,%1,%2,0,31-(%2)" },
+{ "srwi",    3,   PPC,		"rlwinm %0,%1,32-(%2),%2,31" },
+{ "sri",     3,   POWER,	"rlinm %0,%1,32-(%2),%2,31" },
+{ "srwi.",   3,   PPC,		"rlwinm. %0,%1,32-(%2),%2,31" },
+{ "sri.",    3,   POWER,	"rlinm. %0,%1,32-(%2),%2,31" },
+{ "clrrwi",  3,   PPC,		"rlwinm %0,%1,0,0,31-(%2)" },
+{ "clrrwi.", 3,   PPC,		"rlwinm. %0,%1,0,0,31-(%2)" },
+{ "clrlslwi",4,   PPC,		"rlwinm %0,%1,%3,(%2)-(%3),31-(%3)" },
+{ "clrlslwi.",4,  PPC,		"rlwinm. %0,%1,%3,(%2)-(%3),31-(%3)" },
+
+};
+
+const int powerpc_num_macros =
+  sizeof (powerpc_macros) / sizeof (powerpc_macros[0]);
diff -urN linux-2.2.12-pre6/arch/ppc/xmon/privinst.h linux-2.2.12-pre7/arch/ppc/xmon/privinst.h
--- linux-2.2.12-pre6/arch/ppc/xmon/privinst.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/xmon/privinst.h	2003-08-15 15:07:07.000000000 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+
+#define GETREG(reg)		\
+    static inline int get_ ## reg (void)	\
+	{ int ret; asm volatile ("mf" #reg " %0" : "=r" (ret) :); return ret; }
+
+#define SETREG(reg)		\
+    static inline void set_ ## reg (int val)	\
+	{ asm volatile ("mt" #reg " %0" : : "r" (val)); }
+
+GETREG(msr)
+SETREG(msr)
+GETREG(cr)
+
+#define GSETSPR(n, name)	\
+    static inline int get_ ## name (void) \
+	{ int ret; asm volatile ("mfspr %0," #n : "=r" (ret) : ); return ret; } \
+    static inline void set_ ## name (int val) \
+	{ asm volatile ("mtspr " #n ",%0" : : "r" (val)); }
+
+GSETSPR(0, mq)
+GSETSPR(1, xer)
+GSETSPR(4, rtcu)
+GSETSPR(5, rtcl)
+GSETSPR(8, lr)
+GSETSPR(9, ctr)
+GSETSPR(18, dsisr)
+GSETSPR(19, dar)
+GSETSPR(22, dec)
+GSETSPR(25, sdr1)
+GSETSPR(26, srr0)
+GSETSPR(27, srr1)
+GSETSPR(272, sprg0)
+GSETSPR(273, sprg1)
+GSETSPR(274, sprg2)
+GSETSPR(275, sprg3)
+GSETSPR(282, ear)
+GSETSPR(287, pvr)
+GSETSPR(528, bat0u)
+GSETSPR(529, bat0l)
+GSETSPR(530, bat1u)
+GSETSPR(531, bat1l)
+GSETSPR(532, bat2u)
+GSETSPR(533, bat2l)
+GSETSPR(534, bat3u)
+GSETSPR(535, bat3l)
+GSETSPR(1008, hid0)
+GSETSPR(1009, hid1)
+GSETSPR(1010, iabr)
+GSETSPR(1013, dabr)
+GSETSPR(1023, pir)
+
+static inline int get_sr(int n)
+{
+    int ret;
+
+    asm (" mfsrin %0,%1" : "=r" (ret) : "r" (n << 28));
+    return ret;
+}
+
+static inline void set_sr(int n, int val)
+{
+    asm ("mtsrin %0,%1" : : "r" (val), "r" (n << 28));
+}
+
+static inline void store_inst(void *p)
+{
+    asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
+}
+
+
diff -urN linux-2.2.12-pre6/arch/ppc/xmon/setjmp.c linux-2.2.12-pre7/arch/ppc/xmon/setjmp.c
--- linux-2.2.12-pre6/arch/ppc/xmon/setjmp.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/xmon/setjmp.c	2003-08-15 15:07:07.000000000 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * NB this file must be compiled with -O2.
+ */
+
+int
+xmon_setjmp(long *buf)
+{
+    asm ("mflr 0; stw 0,0(%0);"
+	 "stw 1,4(%0); stw 2,8(%0);"
+	 "mfcr 0; stw 0,12(%0);"
+	 "stmw 13,16(%0)"
+	 : : "r" (buf));
+    /* XXX should save fp regs as well */
+    return 0;
+}
+
+void
+xmon_longjmp(long *buf, int val)
+{
+    if (val == 0)
+	val = 1;
+    asm ("lmw 13,16(%0);"
+	 "lwz 0,12(%0); mtcrf 0x38,0;"
+	 "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
+	 "mtlr 0; mr 3,%1"
+	 : : "r" (buf), "r" (val));
+}
diff -urN linux-2.2.12-pre6/arch/ppc/xmon/start.c linux-2.2.12-pre7/arch/ppc/xmon/start.c
--- linux-2.2.12-pre6/arch/ppc/xmon/start.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/xmon/start.c	2003-08-15 15:07:07.000000000 -0700
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include <linux/config.h>
+#include <linux/string.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/adb.h>
+#include <asm/prom.h>
+#include <asm/bootx.h>
+#include <asm/pmu.h>
+
+static volatile unsigned char *sccc, *sccd;
+unsigned long TXRDY, RXRDY;
+extern void xmon_printf(const char *fmt, ...);
+extern void map_bootx_text(void);
+extern void drawchar(char);
+extern void drawstring(const char *str);
+
+static int console = 0;
+static int use_screen = 0;
+
+void buf_access(void)
+{
+	if ( _machine == _MACH_chrp )
+		sccd[3] &= ~0x80;	/* reset DLAB */
+}
+
+void
+xmon_map_scc(void)
+{
+	volatile unsigned char *base;
+
+	if ( _machine == _MACH_Pmac )
+	{
+		struct device_node *np;
+		extern boot_infos_t *boot_infos;
+		unsigned long addr;
+
+#ifdef CONFIG_BOOTX_TEXT
+		if (boot_infos != 0 && find_via_pmu()) {
+			printk(KERN_INFO "xmon uses screen and keyboard\n");
+			use_screen = 1;
+			map_bootx_text();
+			return;
+		}
+#endif
+#ifdef CHRP_ESCC
+		addr = 0xc1013020;
+#else
+		addr = 0xf3013020;
+#endif
+		TXRDY = 4;
+		RXRDY = 1;
+		
+		np = find_devices("mac-io");
+		if (np && np->n_addrs) {
+			addr = np->addrs[0].address + 0x13000;
+			/* use the B channel on the iMac, A channel on others */
+			if (addr >= 0xf0000000)
+				addr += 0x20; /* use A channel */
+		}
+		base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
+		sccc = base + (addr & ~PAGE_MASK);
+#ifdef CHRP_ESCC
+		sccd = sccc + (0xc1013030 - 0xc1013020);
+#else
+		sccd = sccc + (0xf3013030 - 0xf3013020);
+#endif
+	}
+	else
+	{
+		/* should already be mapped by the kernel boot */
+		sccc = (volatile unsigned char *) (isa_io_base + 0x3fd);
+		sccd = (volatile unsigned char *) (isa_io_base + 0x3f8);
+		TXRDY = 0x20;
+		RXRDY = 1;
+	}
+}
+
+static int scc_initialized = 0;
+
+void xmon_init_scc(void);
+extern void pmu_poll(void);
+
+int
+xmon_write(void *handle, void *ptr, int nb)
+{
+    char *p = ptr;
+    int i, ct;
+
+#ifdef CONFIG_BOOTX_TEXT
+    if (use_screen) {
+	/* write it on the screen */
+	for (i = 0; i < nb; ++i)
+	    drawchar(*p++);
+	return nb;
+    }
+#endif
+    if (!scc_initialized)
+	xmon_init_scc();
+    for (i = 0; i < nb; ++i) {
+	while ((*sccc & TXRDY) == 0)
+	    if (adb_hardware == ADB_VIAPMU)
+		pmu_poll();
+	buf_access();
+	if ( console && (*p != '\r'))
+		printk("%c", *p);
+	ct = 0;
+	if ( *p == '\n')
+		ct = 1;
+	*sccd = *p++;
+	if ( ct )
+		xmon_write(handle, "\r", 1);
+    }
+    return i;
+}
+
+int xmon_wants_key;
+int xmon_pmu_keycode;
+
+#ifdef CONFIG_BOOTX_TEXT
+static int xmon_pmu_shiftstate;
+
+static unsigned char xmon_keytab[128] =
+	"asdfhgzxcv\000bqwer"				/* 0x00 - 0x0f */
+	"yt123465=97-80o]"				/* 0x10 - 0x1f */
+	"u[ip\rlj'k;\\,/nm."				/* 0x20 - 0x2f */
+	"\t `\177\0\033\0\0\0\0\0\0\0\0\0\0"		/* 0x30 - 0x3f */
+	"\0.\0*\0+\0\0\0\0\0/\r\0-\0"			/* 0x40 - 0x4f */
+	"\0\0000123456789\0\0\0";			/* 0x50 - 0x5f */
+
+static unsigned char xmon_shift_keytab[128] =
+	"ASDFHGZXCV\000BQWER"				/* 0x00 - 0x0f */
+	"YT!@#$^%+(&=*)}O"				/* 0x10 - 0x1f */
+	"U{IP\rLJ\"K:|<?NM>"				/* 0x20 - 0x2f */
+	"\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0"		/* 0x30 - 0x3f */
+	"\0.\0*\0+\0\0\0\0\0/\r\0-\0"			/* 0x40 - 0x4f */
+	"\0\0000123456789\0\0\0";			/* 0x50 - 0x5f */
+
+static int
+xmon_get_pmu_key(void)
+{
+	int k, t, on;
+
+	xmon_wants_key = 1;
+	for (;;) {
+		xmon_pmu_keycode = -1;
+		t = 0;
+		on = 0;
+		do {
+			if (--t < 0) {
+				on = 1 - on;
+				drawchar(on? 0xdb: 0x20);
+				drawchar('\b');
+				t = 200000;
+			}
+			pmu_poll();
+		} while (xmon_pmu_keycode == -1);
+		k = xmon_pmu_keycode;
+		if (on)
+			drawstring(" \b");
+
+		/* test for shift keys */
+		if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
+			xmon_pmu_shiftstate = (k & 0x80) == 0;
+			continue;
+		}
+		if (k >= 0x80)
+			continue;	/* ignore up transitions */
+		k = (xmon_pmu_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
+		if (k != 0)
+			break;
+	}
+	xmon_wants_key = 0;
+	return k;
+}
+#endif /* CONFIG_BOOTX_TEXT */
+
+int
+xmon_read(void *handle, void *ptr, int nb)
+{
+    char *p = ptr;
+    int i;
+
+#ifdef CONFIG_BOOTX_TEXT
+    if (use_screen) {
+	for (i = 0; i < nb; ++i)
+	    *p++ = xmon_get_pmu_key();
+	return i;
+    }
+#endif
+    if (!scc_initialized)
+	xmon_init_scc();
+    for (i = 0; i < nb; ++i) {
+	while ((*sccc & RXRDY) == 0)
+	    if (adb_hardware == ADB_VIAPMU)
+		pmu_poll();
+	buf_access();
+#if 0	
+	if ( 0/*console*/ )
+		*p++ = ppc_md.kbd_getkeycode();
+	else
+#endif		
+		*p++ = *sccd;
+    }
+    return i;
+}
+
+static unsigned char scc_inittab[] = {
+    13, 0,		/* set baud rate divisor */
+    12, 1,
+    14, 1,		/* baud rate gen enable, src=rtxc */
+    11, 0x50,		/* clocks = br gen */
+    5,  0x6a,		/* tx 8 bits, assert RTS */
+    4,  0x44,		/* x16 clock, 1 stop */
+    3,  0xc1,		/* rx enable, 8 bits */
+};
+
+void
+xmon_init_scc()
+{
+	if ( _machine == _MACH_chrp )
+	{
+		sccd[3] = 0x83; eieio();	/* LCR = 8N1 + DLAB */
+		sccd[0] = 3; eieio();		/* DLL = 38400 baud */
+		sccd[1] = 0; eieio();
+		sccd[2] = 0; eieio();		/* FCR = 0 */
+		sccd[3] = 3; eieio();		/* LCR = 8N1 */
+		sccd[1] = 0; eieio();		/* IER = 0 */
+	}
+	else
+	{
+		int i, x;
+
+		for (i = 20000; i != 0; --i) {
+			x = *sccc; eieio();
+		}
+		*sccc = 9; eieio();		/* reset A or B side */
+		*sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio();
+		for (i = 0; i < sizeof(scc_inittab); ++i) {
+			*sccc = scc_inittab[i];
+			eieio();
+		}
+	}
+	scc_initialized = 1;
+}
+
+#if 0
+extern int (*prom_entry)(void *);
+
+int
+xmon_exit(void)
+{
+    struct prom_args {
+	char *service;
+    } args;
+
+    for (;;) {
+	args.service = "exit";
+	(*prom_entry)(&args);
+    }
+}
+#endif
+
+void *xmon_stdin;
+void *xmon_stdout;
+void *xmon_stderr;
+
+void
+xmon_init(void)
+{
+}
+
+int
+xmon_putc(int c, void *f)
+{
+    char ch = c;
+
+    if (c == '\n')
+	xmon_putc('\r', f);
+    return xmon_write(f, &ch, 1) == 1? c: -1;
+}
+
+int
+xmon_putchar(int c)
+{
+    return xmon_putc(c, xmon_stdout);
+}
+
+int
+xmon_fputs(char *str, void *f)
+{
+    int n = strlen(str);
+
+    return xmon_write(f, str, n) == n? 0: -1;
+}
+
+int
+xmon_readchar(void)
+{
+    char ch;
+
+    for (;;) {
+	switch (xmon_read(xmon_stdin, &ch, 1)) {
+	case 1:
+	    return ch;
+	case -1:
+	    xmon_printf("read(stdin) returned -1\r\n", 0, 0);
+	    return -1;
+	}
+    }
+}
+
+static char line[256];
+static char *lineptr;
+static int lineleft;
+
+int
+xmon_getchar(void)
+{
+    int c;
+
+    if (lineleft == 0) {
+	lineptr = line;
+	for (;;) {
+	    c = xmon_readchar();
+	    if (c == -1 || c == 4)
+		break;
+	    if (c == '\r' || c == '\n') {
+		*lineptr++ = '\n';
+		xmon_putchar('\n');
+		break;
+	    }
+	    switch (c) {
+	    case 0177:
+	    case '\b':
+		if (lineptr > line) {
+		    xmon_putchar('\b');
+		    xmon_putchar(' ');
+		    xmon_putchar('\b');
+		    --lineptr;
+		}
+		break;
+	    case 'U' & 0x1F:
+		while (lineptr > line) {
+		    xmon_putchar('\b');
+		    xmon_putchar(' ');
+		    xmon_putchar('\b');
+		    --lineptr;
+		}
+		break;
+	    default:
+		if (lineptr >= &line[sizeof(line) - 1])
+		    xmon_putchar('\a');
+		else {
+		    xmon_putchar(c);
+		    *lineptr++ = c;
+		}
+	    }
+	}
+	lineleft = lineptr - line;
+	lineptr = line;
+    }
+    if (lineleft == 0)
+	return -1;
+    --lineleft;
+    return *lineptr++;
+}
+
+char *
+xmon_fgets(char *str, int nb, void *f)
+{
+    char *p;
+    int c;
+
+    for (p = str; p < str + nb - 1; ) {
+	c = xmon_getchar();
+	if (c == -1) {
+	    if (p == str)
+		return 0;
+	    break;
+	}
+	*p++ = c;
+	if (c == '\n')
+	    break;
+    }
+    *p = 0;
+    return str;
+}
diff -urN linux-2.2.12-pre6/arch/ppc/xmon/subr_prf.c linux-2.2.12-pre7/arch/ppc/xmon/subr_prf.c
--- linux-2.2.12-pre6/arch/ppc/xmon/subr_prf.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/xmon/subr_prf.c	2003-08-15 15:07:07.000000000 -0700
@@ -0,0 +1,47 @@
+/*
+ * Written by Cort Dougan to replace the version written by
+ * Paul Mackerras that had copyright conflicts with Linux.
+ *
+ * This file makes liberal use of the standard linux utility
+ * routines to reduce the size of the binary.  We assume we can
+ * trust some parts of Linux inside the debugger.
+ *   -- Cort (cort@cs.nmt.edu)
+ *
+ * Copyright (C) 1999 Cort Dougan.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <stdarg.h>
+#include "nonstdio.h"
+
+extern int xmon_write(void *, void *, int);
+
+void
+xmon_vfprintf(void *f, const char *fmt, va_list ap)
+{
+	char buf[2048];
+	vsprintf( buf, fmt, ap );
+	xmon_write( f, buf, strlen(buf) );
+}
+
+void
+xmon_printf(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	xmon_vfprintf(stdout, fmt, ap);
+	va_end(ap);
+}
+
+void
+xmon_fprintf(void *f, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	xmon_vfprintf(f, fmt, ap);
+	va_end(ap);
+}
+
diff -urN linux-2.2.12-pre6/arch/ppc/xmon/xmon.c linux-2.2.12-pre7/arch/ppc/xmon/xmon.c
--- linux-2.2.12-pre6/arch/ppc/xmon/xmon.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.12-pre7/arch/ppc/xmon/xmon.c	2003-08-15 15:07:07.000000000 -0700
@@ -0,0 +1,1323 @@
+/*
+ * Routines providing a simple monitor for use on the PowerMac.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+#include <asm/string.h>
+#include "nonstdio.h"
+#include "privinst.h"
+
+#define scanhex	xmon_scanhex
+#define skipbl	xmon_skipbl
+
+static unsigned adrs;
+static int size = 1;
+static unsigned ndump = 64;
+static unsigned nidump = 16;
+static int termch;
+
+static u_int bus_error_jmp[100];
+#define setjmp xmon_setjmp
+#define longjmp xmon_longjmp
+
+/* Breakpoint stuff */
+struct bpt {
+	unsigned address;
+	unsigned instr;
+	unsigned count;
+	unsigned char enabled;
+};
+
+#define NBPTS	16
+static struct bpt bpts[NBPTS];
+static struct bpt dabr;
+static struct bpt iabr;
+static unsigned bpinstr = 0x7fe00008;	/* trap */
+
+/* Prototypes */
+extern void (*debugger_fault_handler)(struct pt_regs *);
+static int cmds(struct pt_regs *);
+static int mread(unsigned, void *, int);
+static int mwrite(unsigned, void *, int);
+static void handle_fault(struct pt_regs *);
+static void byterev(unsigned char *, int);
+static void memex(void);
+static int bsesc(void);
+static void dump(void);
+static void prdump(unsigned, int);
+#ifdef __MWERKS__
+static void prndump(unsigned, int);
+static int nvreadb(unsigned);
+#endif
+static int ppc_inst_dump(unsigned, int);
+void print_address(unsigned);
+static int getsp(void);
+static void dump_hash_table(void);
+static void backtrace(struct pt_regs *);
+static void excprint(struct pt_regs *);
+static void prregs(struct pt_regs *);
+static void memops(int);
+static void memlocate(void);
+static void memzcan(void);
+static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
+int skipbl(void);
+int scanhex(unsigned *valp);
+static void scannl(void);
+static int hexdigit(int);
+void getstring(char *, int);
+static void flush_input(void);
+static int inchar(void);
+static void take_input(char *);
+/* static void openforth(void); */
+static unsigned read_spr(int);
+static void write_spr(int, unsigned);
+static void super_regs(void);
+static void remove_bpts(void);
+static void insert_bpts(void);
+static struct bpt *at_breakpoint(unsigned pc);
+static void bpt_cmds(void);
+
+extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
+extern void printf(const char *fmt, ...);
+extern int putchar(int ch);
+extern int setjmp(u_int *);
+extern void longjmp(u_int *, int);
+
+#define GETWORD(v)	(((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
+
+static char *help_string = "\
+Commands:\n\
+  d	dump bytes\n\
+  di	dump instructions\n\
+  df	dump float values\n\
+  dd	dump double values\n\
+  e	print exception information\n\
+  h	dump hash table\n\
+  m	examine/change memory\n\
+  mm	move a block of memory\n\
+  ms	set a block of memory\n\
+  md	compare two blocks of memory\n\
+  r	print registers\n\
+  S	print special registers\n\
+  t	print backtrace\n\
+  x	exit monitor\n\
+";
+
+static int xmon_trace;
+#define SSTEP	1		/* stepping because of 's' command */
+#define BRSTEP	2		/* stepping over breakpoint */
+
+void
+xmon(struct pt_regs *excp)
+{
+	struct pt_regs regs;
+	int msr, cmd;
+
+	printk("Entering xmon kernel debugger.\n");
+	
+	if (excp == NULL) {
+		asm volatile ("stw	0,0(%0)\n\
+			lwz	0,0(1)\n\
+			stw	0,4(%0)\n\
+			stmw	2,8(%0)" : : "b" (&regs));
+		regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
+		regs.msr = get_msr();
+		regs.ctr = get_ctr();
+		regs.xer = get_xer();
+		regs.ccr = get_cr();
+		regs.trap = 0;
+		excp = &regs;
+	}
+
+	msr = get_msr();
+	set_msr(msr & ~0x8000);	/* disable interrupts */
+	remove_bpts();
+	excprint(excp);
+	cmd = cmds(excp);
+	if (cmd == 's') {
+		xmon_trace = SSTEP;
+		excp->msr |= 0x400;
+	} else if (at_breakpoint(excp->nip)) {
+		xmon_trace = BRSTEP;
+		excp->msr |= 0x400;
+	} else {
+		xmon_trace = 0;
+		insert_bpts();
+	}
+	set_msr(msr);		/* restore interrupt enable */
+}
+
+void
+xmon_irq(int irq, void *d, struct pt_regs *regs)
+{
+	printf("Keyboard interrupt\n");
+	xmon(regs);
+}
+
+int
+xmon_bpt(struct pt_regs *regs)
+{
+	struct bpt *bp;
+
+	bp = at_breakpoint(regs->nip);
+	if (!bp)
+		return 0;
+	if (bp->count) {
+		--bp->count;
+		remove_bpts();
+		excprint(regs);
+		xmon_trace = BRSTEP;
+		regs->msr |= 0x400;
+	} else {
+		xmon(regs);
+	}
+	return 1;
+}
+
+int
+xmon_sstep(struct pt_regs *regs)
+{
+	if (!xmon_trace)
+		return 0;
+	if (xmon_trace == BRSTEP) {
+		xmon_trace = 0;
+		insert_bpts();
+	} else {
+		xmon(regs);
+	}
+	return 1;
+}
+
+int
+xmon_dabr_match(struct pt_regs *regs)
+{
+	if (dabr.enabled && dabr.count) {
+		--dabr.count;
+		remove_bpts();
+		excprint(regs);
+		xmon_trace = BRSTEP;
+		regs->msr |= 0x400;
+	} else {
+		dabr.instr = regs->nip;
+		xmon(regs);
+	}
+	return 1;
+}
+
+int
+xmon_iabr_match(struct pt_regs *regs)
+{
+	if (iabr.enabled && iabr.count) {
+		--iabr.count;
+		remove_bpts();
+		excprint(regs);
+		xmon_trace = BRSTEP;
+		regs->msr |= 0x400;
+	} else {
+		xmon(regs);
+	}
+	return 1;
+}
+
+static struct bpt *
+at_breakpoint(unsigned pc)
+{
+	int i;
+	struct bpt *bp;
+
+	if (dabr.enabled && pc == dabr.instr)
+		return &dabr;
+	if (iabr.enabled && pc == iabr.address)
+		return &iabr;
+	bp = bpts;
+	for (i = 0; i < NBPTS; ++i, ++bp)
+		if (bp->enabled && pc == bp->address)
+			return bp;
+	return 0;
+}
+
+static void
+insert_bpts()
+{
+	int i;
+	struct bpt *bp;
+
+	bp = bpts;
+	for (i = 0; i < NBPTS; ++i, ++bp) {
+		if (!bp->enabled)
+			continue;
+		if (mread(bp->address, &bp->instr, 4) != 4
+		    || mwrite(bp->address, &bpinstr, 4) != 4) {
+			printf("Couldn't insert breakpoint at %x, disabling\n",
+			       bp->address);
+			bp->enabled = 0;
+		}
+	}
+	if (dabr.enabled)
+		set_dabr(dabr.address);
+	if (iabr.enabled)
+		set_iabr(iabr.address);
+}
+
+static void
+remove_bpts()
+{
+	int i;
+	struct bpt *bp;
+	unsigned instr;
+
+	set_dabr(0);
+	set_iabr(0);
+	bp = bpts;
+	for (i = 0; i < NBPTS; ++i, ++bp) {
+		if (!bp->enabled)
+			continue;
+		if (mread(bp->address, &instr, 4) == 4
+		    && instr == bpinstr
+		    && mwrite(bp->address, &bp->instr, 4) != 4)
+			printf("Couldn't remove breakpoint at %x\n",
+			       bp->address);
+	}
+}
+
+static char *last_cmd;
+
+/* Command interpreting routine */
+static int
+cmds(struct pt_regs *excp)
+{
+	int cmd;
+
+	last_cmd = NULL;
+	for(;;) {
+		printf("mon> ");
+		fflush(stdout);
+		flush_input();
+		termch = 0;
+		cmd = skipbl();
+		if( cmd == '\n' ) {
+			if (last_cmd == NULL)
+				continue;
+			take_input(last_cmd);
+			last_cmd = NULL;
+			cmd = inchar();
+		}
+		switch (cmd) {
+		case 'm':
+			cmd = inchar();
+			switch (cmd) {
+			case 'm':
+			case 's':
+			case 'd':
+				memops(cmd);
+				break;
+			case 'l':
+				memlocate();
+				break;
+			case 'z':
+				memzcan();
+				break;
+			default:
+				termch = cmd;
+				memex();
+			}
+			break;
+		case 'd':
+			dump();
+			break;
+		case 'r':
+			if (excp != NULL)
+				prregs(excp);	/* print regs */
+			break;
+		case 'e':
+			if (excp == NULL)
+				printf("No exception information\n");
+			else
+				excprint(excp);
+			break;
+		case 'S':
+			super_regs();
+			break;
+		case 't':
+			backtrace(excp);
+			break;
+#if 0
+		case 'f':
+			openforth();
+			break;
+#endif
+		case 'h':
+			dump_hash_table();
+			break;
+		case 's':
+		case 'x':
+		case EOF:
+			return cmd;
+		case '?':
+			printf(help_string);
+			break;
+		default:
+			printf("Unrecognized command: ");
+			if( ' ' < cmd && cmd <= '~' )
+				putchar(cmd);
+			else
+				printf("\\x%x", cmd);
+			printf(" (type ? for help)\n");
+			break;
+		case 'b':
+			bpt_cmds();
+			break;
+		}
+	}
+}
+
+static void
+bpt_cmds(void)
+{
+	int cmd;
+	unsigned a;
+	int mode, i;
+	struct bpt *bp;
+
+	cmd = inchar();
+	switch (cmd) {
+	case 'd':
+		mode = 7;
+		cmd = inchar();
+		if (cmd == 'r')
+			mode = 5;
+		else if (cmd == 'w')
+			mode = 6;
+		else
+			termch = cmd;
+		dabr.address = 0;
+		dabr.count = 0;
+		dabr.enabled = scanhex(&dabr.address);
+		scanhex(&dabr.count);
+		if (dabr.enabled)
+			dabr.address = (dabr.address & ~7) | mode;
+		break;
+	case 'i':
+		iabr.address = 0;
+		iabr.count = 0;
+		iabr.enabled = scanhex(&iabr.address);
+		if (iabr.enabled)
+			iabr.address |= 3;
+		scanhex(&iabr.count);
+		break;
+	case 'c':
+		if (!scanhex(&a)) {
+			/* clear all breakpoints */
+			for (i = 0; i < NBPTS; ++i)
+				bpts[i].enabled = 0;
+			iabr.enabled = 0;
+			dabr.enabled = 0;
+			printf("All breakpoints cleared\n");
+		} else {
+			bp = at_breakpoint(a);
+			if (bp == 0) {
+				printf("No breakpoint at %x\n", a);
+			} else {
+				bp->enabled = 0;
+			}
+		}
+		break;
+	default:
+		termch = cmd;
+		if (!scanhex(&a)) {
+			/* print all breakpoints */
+			printf("type  address   count\n");
+			if (dabr.enabled) {
+				printf("data %.8x %8x [", dabr.address & ~7,
+				       dabr.count);
+				if (dabr.address & 1)
+					printf("r");
+				if (dabr.address & 2)
+					printf("w");
+				printf("]\n");
+			}
+			if (iabr.enabled)
+				printf("inst %.8x %8x\n", iabr.address & ~3,
+				       iabr.count);
+			for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
+				if (bp->enabled)
+					printf("trap %.8x %8x\n", bp->address,
+					       bp->count);
+			break;
+		}
+		bp = at_breakpoint(a);
+		if (bp == 0) {
+			for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
+				if (!bp->enabled)
+					break;
+			if (bp >= &bpts[NBPTS]) {
+				printf("Sorry, no free breakpoints\n");
+				break;
+			}
+		}
+		bp->enabled = 1;
+		bp->address = a;
+		bp->count = 0;
+		scanhex(&bp->count);
+		break;
+	}
+}
+
+static void
+backtrace(struct pt_regs *excp)
+{
+	unsigned sp;
+	unsigned stack[2];
+	struct pt_regs regs;
+	extern char int_return, syscall_ret_1, syscall_ret_2;
+	extern char lost_irq_ret, do_bottom_half_ret, do_signal_ret;
+
+	if (excp != NULL)
+		sp = excp->gpr[1];
+	else
+		sp = getsp();
+	scanhex(&sp);
+	scannl();
+	for (; sp != 0; sp = stack[0]) {
+		if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
+			break;
+		printf("%x ", stack[1]);
+		if (stack[1] == (unsigned) &int_return
+		    || stack[1] == (unsigned) &syscall_ret_1
+		    || stack[1] == (unsigned) &syscall_ret_2
+		    || stack[1] == (unsigned) &lost_irq_ret
+		    || stack[1] == (unsigned) &do_bottom_half_ret
+		    || stack[1] == (unsigned) &do_signal_ret) {
+			if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
+				break;
+			printf("\nexception:%x [%x] %x ", regs.trap, sp+16,
+			       regs.nip);
+			sp = regs.gpr[1];
+			if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
+				break;
+		}
+	}
+	printf("\n");
+}
+
+int
+getsp()
+{
+    int x;
+
+    asm("mr %0,1" : "=r" (x) :);
+    return x;
+}
+
+void
+excprint(struct pt_regs *fp)
+{
+	printf("vector: %x at pc = %x, msr = %x, sp = %x [%x]\n",
+	       fp->trap, fp->nip, fp->msr, fp->gpr[1], fp);
+	if (fp->trap == 0x300 || fp->trap == 0x600)
+		printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
+	if (current)
+		printf("current = %x, pid = %d, comm = %s\n",
+		       current, current->pid, current->comm);
+}
+
+void
+prregs(struct pt_regs *fp)
+{
+	int n;
+	unsigned base;
+
+	if (scanhex(&base))
+		fp = (struct pt_regs *) base;
+	for (n = 0; n < 32; ++n)
+		printf("R%.2d = %.8x%s", n, fp->gpr[n],
+		       (n & 3) == 3? "\n": "   ");
+	printf("pc  = %.8x   msr = %.8x   lr  = %.8x   cr  = %.8x\n",
+	       fp->nip, fp->msr, fp->link, fp->ccr);
+	printf("ctr = %.8x   xer = %.8x   trap = %4x\n",
+	       fp->ctr, fp->xer, fp->trap);
+}
+
+unsigned int
+read_spr(int n)
+{
+    unsigned int instrs[2];
+    int (*code)(void);
+
+    instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
+    instrs[1] = 0x4e800020;
+    store_inst(instrs);
+    store_inst(instrs+1);
+    code = (int (*)(void)) instrs;
+    return code();
+}
+
+void
+write_spr(int n, unsigned int val)
+{
+    unsigned int instrs[2];
+    int (*code)(unsigned int);
+
+    instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
+    instrs[1] = 0x4e800020;
+    store_inst(instrs);
+    store_inst(instrs+1);
+    code = (int (*)(unsigned int)) instrs;
+    code(val);
+}
+
+static unsigned int regno;
+extern char exc_prolog;
+extern char dec_exc;
+
+void
+super_regs()
+{
+	int i, cmd;
+	unsigned val;
+
+	cmd = skipbl();
+	if (cmd == '\n') {
+		printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
+		printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
+		       get_sprg2(), get_sprg3());
+		printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
+		printf("sr0-15 =");
+		for (i = 0; i < 16; ++i)
+			printf(" %x", get_sr(i));
+		printf("\n");
+		asm("mr %0,1" : "=r" (i) :);
+		printf("sp = %x ", i);
+		asm("mr %0,2" : "=r" (i) :);
+		printf("toc = %x\n", i);
+		return;
+	}
+
+	scanhex(&regno);
+	switch (cmd) {
+	case 'w':
+		val = read_spr(regno);
+		scanhex(&val);
+		write_spr(regno, val);
+		/* fall through */
+	case 'r':
+		printf("spr %x = %x\n", regno, read_spr(regno));
+		break;
+	case 's':
+		val = get_sr(regno);
+		scanhex(&val);
+		set_sr(regno, val);
+		break;
+	case 'm':
+		val = get_msr();
+		scanhex(&val);
+		set_msr(val);
+		break;
+	}
+	scannl();
+}
+
+#if 0
+static void
+openforth()
+{
+    int c;
+    char *p;
+    char cmd[1024];
+    int args[5];
+    extern int (*prom_entry)(int *);
+
+    p = cmd;
+    c = skipbl();
+    while (c != '\n') {
+	*p++ = c;
+	c = inchar();
+    }
+    *p = 0;
+    args[0] = (int) "interpret";
+    args[1] = 1;
+    args[2] = 1;
+    args[3] = (int) cmd;
+    (*prom_entry)(args);
+    printf("\n");
+    if (args[4] != 0)
+	printf("error %x\n", args[4]);
+}
+#endif
+
+static void
+dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
+{
+	extern void *Hash;
+	extern unsigned long Hash_size;
+	unsigned *htab = Hash;
+	unsigned hsize = Hash_size;
+	unsigned v, hmask, va, last_va;
+	int found, last_found, i;
+	unsigned *hg, w1, last_w2, last_va0;
+
+	last_found = 0;
+	hmask = hsize / 64 - 1;
+	va = start;
+	start = (start >> 12) & 0xffff;
+	end = (end >> 12) & 0xffff;
+	for (v = start; v < end; ++v) {
+		found = 0;
+		hg = htab + (((v ^ seg) & hmask) * 16);
+		w1 = 0x80000000 | (seg << 7) | (v >> 10);
+		for (i = 0; i < 8; ++i, hg += 2) {
+			if (*hg == w1) {
+				found = 1;
+				break;
+			}
+		}
+		if (!found) {
+			w1 ^= 0x40;
+			hg = htab + ((~(v ^ seg) & hmask) * 16);
+			for (i = 0; i < 8; ++i, hg += 2) {
+				if (*hg == w1) {
+					found = 1;
+					break;
+				}
+			}
+		}
+		if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
+			if (last_found) {
+				if (last_va != last_va0)
+					printf(" ... %x", last_va);
+				printf("\n");
+			}
+			if (found) {
+				printf("%x to %x", va, hg[1]);
+				last_va0 = va;
+			}
+			last_found = found;
+		}
+		if (found) {
+			last_w2 = hg[1] & ~0x180;
+			last_va = va;
+		}
+		va += 4096;
+	}
+	if (last_found)
+		printf(" ... %x\n", last_va);
+}
+static unsigned hash_ctx;
+static unsigned hash_start;
+static unsigned hash_end;
+
+static void
+dump_hash_table()
+{
+	int seg;
+	unsigned seg_start, seg_end;
+
+	hash_ctx = 0;
+	hash_start = 0;
+	hash_end = 0xfffff000;
+	scanhex(&hash_ctx);
+	scanhex(&hash_start);
+	scanhex(&hash_end);
+	printf("Mappings for context %x\n", hash_ctx);
+	seg_start = hash_start;
+	for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
+		seg_end = (seg << 28) | 0x0ffff000;
+		if (seg_end > hash_end)
+			seg_end = hash_end;
+		dump_hash_table_seg((hash_ctx << 4) + seg, seg_start, seg_end);
+		seg_start = seg_end + 0x1000;
+	}
+}
+
+/*
+ * Stuff for reading and writing memory safely
+ */
+extern inline void sync(void)
+{
+	asm volatile("sync; isync");
+}
+
+extern inline void __delay(unsigned int loops)
+{
+	if (loops != 0)
+		__asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
+				     "r" (loops) : "ctr");
+}
+
+int
+mread(unsigned adrs, void *buf, int size)
+{
+	volatile int n;
+	char *p, *q;
+
+	n = 0;
+	if( setjmp(bus_error_jmp) == 0 ){
+		debugger_fault_handler = handle_fault;
+		sync();
+		p = (char *) adrs;
+		q = (char *) buf;
+		switch (size) {
+		case 2: *(short *)q = *(short *)p;	break;
+		case 4: *(int *)q = *(int *)p;		break;
+		default:
+			for( ; n < size; ++n ) {
+				*q++ = *p++;
+				sync();
+			}
+		}
+		sync();
+		/* wait a little while to see if we get a machine check */
+		__delay(200);
+		n = size;
+	}
+	debugger_fault_handler = 0;
+	return n;
+}
+
+int
+mwrite(unsigned adrs, void *buf, int size)
+{
+	volatile int n;
+	char *p, *q;
+
+	n = 0;
+	if( setjmp(bus_error_jmp) == 0 ){
+		debugger_fault_handler = handle_fault;
+		sync();
+		p = (char *) adrs;
+		q = (char *) buf;
+		switch (size) {
+		case 2: *(short *)p = *(short *)q;	break;
+		case 4: *(int *)p = *(int *)q;		break;
+		default:
+			for( ; n < size; ++n ) {
+				*p++ = *q++;
+				sync();
+			}
+		}
+		sync();
+		n = size;
+	} else {
+		printf("*** Error writing address %x\n", adrs + n);
+	}
+	debugger_fault_handler = 0;
+	return n;
+}
+
+static int fault_type;
+static char *fault_chars[] = { "--", "**", "##" };
+
+static void
+handle_fault(struct pt_regs *regs)
+{
+	fault_type = regs->trap == 0x200? 0: regs->trap == 0x300? 1: 2;
+	longjmp(bus_error_jmp, 1);
+}
+
+#define SWAP(a, b, t)	((t) = (a), (a) = (b), (b) = (t))
+
+void
+byterev(unsigned char *val, int size)
+{
+	int t;
+	
+	switch (size) {
+	case 2:
+		SWAP(val[0], val[1], t);
+		break;
+	case 4:
+		SWAP(val[0], val[3], t);
+		SWAP(val[1], val[2], t);
+		break;
+	}
+}
+
+static int brev;
+static int mnoread;
+
+void
+memex()
+{
+    int cmd, inc, i, nslash;
+    unsigned n;
+    unsigned char val[4];
+
+    last_cmd = "m\n";
+    scanhex(&adrs);
+    while ((cmd = skipbl()) != '\n') {
+	switch( cmd ){
+	case 'b':	size = 1;	break;
+	case 'w':	size = 2;	break;
+	case 'l':	size = 4;	break;
+	case 'r': 	brev = !brev;	break;
+	case 'n':	mnoread = 1;	break;
+	case '.':	mnoread = 0;	break;
+	}
+    }
+    if( size <= 0 )
+	size = 1;
+    else if( size > 4 )
+	size = 4;
+    for(;;){
+	if (!mnoread)
+	    n = mread(adrs, val, size);
+	printf("%.8x%c", adrs, brev? 'r': ' ');
+	if (!mnoread) {
+	    if (brev)
+		byterev(val, size);
+	    putchar(' ');
+	    for (i = 0; i < n; ++i)
+		printf("%.2x", val[i]);
+	    for (; i < size; ++i)
+		printf("%s", fault_chars[fault_type]);
+	}
+	putchar(' ');
+	inc = size;
+	nslash = 0;
+	for(;;){
+	    if( scanhex(&n) ){
+		for (i = 0; i < size; ++i)
+		    val[i] = n >> (i * 8);
+		if (!brev)
+		    byterev(val, size);
+		mwrite(adrs, val, size);
+		inc = size;
+	    }
+	    cmd = skipbl();
+	    if (cmd == '\n')
+		break;
+	    inc = 0;
+	    switch (cmd) {
+	    case '\'':
+		for(;;){
+		    n = inchar();
+		    if( n == '\\' )
+			n = bsesc();
+		    else if( n == '\'' )
+			break;
+		    for (i = 0; i < size; ++i)
+			val[i] = n >> (i * 8);
+		    if (!brev)
+			byterev(val, size);
+		    mwrite(adrs, val, size);
+		    adrs += size;
+		}
+		adrs -= size;
+		inc = size;
+		break;
+	    case ',':
+		adrs += size;
+		break;
+	    case '.':
+		mnoread = 0;
+		break;
+	    case ';':
+		break;
+	    case 'x':
+	    case EOF:
+		scannl();
+		return;
+	    case 'b':
+	    case 'v':
+		size = 1;
+		break;
+	    case 'w':
+		size = 2;
+		break;
+	    case 'l':
+		size = 4;
+		break;
+	    case '^':
+		adrs -= size;
+		break;
+		break;
+	    case '/':
+		if (nslash > 0)
+		    adrs -= 1 << nslash;
+		else
+		    nslash = 0;
+		nslash += 4;
+		adrs += 1 << nslash;
+		break;
+	    case '\\':
+		if (nslash < 0)
+		    adrs += 1 << -nslash;
+		else
+		    nslash = 0;
+		nslash -= 4;
+		adrs -= 1 << -nslash;
+		break;
+	    case 'm':
+		scanhex(&adrs);
+		break;
+	    case 'n':
+		mnoread = 1;
+		break;
+	    case 'r':
+		brev = !brev;
+		break;
+	    case '<':
+		n = size;
+		scanhex(&n);
+		adrs -= n;
+		break;
+	    case '>':
+		n = size;
+		scanhex(&n);
+		adrs += n;
+		break;
+	    }
+	}
+	adrs += inc;
+    }
+}
+
+int
+bsesc()
+{
+	int c;
+
+	c = inchar();
+	switch( c ){
+	case 'n':	c = '\n';	break;
+	case 'r':	c = '\r';	break;
+	case 'b':	c = '\b';	break;
+	case 't':	c = '\t';	break;
+	}
+	return c;
+}
+
+#define isxdigit(c)	(('0' <= (c) && (c) <= '9') \
+			 || ('a' <= (c) && (c) <= 'f') \
+			 || ('A' <= (c) && (c) <= 'F'))
+void
+dump()
+{
+	int c;
+
+	c = inchar();
+	if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
+		termch = c;
+	scanhex(&adrs);
+	if( termch != '\n')
+		termch = 0;
+	if( c == 'i' ){
+		scanhex(&nidump);
+		if( nidump == 0 )
+			nidump = 16;
+		adrs += ppc_inst_dump(adrs, nidump);
+		last_cmd = "di\n";
+	} else {
+		scanhex(&ndump);
+		if( ndump == 0 )
+			ndump = 64;
+		prdump(adrs, ndump);
+		adrs += ndump;
+		last_cmd = "d\n";
+	}
+}
+
+void
+prdump(unsigned adrs, int ndump)
+{
+	register int n, m, c, r, nr;
+	unsigned char temp[16];
+
+	for( n = ndump; n > 0; ){
+		printf("%.8x", adrs);
+		putchar(' ');
+		r = n < 16? n: 16;
+		nr = mread(adrs, temp, r);
+		adrs += nr;
+		for( m = 0; m < r; ++m ){
+			putchar((m & 3) == 0 && m > 0? '.': ' ');
+			if( m < nr )
+				printf("%.2x", temp[m]);
+			else
+				printf("%s", fault_chars[fault_type]);
+		}
+		for(; m < 16; ++m )
+			printf("   ");
+		printf("  |");
+		for( m = 0; m < r; ++m ){
+			if( m < nr ){
+				c = temp[m];
+				putchar(' ' <= c && c <= '~'? c: '.');
+			} else
+				putchar(' ');
+		}
+		n -= r;
+		for(; m < 16; ++m )
+			putchar(' ');
+		printf("|\n");
+		if( nr < r )
+			break;
+	}
+}
+
+int
+ppc_inst_dump(unsigned adr, int count)
+{
+	int nr, dotted;
+	unsigned first_adr;
+	unsigned long inst, last_inst;
+	unsigned char val[4];
+
+	dotted = 0;
+	for (first_adr = adr; count > 0; --count, adr += 4){
+		nr = mread(adr, val, 4);
+		if( nr == 0 ){
+			const char *x = fault_chars[fault_type];
+			printf("%.8x  %s%s%s%s\n", adr, x, x, x, x);
+			break;
+		}
+		inst = GETWORD(val);
+		if (adr > first_adr && inst == last_inst) {
+			if (!dotted) {
+				printf(" ...\n");
+				dotted = 1;
+			}
+			continue;
+		}
+		dotted = 0;
+		last_inst = inst;
+		printf("%.8x  ", adr);
+		printf("%.8x\t", inst);
+		print_insn_big_powerpc(stdout, inst, adr);	/* always returns 4 */
+		printf("\n");
+	}
+	return adr - first_adr;
+}
+
+void
+print_address(addr)
+unsigned addr;
+{
+	printf("0x%x", addr);
+}
+
+/*
+ * Memory operations - move, set, print differences
+ */
+static unsigned mdest;		/* destination address */
+static unsigned msrc;		/* source address */
+static unsigned mval;		/* byte value to set memory to */
+static unsigned mcount;		/* # bytes to affect */
+static unsigned mdiffs;		/* max # differences to print */
+
+void
+memops(int cmd)
+{
+	scanhex(&mdest);
+	if( termch != '\n' )
+		termch = 0;
+	scanhex(cmd == 's'? &mval: &msrc);
+	if( termch != '\n' )
+		termch = 0;
+	scanhex(&mcount);
+	switch( cmd ){
+	case 'm':
+		memmove((void *)mdest, (void *)msrc, mcount);
+		break;
+	case 's':
+		memset((void *)mdest, mval, mcount);
+		break;
+	case 'd':
+		if( termch != '\n' )
+			termch = 0;
+		scanhex(&mdiffs);
+		memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
+		break;
+	}
+}
+
+void
+memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
+{
+	unsigned n, prt;
+
+	prt = 0;
+	for( n = nb; n > 0; --n )
+		if( *p1++ != *p2++ )
+			if( ++prt <= maxpr )
+				printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
+					p1[-1], (unsigned)p2 - 1, p2[-1]);
+	if( prt > maxpr )
+		printf("Total of %d differences\n", prt);
+}
+
+static unsigned mend;
+static unsigned mask;
+
+void
+memlocate()
+{
+	unsigned a, n;
+	unsigned char val[4];
+
+	last_cmd = "ml";
+	scanhex(&mdest);
+	if (termch != '\n') {
+		termch = 0;
+		scanhex(&mend);
+		if (termch != '\n') {
+			termch = 0;
+			scanhex(&mval);
+			mask = ~0;
+			if (termch != '\n') termch = 0;
+			scanhex(&mask);
+		}
+	}
+	n = 0;
+	for (a = mdest; a < mend; a += 4) {
+		if (mread(a, val, 4) == 4
+			&& ((GETWORD(val) ^ mval) & mask) == 0) {
+			printf("%.8x:  %.8x\n", a, GETWORD(val));
+			if (++n >= 10)
+				break;
+		}
+	}
+}
+
+static unsigned mskip = 0x1000;
+static unsigned mlim = 0xffffffff;
+
+void
+memzcan()
+{
+	unsigned char v;
+	unsigned a;
+	int ok, ook;
+
+	scanhex(&mdest);
+	if (termch != '\n') termch = 0;
+	scanhex(&mskip);
+	if (termch != '\n') termch = 0;
+	scanhex(&mlim);
+	ook = 0;
+	for (a = mdest; a < mlim; a += mskip) {
+		ok = mread(a, &v, 1);
+		if (ok && !ook) {
+			printf("%.8x .. ", a);
+			fflush(stdout);
+		} else if (!ok && ook)
+			printf("%.8x\n", a - mskip);
+		ook = ok;
+		if (a + mskip < a)
+			break;
+	}
+	if (ook)
+		printf("%.8x\n", a - mskip);
+}
+
+/* Input scanning routines */
+int
+skipbl()
+{
+	int c;
+
+	if( termch != 0 ){
+		c = termch;
+		termch = 0;
+	} else
+		c = inchar();
+	while( c == ' ' || c == '\t' )
+		c = inchar();
+	return c;
+}
+
+int
+scanhex(vp)
+unsigned *vp;
+{
+	int c, d;
+	unsigned v;
+
+	c = skipbl();
+	d = hexdigit(c);
+	if( d == EOF ){
+		termch = c;
+		return 0;
+	}
+	v = 0;
+	do {
+		v = (v << 4) + d;
+		c = inchar();
+		d = hexdigit(c);
+	} while( d != EOF );
+	termch = c;
+	*vp = v;
+	return 1;
+}
+
+void
+scannl()
+{
+	int c;
+
+	c = termch;
+	termch = 0;
+	while( c != '\n' )
+		c = inchar();
+}
+
+int
+hexdigit(c)
+{
+	if( '0' <= c && c <= '9' )
+		return c - '0';
+	if( 'A' <= c && c <= 'F' )
+		return c - ('A' - 10);
+	if( 'a' <= c && c <= 'f' )
+		return c - ('a' - 10);
+	return EOF;
+}
+
+void
+getstring(char *s, int size)
+{
+	int c;
+
+	c = skipbl();
+	do {
+		if( size > 1 ){
+			*s++ = c;
+			--size;
+		}
+		c = inchar();
+	} while( c != ' ' && c != '\t' && c != '\n' );
+	termch = c;
+	*s = 0;
+}
+
+static char line[256];
+static char *lineptr;
+
+void
+flush_input()
+{
+	lineptr = NULL;
+}
+
+int
+inchar()
+{
+	if (lineptr == NULL || *lineptr == 0) {
+		if (fgets(line, sizeof(line), stdin) == NULL) {
+			lineptr = NULL;
+			return EOF;
+		}
+		lineptr = line;
+	}
+	return *lineptr++;
+}
+
+void
+take_input(str)
+char *str;
+{
+	lineptr = str;
+}
diff -urN linux-2.2.12-pre6/drivers/block/ide-pmac.c linux-2.2.12-pre7/drivers/block/ide-pmac.c
--- linux-2.2.12-pre6/drivers/block/ide-pmac.c	1999-08-09 12:04:57.000000000 -0700
+++ linux-2.2.12-pre7/drivers/block/ide-pmac.c	2003-08-15 15:07:08.000000000 -0700
@@ -30,6 +30,7 @@
 #ifdef CONFIG_PMAC_PBOOK
 #include <asm/adb.h>
 #include <asm/pmu.h>
+#include <asm/irq.h>
 #endif
 #include "ide.h"
 #include "ide_modes.h"
@@ -48,9 +49,9 @@
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
 #ifdef CONFIG_PMAC_PBOOK
-static int idepmac_notify(struct notifier_block *, unsigned long, void *);
-struct notifier_block idepmac_sleep_notifier = {
-	idepmac_notify
+static int idepmac_notify(struct pmu_sleep_notifier *self, int when);
+struct pmu_sleep_notifier idepmac_sleep_notifier = {
+	idepmac_notify, SLEEP_LEVEL_BLOCK,
 };
 #endif /* CONFIG_PMAC_PBOOK */
 
@@ -220,7 +221,7 @@
 	pmac_ide_count = i;
 
 #ifdef CONFIG_PMAC_PBOOK
-	notifier_chain_register(&sleep_notifier_list, &idepmac_sleep_notifier);
+	pmu_register_sleep_notifier(&idepmac_sleep_notifier);
 #endif /* CONFIG_PMAC_PBOOK */
 }
 
@@ -380,29 +381,105 @@
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
 #ifdef CONFIG_PMAC_PBOOK
-static int idepmac_notify(struct notifier_block *this,
-			  unsigned long code, void *p)
+static void idepmac_sleep_disk(int i, unsigned long base)
 {
-	int i, timeout;
+	int j;
 
-	switch (code) {
-	case PBOOK_SLEEP:
-		/* do anything here?? */
+	/* Reset to PIO 0 */
+	out_le32((unsigned *)(base + 0x200 + _IO_BASE), 0x2f8526);
+
+	/* FIXME: We only handle the master IDE */
+	if (ide_hwifs[i].drives[0].media == ide_disk) {
+		/* Spin down the drive */
+		outb(0xa0, base+0x60);
+		outb(0x0, base+0x30);
+		outb(0x0, base+0x20);
+		outb(0x0, base+0x40);
+		outb(0x0, base+0x50);
+		outb(0xe0, base+0x70);
+		outb(0x2, base+0x160);   
+		for (j = 0; j < 10; j++) {
+			int status;
+			mdelay(100);
+			status = inb(base+0x70);
+			if (!(status & BUSY_STAT) && (status & DRQ_STAT))
+				break;
+		}
+	}
+}
+
+static void idepmac_wake_disk(int i, unsigned long base)
+{
+	int j;
+
+	/* Revive IDE disk and controller */
+	feature_set(pmac_ide_node[i], FEATURE_IDE_enable);
+	mdelay(1);
+	feature_set(pmac_ide_node[i], FEATURE_IDE_DiskPower);
+	mdelay(100);
+	feature_set(pmac_ide_node[i], FEATURE_IDE_Reset);
+	mdelay(1);
+	/* Make sure we are still PIO0 */
+	out_le32((unsigned *)(base + 0x200 + _IO_BASE), 0x2f8526);
+	mdelay(100);
+
+	/* Wait up to 10 seconds (enough for recent drives) */
+	for (j = 0; j < 100; j++) {
+		int status;
+		mdelay(100);
+		status = inb(base + 0x70);
+		if (!(status & BUSY_STAT))
+			break;
+	}
+}
+
+/* Here we handle media bay devices */
+static void
+idepmac_wake_bay(int i, unsigned long base)
+{
+	int timeout;
+
+	timeout = 5000;
+	while ((inb(base + 0x70) & BUSY_STAT) && timeout) {
+		mdelay(1);
+		--timeout;
+	}
+}
+
+static int idepmac_notify(struct pmu_sleep_notifier *self, int when)
+{
+	int i, ret;
+	unsigned long base;
+
+	switch (when) {
+	case PBOOK_SLEEP_REQUEST:
+		break;
+	case PBOOK_SLEEP_REJECT:
+		break;
+	case PBOOK_SLEEP_NOW:
+		for (i = 0; i < pmac_ide_count; ++i) {
+			if ((base = pmac_ide_regbase[i]) == 0)
+				continue;
+			/* Disable irq during sleep */
+			disable_irq(pmac_ide_irq[i]);
+			/* Put the disk to sleep */
+			idepmac_sleep_disk(i, base);
+		}
 		break;
 	case PBOOK_WAKE:
-		/* wait for the controller(s) to become ready */
-		timeout = 5000;
 		for (i = 0; i < pmac_ide_count; ++i) {
-			unsigned long base = pmac_ide_regbase[i];
-			if (check_media_bay_by_base(base, MB_CD) == -EINVAL)
+			if ((base = pmac_ide_regbase[i]) == 0)
 				continue;
-			while ((inb(base + 0x70) & BUSY_STAT) && timeout) {
-				mdelay(1);
-				--timeout;
-			}
+		        /* We don't handle media bay devices this way */
+			ret = check_media_bay_by_base(base, MB_CD);
+			if (ret == -ENODEV)
+				idepmac_wake_disk(i, base);
+			else if (ret == 0)
+				idepmac_wake_bay(i, base);
+			enable_irq(pmac_ide_irq[i]);
 		}
 		break;
 	}
-	return NOTIFY_DONE;
+	return PBOOK_SLEEP_OK;
 }
 #endif /* CONFIG_PMAC_PBOOK */
diff -urN linux-2.2.12-pre6/drivers/macintosh/adb.c linux-2.2.12-pre7/drivers/macintosh/adb.c
--- linux-2.2.12-pre6/drivers/macintosh/adb.c	2003-08-15 15:07:07.000000000 -0700
+++ linux-2.2.12-pre7/drivers/macintosh/adb.c	2003-08-15 15:07:08.000000000 -0700
@@ -24,6 +24,7 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
+#include <linux/notifier.h>
 #include <asm/prom.h>
 #include <asm/adb.h>
 #include <asm/cuda.h>
@@ -39,13 +40,13 @@
 struct adb_controller *adb_controller = NULL;
 struct notifier_block *adb_client_list = NULL;
 enum adb_hw adb_hardware = ADB_NONE;
+static int adb_got_sleep = 0;
 
 #ifdef CONFIG_PMAC_PBOOK
-static int adb_notify_sleep(struct notifier_block *, unsigned long, void *);
-static struct notifier_block adb_sleep_notifier = {
+static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
+static struct pmu_sleep_notifier adb_sleep_notifier = {
 	adb_notify_sleep,
-	NULL,
-	0
+	SLEEP_LEVEL_ADB,
 };
 #endif
 
@@ -173,8 +174,7 @@
 	{
 		adb_hardware = adb_controller->kind;
 #ifdef CONFIG_PMAC_PBOOK
-		notifier_chain_register(&sleep_notifier_list,
-					&adb_sleep_notifier);
+		pmu_register_sleep_notifier(&adb_sleep_notifier);
 #endif /* CONFIG_PMAC_PBOOK */
 
 		adb_reset_bus();
@@ -187,21 +187,31 @@
  * notify clients before sleep and reset bus afterwards
  */
 int
-adb_notify_sleep(struct notifier_block *this, unsigned long code, void *x)
+adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
 	int ret;
 	
-	switch (code) {
-	case PBOOK_SLEEP:
+	switch (when) {
+	case PBOOK_SLEEP_REQUEST:
+		adb_got_sleep = 1;
 		ret = notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL);
 		if (ret & NOTIFY_STOP_MASK)
-			return -EBUSY;
+			return PBOOK_SLEEP_REFUSE;
+		break;
+	case PBOOK_SLEEP_REJECT:
+		if (adb_got_sleep) {
+			adb_got_sleep = 0;
+			adb_reset_bus();
+		}
+		break;
+		
+	case PBOOK_SLEEP_NOW:
 		break;
 	case PBOOK_WAKE:
 		adb_reset_bus();
 		break;
 	}
-	return NOTIFY_DONE;
+	return PBOOK_SLEEP_OK;
 }
 #endif /* CONFIG_PMAC_PBOOK */
 
diff -urN linux-2.2.12-pre6/drivers/macintosh/mac_keyb.c linux-2.2.12-pre7/drivers/macintosh/mac_keyb.c
--- linux-2.2.12-pre6/drivers/macintosh/mac_keyb.c	2003-08-15 15:07:07.000000000 -0700
+++ linux-2.2.12-pre7/drivers/macintosh/mac_keyb.c	2003-08-15 15:07:08.000000000 -0700
@@ -16,13 +16,14 @@
  *
  * - Standard 1 button mouse
  * - All standard Apple Extended protocol (handler ID 4)
- *   mice & trackballs
+ * - mouseman and trackman mice & trackballs 
  * - PowerBook Trackpad (default setup: enable tapping)
  * - MicroSpeed mouse & trackball (needs testing)
  * - CH Products Trackball Pro (needs testing)
  * - Contour Design (Contour Mouse)
  * - Hunter digital (NoHandsMouse)
  * - Kensignton TurboMouse 5 (needs testing)
+ * - Mouse Systems A3 mice and trackballs <aidan@kublai.com>
  *
  * To do:
  *
@@ -39,6 +40,7 @@
 #include <linux/init.h>
 #include <linux/tty_flip.h>
 #include <linux/config.h>
+#include <linux/notifier.h>
 
 #include <asm/bitops.h>
 #include <asm/adb.h>
@@ -239,6 +241,7 @@
 static void init_trackball(int id);
 static void init_turbomouse(int id);
 static void init_microspeed(int id);
+static void init_ms_a3(int id);
 
 #ifdef CONFIG_ADBMOUSE
 /* XXX: Hook for mouse driver */
@@ -268,6 +271,7 @@
 #define ADBMOUSE_TURBOMOUSE5    5	/* Turbomouse 5 (previously req. mousehack) */
 #define ADBMOUSE_MICROSPEED	6	/* Microspeed mouse (&trackball ?), MacPoint */
 #define ADBMOUSE_TRACKBALLPRO	7	/* Trackball Pro (special buttons) */
+#define ADBMOUSE_MS_A3		8	/* Mouse systems A3 trackball (handler 3) */
 
 static int adb_mouse_kinds[16];
 
@@ -512,6 +516,11 @@
 		data[2] = (data[2] & 0x7f) | ((data[3] & 0x01) << 7);
 		data[3] = (data[3] & 0x77) | ((data[3] & 0x02) << 6);
 		break;
+	    case ADBMOUSE_MS_A3:
+		data[1] = (data[1] & 0x7f) | ((data[3] & 0x01) << 7);
+		data[2] = (data[2] & 0x7f) | ((data[3] & 0x02) << 6);
+		data[3] = ((data[3] & 0x04) << 5);
+		break;
 	}
 
 	if (adb_mouse_interrupt_hook)
@@ -760,10 +769,6 @@
 			printk("ADB mouse at %d, handler set to 4", id);
 			adb_mouse_kinds[id] = ADBMOUSE_EXTENDED;
 		}
-		else if (adb_try_handler_change(id, 2)) {
-			printk("ADB mouse at %d, handler set to 2", id);
-			adb_mouse_kinds[id] = ADBMOUSE_STANDARD_200;
-		}
 		else if (adb_try_handler_change(id, 0x2F)) {
 			printk("ADB mouse at %d, handler set to 0x2F", id);
 			adb_mouse_kinds[id] = ADBMOUSE_MICROSPEED;
@@ -780,6 +785,14 @@
 			printk("ADB mouse at %d, handler set to 0x5F", id);
 			adb_mouse_kinds[id] = ADBMOUSE_MICROSPEED;
 		}
+		else if (adb_try_handler_change(id, 3)) {
+			printk("ADB mouse at %d, handler set to 3", id);
+			adb_mouse_kinds[id] = ADBMOUSE_MS_A3;
+		}
+		else if (adb_try_handler_change(id, 2)) {
+			printk("ADB mouse at %d, handler set to 2", id);
+			adb_mouse_kinds[id] = ADBMOUSE_STANDARD_200;
+		}
 		else {
 			printk("ADB mouse at %d, handler 1", id);
 			adb_mouse_kinds[id] = ADBMOUSE_STANDARD_100;
@@ -788,6 +801,8 @@
 		if ((adb_mouse_kinds[id] == ADBMOUSE_TRACKBALLPRO)
 		    || (adb_mouse_kinds[id] == ADBMOUSE_MICROSPEED)) {
 			init_microspeed(id);
+		} else if (adb_mouse_kinds[id] == ADBMOUSE_MS_A3) {
+			init_ms_a3(id);	
 		}  else if (adb_mouse_kinds[id] ==  ADBMOUSE_EXTENDED) {
 			/*
 			 * Register 1 is usually used for device
@@ -799,7 +814,8 @@
 				    ADB_READREG(id, 1));
 
 			if ((req.reply_len) &&
-			    (req.reply[1] == 0x9a) && (req.reply[2] == 0x21))
+			    (req.reply[1] == 0x9a) && ((req.reply[2] == 0x21)
+			    	|| (req.reply[2] == 0x20)))
 				init_trackball(id);
 			else if ((req.reply_len >= 4) &&
 			    (req.reply[1] == 0x74) && (req.reply[2] == 0x70) &&
@@ -871,7 +887,7 @@
 {
 	struct adb_request req;
 	
-	printk(" (trackball)");
+	printk(" (trackman/mouseman)");
 	
 	adb_mouse_kinds[id] = ADBMOUSE_TRACKBALL;
 
@@ -977,3 +993,18 @@
 
 	adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
 }
+
+static void
+init_ms_a3(int id)
+{
+	struct adb_request req;
+
+	printk(" (Mouse Systems A3 Mouse, or compatible)");
+	adb_request(&req, NULL, ADBREQ_SYNC, 3,
+	ADB_WRITEREG(id, 0x2),
+	    0x00,
+	    0x07);
+ 
+ 	adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
+ }
+
diff -urN linux-2.2.12-pre6/drivers/macintosh/via-pmu.c linux-2.2.12-pre7/drivers/macintosh/via-pmu.c
--- linux-2.2.12-pre6/drivers/macintosh/via-pmu.c	1999-08-09 12:04:57.000000000 -0700
+++ linux-2.2.12-pre7/drivers/macintosh/via-pmu.c	2003-08-15 15:07:08.000000000 -0700
@@ -1,3 +1,4 @@
+
 /*
  * Device driver for the via-pmu on Apple Powermacs.
  *
@@ -33,6 +34,7 @@
 #include <asm/irq.h>
 #include <asm/feature.h>
 #include <asm/uaccess.h>
+#include <asm/mmu_context.h>
 
 /* Misc minor number allocated for /dev/pmu */
 #define PMU_MINOR	154
@@ -71,6 +73,7 @@
 #define IER_SET		0x80		/* set bits in IER */
 #define IER_CLR		0		/* clear bits in IER */
 #define SR_INT		0x04		/* Shift register full/empty */
+#define CB2_INT		0x08
 #define CB1_INT		0x10		/* transition on CB1 input */
 
 static enum pmu_state {
@@ -125,6 +128,16 @@
 	pmu_poll
 };
 
+extern void low_sleep_handler(void);
+extern void sleep_save_intrs(int);
+extern void sleep_restore_intrs(void);
+
+extern int grackle_pcibios_read_config_word(unsigned char bus,
+	unsigned char dev_fn, unsigned char offset, unsigned short *val);
+
+extern int grackle_pcibios_write_config_word(unsigned char bus,
+	unsigned char dev_fn, unsigned char offset, unsigned short val);
+
 /*
  * This table indicates for each PMU opcode:
  * - the number of data bytes to be sent with the command, or -1
@@ -168,13 +181,21 @@
 /*f8*/	{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
 };
 
+static char *pbook_type[] = {
+	"Unknown PowerBook",
+	"PowerBook 2400/3400/3500(G3)",
+	"PowerBook G3 Series",
+	"1999 PowerBook G3",
+};
 
-void __openfirmware
+int __openfirmware
 find_via_pmu()
 {
+	if (via != 0)
+		return 1;
 	vias = find_devices("via-pmu");
 	if (vias == 0)
-		return;
+		return 0;
 	if (vias->next != 0)
 		printk(KERN_WARNING "Warning: only using 1st via-pmu\n");
 	
@@ -196,12 +217,14 @@
 		printk(KERN_ERR "via-pmu: %d addresses, %d interrupts!\n",
 		       vias->n_addrs, vias->n_intrs);
 		if (vias->n_addrs < 1 || vias->n_intrs < 1)
-			return;
+			return 0;
 	}
 
 	if (vias->parent->name && ((strcmp(vias->parent->name, "ohare") == 0)
 	    || device_is_compatible(vias->parent, "ohare")))
 		pmu_kind = PMU_OHARE_BASED;
+	else if (device_is_compatible(vias->parent, "paddington"))
+		pmu_kind = PMU_PADDINGTON_BASED;
 	else if (device_is_compatible(vias->parent, "heathrow"))
 		pmu_kind = PMU_HEATHROW_BASED;
 	else
@@ -220,9 +243,9 @@
 
 	if (via)
 		printk(KERN_INFO "PMU driver initialized for %s\n",
-		    (pmu_kind == PMU_OHARE_BASED) ? "PowerBook 2400/3400/3500(G3)" :
-		    ((pmu_kind == PMU_HEATHROW_BASED) ? "PowerBook G3 Series" :
-		    "Unknown PowerBook"));
+		       pbook_type[pmu_kind]);
+
+	return via != 0;
 }
 
 void __openfirmware
@@ -517,19 +540,25 @@
 static void __openfirmware
 send_byte(int x)
 {
-	out_8(&via[ACR], 0x1c);
-	out_8(&via[SR], x);
-	out_8(&via[B], via[B] & ~0x10);		/* assert TREQ */
+	volatile unsigned char *v = via;
+
+	out_8(&v[ACR], in_8(&v[ACR]) | SR_OUT | SR_EXT);
+	out_8(&v[SR], x);
+	out_8(&v[B], in_8(&v[B]) & ~TREQ);		/* assert TREQ */
 }
 
 static void __openfirmware
 recv_byte()
 {
-	out_8(&via[ACR], 0x0c);
-	in_8(&via[SR]);		/* resets SR */
-	out_8(&via[B], via[B] & ~0x10);
+	volatile unsigned char *v = via;
+
+	out_8(&v[ACR], (in_8(&v[ACR]) & ~SR_OUT) | SR_EXT);
+	in_8(&v[SR]);		/* resets SR */
+	out_8(&v[B], in_8(&v[B]) & ~0x10);
 }
 
+static int disable_poll;
+
 static void __openfirmware
 pmu_start()
 {
@@ -549,7 +578,9 @@
 	data_len = pmu_data_len[req->data[0]][0];
 
 	/* set the shift register to shift out and send a byte */
+	++disable_poll;
 	send_byte(req->data[0]);
+	--disable_poll;
 
 out:
 	restore_flags(flags);
@@ -560,6 +591,8 @@
 {
 	int ie;
 
+	if (disable_poll)
+		return;
 	ie = _disable_interrupts();
 	if (via[IFR] & (SR_INT | CB1_INT))
 		via_pmu_interrupt(0, 0, 0);
@@ -572,6 +605,7 @@
 	int intr;
 	int nloop = 0;
 
+	++disable_poll;
 	while ((intr = in_8(&via[IFR])) != 0) {
 		if (++nloop > 1000) {
 			printk(KERN_DEBUG "PMU: stuck in intr loop, "
@@ -583,11 +617,9 @@
 		else if (intr & CB1_INT) {
 			adb_int_pending = 1;
 			out_8(&via[IFR], CB1_INT);
-		} else
-		{
-			/* -- Disabled printk, will happen _really_ often on
-				  PowerBooks ((CB2 interrupts) --
-			printk(KERN_DEBUG "PMU: spurrious interrupt intr=%x\n", intr); */
+		}
+		intr &= ~(SR_INT | CB1_INT);
+		if (intr != 0) {
 			out_8(&via[IFR], intr);
 		}
 	}
@@ -600,6 +632,7 @@
 			pmu_start();
 		}
 	}
+	--disable_poll;
 }
 
 static void __openfirmware
@@ -608,17 +641,17 @@
 	struct adb_request *req;
 	int bite, timeout;
 
+	if (via[B] & TREQ) {
+		printk(KERN_ERR "PMU: spurious SR intr (%x)\n", via[B]);
+		out_8(&via[IFR], SR_INT);
+		return;
+	}
 	if (via[B] & TACK)
-		printk(KERN_DEBUG "PMU: sr_intr but ack still high! (%x)\n",
+		printk(KERN_ERR "PMU: sr_intr but ack still high! (%x)\n",
 		       via[B]);
 
-	/* if reading grab the byte, and reset the interrupt */
-	if ((via[ACR] & SR_OUT) == 0)
-		bite = in_8(&via[SR]);
-	out_8(&via[IFR], SR_INT);
-
 	/* reset TREQ and wait for TACK to go high */
-	out_8(&via[B], via[B] | TREQ);
+	out_8(&via[B], in_8(&via[B]) | TREQ);
 	timeout = 3200;
 	while ((in_8(&via[B]) & TACK) == 0) {
 		if (--timeout < 0) {
@@ -628,6 +661,11 @@
 		udelay(10);
 	}
 
+	/* if reading grab the byte, and reset the interrupt */
+	if (pmu_state == reading || pmu_state == reading_intr)
+		bite = in_8(&via[SR]);
+	out_8(&via[IFR], SR_INT);
+
 	switch (pmu_state) {
 	case sending:
 		req = current_req;
@@ -710,8 +748,6 @@
 static void __openfirmware
 pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
 {
-	static int show_pmu_ints = 1;
-
 	asleep = 0;
 	if (len < 1) {
 		adb_int_pending = 0;
@@ -733,12 +769,23 @@
 			}
 			pmu_done(req);
 		} else {
+#ifdef CONFIG_XMON
+			if (len == 4 && data[1] == 0x2c) {
+				extern int xmon_wants_key, xmon_pmu_keycode;
+				if (xmon_wants_key) {
+					xmon_pmu_keycode = data[2];
+					return;
+				}
+			}
+#endif /* CONFIG_XMON */
 			/*
-			 * XXX the PMU gives us an up event for keycodes
-			 * 0x74 or 0x75 when the PC card eject buttons
-			 * are released, so we ignore those events.
+			 * XXX On the [23]400 the PMU gives us an up
+			 * event for keycodes 0x74 or 0x75 when the PC
+			 * card eject buttons are released, so we
+			 * ignore those events.
 			 */
-			if (!(len == 4 && data[1] == 0x2c && data[3] == 0xff
+			if (!(pmu_kind == PMU_OHARE_BASED && len == 4
+			      && data[1] == 0x2c && data[3] == 0xff
 			      && (data[2] & ~1) == 0xf4))
 				adb_input(data+1, len-1, regs, 1);
 		}
@@ -749,15 +796,6 @@
 	} else {
 #ifdef CONFIG_PMAC_PBOOK
 		pmu_pass_intr(data, len);
-#else
-		if (show_pmu_ints
-		    && !(data[0] == PMU_INT_TICK && len == 1)) {
-			int i;
-			printk(KERN_DEBUG "pmu intr");
-			for (i = 0; i < len; ++i)
-				printk(" %.2x", data[i]);
-			printk("\n");
-		}
 #endif
 	}
 }
@@ -773,38 +811,46 @@
 	struct adb_request req;
 
 	if (vias == NULL)
-		return ;
+		return;
 		
-	if (on) {
-	    /* first call: get current backlight value */
-	    if (backlight_level < 0) {
-		switch(pmu_kind) {
-		    case PMU_OHARE_BASED:
+	/* first call: get current backlight value */
+	if (on && backlight_level < 0) {
+		switch (pmu_kind) {
+		case PMU_OHARE_BASED:
 			pmu_request(&req, NULL, 2, 0xd9, 0);
 			while (!req.complete)
 				pmu_poll();
 			backlight_level = req.reply[1] >> 3;
-			printk(KERN_DEBUG "pmu: controls returned bright: %d\n", (int)req.reply[1]);
 			break;
-		    case PMU_HEATHROW_BASED:
+		case PMU_HEATHROW_BASED:
+			/* We cannot use nvram_read_byte here (not yet initialized) */
 			pmu_request(&req, NULL, 3, PMU_READ_NVRAM, 0x14, 0xe);
 			while (!req.complete)
 				pmu_poll();
-			printk(KERN_DEBUG "pmu: nvram returned bright: %d\n", (int)req.reply[1]);
 			backlight_level = req.reply[1];
+			printk(KERN_DEBUG "pmu: nvram returned bright: %d\n", backlight_level);
+			break;
+		case PMU_PADDINGTON_BASED:
+			/* the G3 PB 1999 has a backlight node
+			   and chrp-structured nvram */
+			/* XXX should read macos's "blkt" property in nvram
+			   for this node.  For now this ensures that the
+			   backlight doesn't go off as soon as linux boots. */
+			backlight_level = 20;
 			break;
-		    default:
+		default:
 		        backlight_enabled = 0;
 		        return;
 		}
-	    }
-	    pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT,
-	    	LEVEL_TO_BRIGHT(backlight_level));
-	    while (!req.complete)
-		pmu_poll();
+	}
+	if (on) {
+		pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT,
+			    LEVEL_TO_BRIGHT(backlight_level));
+		while (!req.complete)
+			pmu_poll();
 	}
 	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
-	    PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF));
+		    PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF));
 	while (!req.complete)
 		pmu_poll();
 	backlight_enabled = on;
@@ -903,6 +949,68 @@
 
 #ifdef CONFIG_PMAC_PBOOK
 
+static LIST_HEAD(sleep_notifiers);
+
+int
+pmu_register_sleep_notifier(struct pmu_sleep_notifier *n)
+{
+	struct list_head *list;
+	struct pmu_sleep_notifier *current;
+
+	for (list = sleep_notifiers.next; list != &sleep_notifiers;
+	     list = list->next) {
+		current = list_entry(list, struct pmu_sleep_notifier, list);
+		if (n->priority > current->priority)
+			break;
+	}
+	__list_add(&n->list, list->prev, list);
+	return 0;
+}
+
+int
+pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* n)
+{
+	if (n->list.next == 0)
+		return -ENOENT;
+	list_del(&n->list);
+	n->list.next = 0;
+	return 0;
+}
+
+/* Sleep is broadcast last-to-first */
+static int
+broadcast_sleep(int when, int can_cancel)
+{
+	int ret = PBOOK_SLEEP_OK;
+	struct list_head *list;
+	struct pmu_sleep_notifier *current;
+
+	for (list = sleep_notifiers.prev; list != &sleep_notifiers;
+	     list = list->prev) {
+		current = list_entry(list, struct pmu_sleep_notifier, list);
+		ret = current->notifier_call(current, when);
+		if (can_cancel && (ret != PBOOK_SLEEP_OK))
+			return ret;
+	}
+	return ret;
+}
+
+/* Wake is broadcast first-to-last */
+static int
+broadcast_wake(void)
+{
+	int ret = PBOOK_SLEEP_OK;
+	struct list_head *list;
+	struct pmu_sleep_notifier *current;
+
+	for (list = sleep_notifiers.next; list != &sleep_notifiers;
+	     list = list->next) {
+		current = list_entry(list, struct pmu_sleep_notifier, list);
+		current->notifier_call(current, PBOOK_WAKE);
+	}
+	return ret;
+}
+
 /*
  * This struct is used to store config register values for
  * PCI devices which may get powered off when we sleep.
@@ -914,7 +1022,7 @@
 } *pbook_pci_saves;
 static int n_pbook_pci_saves;
 
-static inline void __openfirmware
+static void __openfirmware
 pbook_pci_save(void)
 {
 	int npci;
@@ -941,7 +1049,7 @@
 	}
 }
 
-static inline void __openfirmware
+static void __openfirmware
 pbook_pci_restore(void)
 {
 	u16 cmd;
@@ -974,46 +1082,168 @@
 	}
 }
 
+#if 0
+/* N.B. This doesn't work on the 3400 */
+void pmu_blink(int n)
+{
+	struct adb_request req;
+
+	for (; n > 0; --n) {
+		pmu_request(&req, NULL, 4, 0xee, 4, 0, 1);
+		while (!req.complete) pmu_poll();
+		udelay(50000);
+		pmu_request(&req, NULL, 4, 0xee, 4, 0, 0);
+		while (!req.complete) pmu_poll();
+		udelay(50000);
+	}
+	udelay(50000);
+}
+#endif
+
 /*
  * Put the powerbook to sleep.
  */
-#define IRQ_ENABLE	((unsigned int *)0xf3000024)
-#define MEM_CTRL	((unsigned int *)0xf8000070)
+ 
+#define FEATURE_CTRL(base)	((unsigned int *)(base + 0x38))
+#define	GRACKLE_PM	(1<<7)
+#define GRACKLE_DOZE	(1<<5)
+#define	GRACKLE_NAP	(1<<4)
+#define	GRACKLE_SLEEP	(1<<3)
+
+int __openfirmware powerbook_sleep_G3(void)
+{
+	int ret;
+	unsigned long save_l2cr;
+	unsigned long save_fcr;
+	unsigned long wait;
+	unsigned short pmcr1;
+	struct adb_request sleep_req;
+	struct device_node *macio;
+	unsigned long macio_base = 0;
+
+	macio = find_devices("mac-io");
+	if (macio != 0 && macio->n_addrs > 0)
+		macio_base = (unsigned long)
+			ioremap(macio->addrs[0].address, 0x40);
+
+	/* Sync the disks. */
+	/* XXX It would be nice to have some way to ensure that
+	 * nobody is dirtying any new buffers while we wait. */
+	fsync_dev(0);
+
+	/* Notify device drivers */
+	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, 1);
+	if (ret != PBOOK_SLEEP_OK) {
+		broadcast_sleep(PBOOK_SLEEP_REJECT, 0);
+		printk("pmu: sleep rejected\n");
+		return -EBUSY;
+	}
+	broadcast_sleep(PBOOK_SLEEP_NOW, 0);
+
+	/* Give the disks a little time to actually finish writing */
+	for (wait = jiffies + (HZ/4); time_before(jiffies, wait); )
+		mb();
+
+	/* Disable all interrupts except pmu */
+	sleep_save_intrs(vias->intrs[0].line);
 
-int __openfirmware powerbook_sleep(void)
+	/* Make sure the decrementer won't interrupt us */
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+#if 0
+	/* Save the state of PCI config space for some slots */
+	pbook_pci_save();
+#endif
+	/* For 750, save backside cache setting and disable it */
+	save_l2cr = _get_L2CR();	/* (returns 0 if not 750) */
+	if (save_l2cr)
+		_set_L2CR(0);
+
+	if (macio_base != 0) {
+		save_fcr = in_le32(FEATURE_CTRL(macio_base));
+		/* Check if this is still valid on older powerbooks */
+		out_le32(FEATURE_CTRL(macio_base), save_fcr & ~(0x00000140UL));
+	}
+
+	if (current->tss.regs && (current->tss.regs->msr & MSR_FP) != 0)
+		giveup_fpu(current);
+
+	grackle_pcibios_read_config_word(0,0,0x70,&pmcr1);
+	/* Apparently, MacOS uses NAP mode for Grackle ??? */
+	pmcr1 &= ~(GRACKLE_DOZE|GRACKLE_SLEEP); 
+	pmcr1 |= GRACKLE_PM|GRACKLE_NAP;
+	grackle_pcibios_write_config_word(0, 0, 0x70, pmcr1);
+
+	/* Ask the PMU to put us to sleep */
+	pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
+	while (!sleep_req.complete)
+		mb();
+
+	cli();
+	while (pmu_state != idle)
+		pmu_poll();
+
+	/* Call low-level ASM sleep handler */
+	low_sleep_handler();
+
+	/* We're awake again, stop grackle PM */
+	grackle_pcibios_read_config_word(0, 0, 0x70, &pmcr1);
+	pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); 
+	grackle_pcibios_write_config_word(0, 0, 0x70, pmcr1);
+
+	sti();
+#if 0
+	/* According to someone from Apple, this should not be needed,
+	   at least not for all devices. Let's keep it for now until we
+	   have something that works. */
+	pbook_pci_restore();
+#endif
+	set_context(current->mm->context);
+
+	/* Restore L2 cache */
+	if (save_l2cr)
+		_set_L2CR(save_l2cr | 0x200000); /* set invalidate bit */
+	
+	/* reenable interrupts */
+	sleep_restore_intrs();
+
+	/* Notify drivers */
+	broadcast_wake();
+
+	return 0;
+}
+
+#define PB3400_MEM_CTRL		((unsigned int *)0xf8000070)
+
+int __openfirmware powerbook_sleep_3400(void)
 {
 	int ret, i, x;
-	static int save_backlight;
-	static unsigned int save_irqen;
 	unsigned long msr;
 	unsigned int hid0;
 	unsigned long p, wait;
 	struct adb_request sleep_req;
 
-	/* Notify device drivers */
-	ret = notifier_call_chain(&sleep_notifier_list, PBOOK_SLEEP, NULL);
-	if (ret & NOTIFY_STOP_MASK)
-		return -EBUSY;
-
 	/* Sync the disks. */
 	/* XXX It would be nice to have some way to ensure that
 	 * nobody is dirtying any new buffers while we wait. */
 	fsync_dev(0);
 
-	/* Turn off the display backlight */
-	save_backlight = backlight_enabled;
-	if (save_backlight)
-		pmu_enable_backlight(0);
+	/* Notify device drivers */
+	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, 1);
+	if (ret != PBOOK_SLEEP_OK) {
+		broadcast_sleep(PBOOK_SLEEP_REJECT, 0);
+		printk("pmu: sleep rejected\n");
+		return -EBUSY;
+	}
+	broadcast_sleep(PBOOK_SLEEP_NOW, 0);
 
 	/* Give the disks a little time to actually finish writing */
 	for (wait = jiffies + (HZ/4); time_before(jiffies, wait); )
 		mb();
 
 	/* Disable all interrupts except pmu */
-	save_irqen = in_le32(IRQ_ENABLE);
-	for (i = 0; i < 32; ++i)
-		if (i != vias->intrs[0].line && (save_irqen & (1 << i)))
-			disable_irq(i);
+	sleep_save_intrs(vias->intrs[0].line);
+
+	/* Make sure the decrementer won't interrupt us */
 	asm volatile("mtdec %0" : : "r" (0x7fffffff));
 
 	/* Save the state of PCI config space for some slots */
@@ -1022,9 +1252,9 @@
 	/* Set the memory controller to keep the memory refreshed
 	   while we're asleep */
 	for (i = 0x403f; i >= 0x4000; --i) {
-		out_be32(MEM_CTRL, i);
+		out_be32(PB3400_MEM_CTRL, i);
 		do {
-			x = (in_be32(MEM_CTRL) >> 16) & 0x3ff;
+			x = (in_be32(PB3400_MEM_CTRL) >> 16) & 0x3ff;
 		} while (x == 0);
 		if (x >= 0x100)
 			break;
@@ -1034,6 +1264,7 @@
 	pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
 	while (!sleep_req.complete)
 		mb();
+
 	/* displacement-flush the L2 cache - necessary? */
 	for (p = KERNELBASE; p < KERNELBASE + 0x100000; p += 0x1000)
 		i = *(volatile int *)p;
@@ -1049,7 +1280,7 @@
 	udelay(10);
 
 	/* OK, we're awake again, start restoring things */
-	out_be32(MEM_CTRL, 0x3f);
+	out_be32(PB3400_MEM_CTRL, 0x3f);
 	pbook_pci_restore();
 
 	/* wait for the PMU interrupt sequence to complete */
@@ -1057,21 +1288,10 @@
 		mb();
 
 	/* reenable interrupts */
-	for (i = 0; i < 32; ++i)
-		if (i != vias->intrs[0].line && (save_irqen & (1 << i)))
-			enable_irq(i);
+	sleep_restore_intrs();
 
 	/* Notify drivers */
-	notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL);
-
-	/* reenable ADB autopoll */
-	pmu_adb_autopoll(adb_dev_map);
-
-	/* Turn on the screen backlight, if it was on before */
-	if (save_backlight)
-		pmu_enable_backlight(1);
-
-	/* Wait for the hard disk to spin up */
+	broadcast_wake();
 
 	return 0;
 }
@@ -1224,7 +1444,7 @@
 }
 
 /* Note: removed __openfirmware here since it causes link errors */
-static int /*__openfirmware*/ pmu_ioctl(struct inode * inode, struct file *filp,
+static int pmu_ioctl(struct inode * inode, struct file *filp,
 		     u_int cmd, u_long arg)
 {
 	int error;
@@ -1232,9 +1452,18 @@
 
 	switch (cmd) {
 	case PMU_IOC_SLEEP:
-	    	if (pmu_kind != PMU_OHARE_BASED)
-	    		return -ENOSYS;
-		return powerbook_sleep();
+		switch (pmu_kind) {
+		case PMU_OHARE_BASED:
+			error = powerbook_sleep_3400();
+			break;
+		case PMU_HEATHROW_BASED:
+		case PMU_PADDINGTON_BASED:
+			error = powerbook_sleep_G3();
+			break;
+		default:
+			error = ENOSYS;
+		}
+		return error;
 	case PMU_IOC_GET_BACKLIGHT:
 		return put_user(backlight_level, (__u32 *)arg);
 	case PMU_IOC_SET_BACKLIGHT:
@@ -1272,3 +1501,72 @@
 }
 #endif /* CONFIG_PMAC_PBOOK */
 
+#if 0
+static inline void polled_handshake(volatile unsigned char *via)
+{
+	via[B] &= ~TREQ; eieio();
+	while ((via[B] & TACK) != 0)
+		;
+	via[B] |= TREQ; eieio();
+	while ((via[B] & TACK) == 0)
+		;
+}
+
+static inline void polled_send_byte(volatile unsigned char *via, int x)
+{
+	xmon_printf("s%.2x", x);
+	via[ACR] |= SR_OUT | SR_EXT; eieio();
+	via[SR] = x; eieio();
+	polled_handshake(via);
+}
+
+static inline int polled_recv_byte(volatile unsigned char *via)
+{
+	int x;
+
+	via[ACR] = (via[ACR] & ~SR_OUT) | SR_EXT; eieio();
+	x = via[SR]; eieio();
+	polled_handshake(via);
+	x = via[SR]; eieio();
+	xmon_printf("r%.2x", x);
+	return x;
+}
+
+int
+pmu_polled_request(struct adb_request *req)
+{
+	unsigned long flags;
+	int i, l, c;
+	volatile unsigned char *v = via;
+
+	req->complete = 1;
+	c = req->data[0];
+	l = pmu_data_len[c][0];
+	if (l >= 0 && req->nbytes != l + 1)
+		return -EINVAL;
+
+	save_flags(flags); cli();
+	while (pmu_state != idle)
+		pmu_poll();
+
+	polled_send_byte(v, c);
+	if (l < 0) {
+		l = req->nbytes - 1;
+		polled_send_byte(v, l);
+	}
+	for (i = 1; i <= l; ++i)
+		polled_send_byte(v, req->data[i]);
+
+	l = pmu_data_len[c][1];
+	if (l < 0)
+		l = polled_recv_byte(v);
+	for (i = 0; i < l; ++i)
+		req->reply[i + req->reply_len] = polled_recv_byte(v);
+
+	if (req->done)
+		(*req->done)(req);
+
+	restore_flags(flags);
+	return 0;
+}
+#endif /* 0 */
diff -urN linux-2.2.12-pre6/drivers/net/bmac.c linux-2.2.12-pre7/drivers/net/bmac.c
--- linux-2.2.12-pre6/drivers/net/bmac.c	1999-08-09 12:04:57.000000000 -0700
+++ linux-2.2.12-pre7/drivers/net/bmac.c	2003-08-15 15:07:08.000000000 -0700
@@ -19,6 +19,11 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/feature.h>
+#ifdef CONFIG_PMAC_PBOOK
+#include <asm/adb.h>
+#include <asm/pmu.h>
+#include <asm/irq.h>
+#endif
 #include "bmac.h"
 
 #define trunc_page(x)	((void *)(((unsigned long)(x)) & ~((unsigned long)(PAGE_SIZE - 1))))
@@ -117,6 +122,13 @@
 struct device *bmac_devs = NULL;
 static int is_bmac_plus;
 
+#ifdef CONFIG_PMAC_PBOOK
+int bmac_sleep_notify(struct pmu_sleep_notifier *self, int when);
+static struct pmu_sleep_notifier bmac_sleep_notifier = {
+	bmac_sleep_notify, SLEEP_LEVEL_NET,
+};
+#endif
+
 #if 0
 /*
  * If we can't get a skbuff when we need it, we use this area for DMA.
@@ -244,7 +256,7 @@
 	udelay(10000);
 }
 
-#define MIFDELAY	udelay(500)
+#define MIFDELAY	udelay(10)
 
 static unsigned int
 bmac_mif_readbits(struct device *dev, int nb)
@@ -427,8 +439,8 @@
 	udelay(20000);
 }
 
-static int
-bmac_init_chip(struct device *dev)
+static void
+bmac_init_phy(struct device *dev)
 {
 	unsigned int addr;
 
@@ -451,10 +463,54 @@
 		} else
 			bmac_mif_write(dev, 0, 0x1000);
 	}
+}
+
+static int
+bmac_init_chip(struct device *dev)
+{
+	bmac_init_phy(dev);
 	bmac_init_registers(dev);
 	return 1;
 }
 
+#ifdef CONFIG_PMAC_PBOOK
+int
+bmac_sleep_notify(struct pmu_sleep_notifier *self, int when)
+{
+	struct bmac_data *bp;
+
+	if (bmac_devs == 0)
+		return PBOOK_SLEEP_OK;
+		
+	bp = (struct bmac_data *) bmac_devs->priv;
+	
+	switch (when) {
+	case PBOOK_SLEEP_REQUEST:
+		break;
+	case PBOOK_SLEEP_REJECT:
+		break;
+	case PBOOK_SLEEP_NOW:
+		/* prolly should wait for dma to finish & turn off the chip */
+		disable_irq(bmac_devs->irq);
+		disable_irq(bp->tx_dma_intr);
+		disable_irq(bp->rx_dma_intr);
+		feature_set(bp->node, FEATURE_BMac_reset);
+		udelay(10000);
+		feature_clear(bp->node, FEATURE_BMac_IO_enable);
+		udelay(10000);
+		break;
+	case PBOOK_WAKE:
+		/* see if this is enough */
+		bmac_reset_and_enable(bmac_devs, 1);
+		enable_irq(bmac_devs->irq);
+		enable_irq(bp->tx_dma_intr);
+		enable_irq(bp->rx_dma_intr);
+		break;
+	}
+	return PBOOK_SLEEP_OK;
+}
+#endif
+
 static int bmac_set_address(struct device *dev, void *addr)
 {
 	unsigned char *p = addr;
@@ -1220,7 +1276,12 @@
 	if (bmacs == NULL) return -ENODEV;
 	next_bmac = bmacs->next;
 
-	bmac_devs = dev; /* KLUDGE!! */
+	if (bmac_devs == 0) {
+		bmac_devs = dev; /* KLUDGE!! */
+#ifdef CONFIG_PMAC_PBOOK
+		pmu_register_sleep_notifier(&bmac_sleep_notifier);
+#endif
+	}
 
 	if (bmacs->n_addrs != 3 || bmacs->n_intrs != 3) {
 		printk(KERN_ERR "can't use BMAC %s: expect 3 addrs and 3 intrs\n",
@@ -1556,15 +1617,24 @@
     res = bmac_probe(NULL);
     return res;
 }
+
 void cleanup_module(void)
 {
-    struct bmac_data *bp = (struct bmac_data *) bmac_devs->priv;
+    struct bmac_data *bp;
+
+    if (bmac_devs == 0)
+	return;
+
+    bp = (struct bmac_data *) bmac_devs->priv;
     unregister_netdev(bmac_devs);
 
     free_irq(bmac_devs->irq, bmac_misc_intr);
     free_irq(bp->tx_dma_intr, bmac_txdma_intr);
     free_irq(bp->rx_dma_intr, bmac_rxdma_intr);
 
+#ifdef CONFIG_PMAC_PBOOK
+    pmu_unregister_sleep_notifier(&bmac_sleep_notifier);
+#endif
     kfree(bmac_devs);
     bmac_devs = NULL;
 }
diff -urN linux-2.2.12-pre6/drivers/sound/dmasound.c linux-2.2.12-pre7/drivers/sound/dmasound.c
--- linux-2.2.12-pre6/drivers/sound/dmasound.c	1999-08-09 12:04:57.000000000 -0700
+++ linux-2.2.12-pre7/drivers/sound/dmasound.c	2003-08-15 15:07:08.000000000 -0700
@@ -242,6 +242,9 @@
 static short *beep_buf;
 static volatile struct dbdma_cmd *beep_dbdma_cmd;
 static void (*orig_mksound)(unsigned int, unsigned int);
+static int is_pbook_3400;
+static int is_pbook_G3;
+static unsigned char *macio_base;
 
 /* Burgundy functions */
 static void awacs_burgundy_wcw(unsigned addr,unsigned newval);
@@ -255,9 +258,9 @@
 /*
  * Stuff for restoring after a sleep.
  */
-static int awacs_sleep_notify(struct notifier_block *, unsigned long, void *);
-struct notifier_block awacs_sleep_notifier = {
-	awacs_sleep_notify
+static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when);
+struct pmu_sleep_notifier awacs_sleep_notifier = {
+	awacs_sleep_notify, SLEEP_LEVEL_SOUND,
 };
 #endif /* CONFIG_PMAC_PBOOK */
 
@@ -3020,7 +3023,7 @@
 		kfree(beep_buf);
 	kd_mksound = orig_mksound;
 #ifdef CONFIG_PMAC_PBOOK
-	notifier_chain_unregister(&sleep_notifier_list, &awacs_sleep_notifier);
+	pmu_unregister_sleep_notifier(&awacs_sleep_notifier);
 #endif
 }
 #endif /* MODULE */
@@ -3342,14 +3345,15 @@
 /*
  * Save state when going to sleep, restore it afterwards.
  */
-static int awacs_sleep_notify(struct notifier_block *this,
-			      unsigned long code, void *x)
+static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when)
 {
-	switch (code) {
-	case PBOOK_SLEEP:
+	switch (when) {
+	case PBOOK_SLEEP_NOW:
 		/* XXX we should stop any dma in progress when going to sleep
 		   and restart it when we wake. */
 		PMacSilence();
+		disable_irq(awacs_irq);
+		disable_irq(awacs_tx_irq);
 		break;
 	case PBOOK_WAKE:
 		out_le32(&awacs->control, MASK_IEPC
@@ -3360,8 +3364,10 @@
 		awacs_write(awacs_reg[2] | MASK_ADDR2);
 		awacs_write(awacs_reg[4] | MASK_ADDR4);
 		out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE);
+		enable_irq(awacs_irq);
+		enable_irq(awacs_tx_irq);
 	}
-	return NOTIFY_DONE;
+	return PBOOK_SLEEP_OK;
 }
 #endif /* CONFIG_PMAC_PBOOK */
 
@@ -3983,7 +3989,8 @@
 
 #ifdef CONFIG_PPC
 	case DMASND_AWACS:
-		if (awacs_revision<AWACS_BURGUNDY) { /* Different IOCTLS for burgundy*/
+		/* Different IOCTLS for burgundy*/
+		if (awacs_revision < AWACS_BURGUNDY) {
 			switch (cmd) {
 			case SOUND_MIXER_INFO: {
 			    mixer_info info;
@@ -4999,9 +5006,33 @@
 			printk(KERN_WARNING "dmasound: no memory for "
 			       "beep buffer\n");
 #ifdef CONFIG_PMAC_PBOOK
-		notifier_chain_register(&sleep_notifier_list,
-					&awacs_sleep_notifier);
+		pmu_register_sleep_notifier(&awacs_sleep_notifier);
 #endif /* CONFIG_PMAC_PBOOK */
+
+		/* Powerbooks have odd ways of enabling inputs such as
+		   an expansion-bay CD or sound from an internal modem
+		   or a PC-card modem. */
+		if (machine_is_compatible("AAPL,3400/2400")) {
+			is_pbook_3400 = 1;
+			/*
+			 * Enable CD and PC-card sound inputs.
+			 * This is done by reading from address
+			 * f301a000, + 0x10 to enable the expansion-bay
+			 * CD sound input, + 0x80 to enable the PC-card
+			 * sound input.  The 0x100 seems to enable the
+			 * MESH and/or its SCSI bus drivers.
+			 */
+			in_8((unsigned char *)0xf301a190);
+		} else if (machine_is_compatible("PowerBook1,1")) {
+			np = find_devices("mac-io");
+			if (np && np->n_addrs > 0) {
+				is_pbook_G3 = 1;
+				macio_base = (unsigned char *)
+					ioremap(np->addrs[0].address, 0x40);
+				/* enable CD sound input */
+				out_8(macio_base + 0x37, 3);
+			}
+		}
 	}
 #endif /* CONFIG_PPC */
 
diff -urN linux-2.2.12-pre6/drivers/video/offb.c linux-2.2.12-pre7/drivers/video/offb.c
--- linux-2.2.12-pre6/drivers/video/offb.c	1999-04-29 12:53:48.000000000 -0700
+++ linux-2.2.12-pre7/drivers/video/offb.c	2003-08-15 15:07:08.000000000 -0700
@@ -346,6 +346,21 @@
 		    dp->addrs[0].size = 0x01000000;
 		}
 	    }
+
+	    /*
+	     * The LTPro on the Lombard powerbook has no addresses
+	     * on the display nodes, they are on their parent.
+	     */
+	    if (dp->n_addrs == 0 && device_is_compatible(dp, "ATY,264LTPro")) {
+		int na;
+		unsigned int *ap = (unsigned int *)
+		    get_property(dp, "AAPL,address", &na);
+		if (ap != 0)
+		    for (na /= sizeof(unsigned int); na > 0; --na, ++ap)
+			if (*ap <= addr && addr < *ap + 0x1000000)
+			    goto foundit;
+	    }
+
 	    /*
 	     * See if the display address is in one of the address
 	     * ranges for this display.
@@ -356,6 +371,7 @@
 		    break;
 	    }
 	    if (i < dp->n_addrs) {
+	    foundit:
 		printk(KERN_INFO "MacOS display is %s\n", dp->full_name);
 		macos_display = dp;
 		break;
diff -urN linux-2.2.12-pre6/include/asm-ppc/bootx.h linux-2.2.12-pre7/include/asm-ppc/bootx.h
--- linux-2.2.12-pre6/include/asm-ppc/bootx.h	1999-03-10 21:30:32.000000000 -0800
+++ linux-2.2.12-pre7/include/asm-ppc/bootx.h	2003-08-15 15:07:08.000000000 -0700
@@ -11,6 +11,7 @@
 
 #ifdef macintosh
 #include <Types.h>
+#include "linux_type_defs.h"
 #endif
 
 #ifdef macintosh
@@ -18,66 +19,118 @@
 #pragma options align=power
 #endif
 
-/* On boostrap entry:
+/* On kernel entry:
  *
- * r3 = 0x426f6f58	('BooX')
+ * r3 = 0x426f6f58    ('BooX')
  * r4 = pointer to boot_infos
  * r5 = NULL
+ *
+ * Data and instruction translation disabled, interrupts
+ * disabled, kernel loaded at physical 0x00000000 on PCI
+ * machines (will be different on NuBus).
+ */
+
+#define BOOT_INFO_VERSION               5
+#define BOOT_INFO_COMPATIBLE_VERSION    1
+
+/* Bit in the architecture flag mask. More to be defined in
+   future versions. Note that either BOOT_ARCH_PCI or
+   BOOT_ARCH_NUBUS is set. The other BOOT_ARCH_NUBUS_xxx are
+   set additionally when BOOT_ARCH_NUBUS is set.
  */
+#define BOOT_ARCH_PCI                   0x00000001UL
+#define BOOT_ARCH_NUBUS                 0x00000002UL
+#define BOOT_ARCH_NUBUS_PDM             0x00000010UL
+#define BOOT_ARCH_NUBUS_PERFORMA        0x00000020UL
+#define BOOT_ARCH_NUBUS_POWERBOOK       0x00000040UL
+
+/*  Maximum number of ranges in phys memory map */
+#define MAX_MEM_MAP_SIZE				26
+
+/* This is the format of an element in the physical memory map. Note that
+   the map is optional and current BootX will only build it for pre-PCI
+   machines */
+typedef struct boot_info_map_entry
+{
+    __u32       physAddr;                /* Physical starting address */
+    __u32       size;                    /* Size in bytes */
+} boot_info_map_entry_t;
 
-#define BOOT_INFO_VERSION		2
-#define BOOT_INFO_COMPATIBLE_VERSION	1
 
 /* Here are the boot informations that are passed to the bootstrap
  * Note that the kernel arguments and the device tree are appended
  * at the end of this structure. */
 typedef struct boot_infos
 {
-	/* Version of this structure */
-	unsigned long	version;
-	/* backward compatible down to version: */
-	unsigned long	compatible_version;
-	
-	/* NEW (vers. 2) this holds the current _logical_ base addr of
-	   the frame buffer (for use by early boot message) */
-	unsigned char*	logicalDisplayBase;
-
-	/* Set to 0 by current BootX */
-	unsigned long	unused[2];
-	
-	/* The device tree (internal addresses relative to the beginning of the tree,
-	 * device tree offset relative to the beginning of this structure). */
-	unsigned long	deviceTreeOffset;	/* Device tree offset */
-	unsigned long	deviceTreeSize;		/* Size of the device tree */
-		
-	/* Some infos about the current MacOS display */
-	unsigned long	dispDeviceRect[4];	/* left,top,right,bottom */
-	unsigned long	dispDeviceDepth;	/* (8, 16 or 32) */
-	unsigned char*	dispDeviceBase;		/* base address (physical) */
-	unsigned long	dispDeviceRowBytes;	/* rowbytes (in bytes) */
-	unsigned long	dispDeviceColorsOffset;	/* Colormap (8 bits only) or 0 (*) */
-	/* Optional offset in the registry to the current
-	 * MacOS display. (Can be 0 when not detected) */
- 	unsigned long	dispDeviceRegEntryOffset;
-
-	/* Optional pointer to boot ramdisk (offset from this structure) */
-	unsigned long	ramDisk;
-	unsigned long	ramDiskSize;		/* size of ramdisk image */
-	
-	/* Kernel command line arguments (offset from this structure) */
-	unsigned long	kernelParamsOffset;
-		
+    /* Version of this structure */
+    __u32       version;
+    /* backward compatible down to version: */
+    __u32       compatible_version;
+    
+    /* NEW (vers. 2) this holds the current _logical_ base addr of
+       the frame buffer (for use by early boot message) */
+    __u8*       logicalDisplayBase;
+
+    /* NEW (vers. 4) Apple's machine identification */
+    __u32       machineID;
+
+    /* NEW (vers. 4) Detected hw architecture */
+    __u32       architecture;
+    
+    /* The device tree (internal addresses relative to the beginning of the tree,
+     * device tree offset relative to the beginning of this structure).
+     * On pre-PCI macintosh (BOOT_ARCH_PCI bit set to 0 in architecture), this
+     * field is 0.
+     */
+    __u32       deviceTreeOffset;        /* Device tree offset */
+    __u32       deviceTreeSize;          /* Size of the device tree */
+        
+    /* Some infos about the current MacOS display */
+    __u32       dispDeviceRect[4];       /* left,top,right,bottom */
+    __u32       dispDeviceDepth;         /* (8, 16 or 32) */
+    __u8*       dispDeviceBase;          /* base address (physical) */
+    __u32       dispDeviceRowBytes;      /* rowbytes (in bytes) */
+    __u32       dispDeviceColorsOffset;  /* Colormap (8 bits only) or 0 (*) */
+    /* Optional offset in the registry to the current
+     * MacOS display. (Can be 0 when not detected) */
+     __u32      dispDeviceRegEntryOffset;
+
+    /* Optional pointer to boot ramdisk (offset from this structure) */
+    __u32       ramDisk;
+    __u32       ramDiskSize;             /* size of ramdisk image */
+    
+    /* Kernel command line arguments (offset from this structure) */
+    __u32       kernelParamsOffset;
+    
+    /* ALL BELOW NEW (vers. 4) */
+    
+    /* This defines the physical memory. Valid with BOOT_ARCH_NUBUS flag
+       (non-PCI) only. On PCI, memory is contiguous and it's size is in the
+       device-tree. */
+    boot_info_map_entry_t
+    	        physMemoryMap[MAX_MEM_MAP_SIZE]; /* Where the phys memory is */
+    __u32       physMemoryMapSize;               /* How many entries in map */
+    
+				
+    /* The framebuffer size (optional, currently 0) */
+    __u32       frameBufferSize;         /* Represents a max size, can be 0. */
+    
+    /* NEW (vers. 5) */
+
+    /* Total params size (args + colormap + device tree + ramdisk) */
+    __u32       totalParamsSize;
+
 } boot_infos_t;
 
 /* (*) The format of the colormap is 256 * 3 * 2 bytes. Each color index is represented
  * by 3 short words containing a 16 bits (unsigned) color component.
  * Later versions may contain the gamma table for direct-color devices here.
  */
-#define BOOTX_COLORTABLE_SIZE	(256UL*3UL*2UL)
+#define BOOTX_COLORTABLE_SIZE    (256UL*3UL*2UL)
 
 #ifdef macintosh
 #pragma options align=reset
 #endif
 
 #endif
-
+    
\ No newline at end of file
diff -urN linux-2.2.12-pre6/include/asm-ppc/feature.h linux-2.2.12-pre7/include/asm-ppc/feature.h
--- linux-2.2.12-pre6/include/asm-ppc/feature.h	1999-03-10 21:30:32.000000000 -0800
+++ linux-2.2.12-pre7/include/asm-ppc/feature.h	2003-08-15 15:07:08.000000000 -0700
@@ -36,6 +36,8 @@
 	FEATURE_BMac_reset,
 	FEATURE_BMac_IO_enable,
 	FEATURE_Modem_Reset,
+	FEATURE_IDE_DiskPower,
+	FEATURE_IDE_Reset,
 	FEATURE_last,
 };
 
diff -urN linux-2.2.12-pre6/include/asm-ppc/ohare.h linux-2.2.12-pre7/include/asm-ppc/ohare.h
--- linux-2.2.12-pre6/include/asm-ppc/ohare.h	1999-03-10 21:30:32.000000000 -0800
+++ linux-2.2.12-pre7/include/asm-ppc/ohare.h	2003-08-15 15:07:08.000000000 -0700
@@ -18,7 +18,9 @@
 #define OH_BAY_IDE_ENABLE	8
 #define OH_BAY_FLOPPY_ENABLE	0x10
 #define OH_IDE_ENABLE		0x20
+#define OH_IDE_POWER		0x40	/* a guess */
 #define OH_BAY_ENABLE		0x80
+#define OH_IDE_RESET		0x100	/* 0-based, a guess */
 #define OH_SCC_ENABLE		0x200
 #define OH_MESH_ENABLE		0x400
 #define OH_FLOPPY_ENABLE	0x800
diff -urN linux-2.2.12-pre6/include/asm-ppc/pmu.h linux-2.2.12-pre7/include/asm-ppc/pmu.h
--- linux-2.2.12-pre6/include/asm-ppc/pmu.h	1999-04-29 12:39:01.000000000 -0700
+++ linux-2.2.12-pre7/include/asm-ppc/pmu.h	2003-08-15 15:07:08.000000000 -0700
@@ -33,20 +33,23 @@
 #define PMU_POW_ON		0x80	/* OR this to power ON the device */
 #define PMU_POW_OFF		0x00	/* leave bit 7 to 0 to power it OFF */
 #define PMU_POW_BACKLIGHT	0x01	/* backlight power */
-#define PMU_POW_IRLED		0x04	/* IR led power (on wallstreet) ??? */
+#define PMU_POW_IRLED		0x04	/* IR led power (on wallstreet) */
 
 /* Bits in PMU interrupt and interrupt mask bytes */
 #define PMU_INT_ADB_AUTO	0x04	/* ADB autopoll, when PMU_INT_ADB */
 #define PMU_INT_PCEJECT		0x04	/* PC-card eject buttons */
 #define PMU_INT_SNDBRT		0x08	/* sound/brightness up/down buttons */
 #define PMU_INT_ADB		0x10	/* ADB autopoll or reply data */
+#define PMU_INT_BATTERY		0x20
+#define PMU_INT_WAKEUP		0x40
 #define PMU_INT_TICK		0x80	/* 1-second tick interrupt */
 
 /* Kind of PMU (model) */
 enum {
-  PMU_UNKNOWN,
-  PMU_OHARE_BASED,
-  PMU_HEATHROW_BASED
+	PMU_UNKNOWN,
+	PMU_OHARE_BASED,	/* 2400, 3400, 3500 (old G3 powerbook) */
+	PMU_HEATHROW_BASED,	/* PowerBook G3 series */
+	PMU_PADDINGTON_BASED,	/* 1999 PowerBook G3 */
 };
 
 /*
@@ -65,7 +68,7 @@
 
 #ifdef __KERNEL__
 
-void find_via_pmu(void);
+int find_via_pmu(void);
 void via_pmu_init(void);
 
 int pmu_request(struct adb_request *req,
@@ -83,15 +86,49 @@
 int pmu_present(void);
 int pmu_get_model(void);
 
+#ifdef CONFIG_PMAC_PBOOK
 /*
  * Stuff for putting the powerbook to sleep and waking it again.
+ *
  */
-#include <linux/notifier.h>
+#include <linux/list.h>
 
-extern struct notifier_block *sleep_notifier_list;
+struct pmu_sleep_notifier
+{
+	int (*notifier_call)(struct pmu_sleep_notifier *self, int when);
+	int priority;
+	struct list_head list;
+};
+
+/* Code values for calling sleep/wakeup handlers
+ *
+ * Note: If a sleep request got cancelled, all drivers will get
+ * the PBOOK_SLEEP_REJECT, even those who didn't get the PBOOK_SLEEP_REQUEST.
+ */
+#define PBOOK_SLEEP_REQUEST	1
+#define PBOOK_SLEEP_NOW		2
+#define PBOOK_SLEEP_REJECT	3
+#define PBOOK_WAKE		4
+
+/* Result codes returned by the notifiers */
+#define PBOOK_SLEEP_OK		0
+#define PBOOK_SLEEP_REFUSE	-1
+
+/* priority levels in notifiers */
+#define SLEEP_LEVEL_VIDEO	100	/* Video driver (first wake) */
+#define SLEEP_LEVEL_SOUND	90	/* Sound driver */
+#define SLEEP_LEVEL_MEDIABAY	80	/* Media bay driver */
+#define SLEEP_LEVEL_BLOCK	70	/* IDE, SCSI */
+#define SLEEP_LEVEL_NET		60	/* bmac */
+#define SLEEP_LEVEL_ADB		50	/* ADB */
+#define SLEEP_LEVEL_MISC	30	/* Anything */
+#define SLEEP_LEVEL_LAST	0	/* Anything */
+
+/* special register notifier functions */
+int pmu_register_sleep_notifier(struct pmu_sleep_notifier* notifier);
+int pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* notifier);
+
+#endif /* CONFIG_PMAC_PBOOK */
 
-/* code values for calling sleep/wakeup handlers */
-#define PBOOK_SLEEP	1
-#define PBOOK_WAKE	2
 
 #endif	/* __KERNEL */
diff -urN linux-2.2.12-pre6/include/asm-ppc/processor.h linux-2.2.12-pre7/include/asm-ppc/processor.h
--- linux-2.2.12-pre6/include/asm-ppc/processor.h	1999-08-09 12:04:57.000000000 -0700
+++ linux-2.2.12-pre7/include/asm-ppc/processor.h	2003-08-15 15:07:08.000000000 -0700
@@ -51,6 +51,7 @@
 #define HID0_DLOCK	(1<<12)		/* Data Cache Lock */
 #define HID0_ICFI	(1<<11)		/* Instruction Cache Flash Invalidate */
 #define HID0_DCI	(1<<10)		/* Data Cache Invalidate */
+#define HID0_SPD	(1<<9)		/* Speculative disable */
 #define HID0_SIED	(1<<7)		/* Serial Instruction Execution [Disable] */
 #define HID0_BHTE	(1<<2)		/* Branch History Table Enable */
 #define HID0_BTCD	(1<<1)		/* Branch target cache disable */
diff -urN linux-2.2.12-pre6/include/asm-ppc/prom.h linux-2.2.12-pre7/include/asm-ppc/prom.h
--- linux-2.2.12-pre6/include/asm-ppc/prom.h	1998-11-15 10:51:50.000000000 -0800
+++ linux-2.2.12-pre7/include/asm-ppc/prom.h	2003-08-15 15:07:08.000000000 -0700
@@ -72,7 +72,8 @@
 extern struct device_node *find_compatible_devices(const char *type,
 						   const char *compat);
 extern struct device_node *find_phandle(phandle);
-extern int device_is_compatible(struct device_node *device, const char* compat);
+extern int device_is_compatible(struct device_node *device, const char *);
+extern int machine_is_compatible(const char *compat);
 extern unsigned char *get_property(struct device_node *node, const char *name,
 				   int *lenp);
 extern void print_properties(struct device_node *node);
