diff -u --recursive --new-file linux-2.0.39/CREDITS linux-2.0.40/CREDITS
--- linux-2.0.39/CREDITS	Fri Dec 15 04:12:28 2000
+++ linux-2.0.40/CREDITS	Sat Feb 24 02:31:44 2001
@@ -3,7 +3,7 @@
 	formatted in a format that allows for easy grepping and
 	beautification by scripts.  The fields are: name (N), email (E),
 	web-address (W), PGP key ID and fingerprint (P), description (D)
-	and snail-mail address (S). 
+	and snail-mail address (S).
 	Thanks,
 
 			Linus
@@ -263,7 +263,7 @@
 E: jjo@mendoza.gov.ar
 D: Network driver alias support
 D: IP masq hashing and app modules
-D: IP ip_dynaddr bits 
+D: IP ip_dynaddr bits
 S: Las Cuevas 2385 - Bo Guemes
 S: Las Heras, Mendoza CP 5539
 S: Argentina
@@ -513,7 +513,7 @@
 N: Paul Gortmaker
 E: p_gortmaker@yahoo.com
 D: Real Time Clock driver author.
-D: 8390 net driver hacker (ne2000, wd8013, smc-ultra, 3c503, etc.) 
+D: 8390 net driver hacker (ne2000, wd8013, smc-ultra, 3c503, etc.)
 D: Ethernet-HowTo and BootPrompt-HowTo author.
 D: Added many new CONFIG options (modules, ramdisk, generic-serial, etc.)
 D: Implemented 1st "official" kernel thread (moved user bdflush to kflushd)
@@ -540,7 +540,7 @@
 W: http://www.torque.net/linux-pp.html
 D: Iomega PPA / ZIP driver
 S: 44 St. Joseph Street, Suite 506
-S: Toronto, Ontario, M4Y 2W4 
+S: Toronto, Ontario, M4Y 2W4
 S: Canada
 
 N: Danny ter Haar
@@ -717,7 +717,7 @@
 N: Bernhard Kaindl
 E: bkaindl@netway.at
 E: edv@bartelt.via.at
-D: Author of a menu based configuration tool, kmenu, which 
+D: Author of a menu based configuration tool, kmenu, which
 D: is the predecessor of 'make menuconfig' and 'make xconfig'.
 S: Tallak 95
 S: 8103 Rein
@@ -781,7 +781,7 @@
 D: IP transparent proxy support
 S: X/OS Experts in Open Systems BV
 S: Kruislaan 419
-S: 1098 VA Amsterdam 
+S: 1098 VA Amsterdam
 S: The Netherlands
 
 N: Gero Kuhlmann
@@ -922,7 +922,7 @@
 D: BOOTP support
 S: Kankovskeho 1241
 S: 182 00 Praha 8
-S: Czech Republic 
+S: Czech Republic
 
 N: John A. Martin
 E: jam@acm.org
@@ -970,7 +970,7 @@
 P: 1024/04B6E8F5 6C 77 33 CA CC D6 22 03  AB AB 15 A3 AE AD 39 7D
 D: Kernel hacker. Software watchdog daemon.
 D: Maintainer of several Debian packages
-S: Th.-Heuss-Str. 61 
+S: Th.-Heuss-Str. 61
 S: D-41812 Erkelenz
 S: Germany
 
@@ -1085,7 +1085,7 @@
 W: http://www.i-Connect.Net/~mike/
 D: Developer and maintainer of the EATA-DMA SCSI driver
 D: Co-developer EATA-PIO SCSI driver
-D: /proc/scsi and assorted other snippets 
+D: /proc/scsi and assorted other snippets
 S: Zum Schiersteiner Grund 2
 S: 55127 Mainz
 S: Germany
@@ -1131,23 +1131,23 @@
 S: Russia
 
 N: Kai Petzke
-E: wpp@marie.physik.tu-berlin.de
-W: http://physik.tu-berlin.de/~wpp
-P: 1024/B42868C1 D9 59 B9 98 BB 93 05 38  2E 3E 31 79 C3 65 5D E1 
+E: petzke@teltarif.de
+W: http://www.teltarif.de/
+P: 1024/B42868C1 D9 59 B9 98 BB 93 05 38  2E 3E 31 79 C3 65 5D E1
 D: Driver for Laser Magnetic Storage CD-ROM
 D: Some kernel bug fixes
 D: Port of the database Postgres
-D: "Unix fuer Jedermann" a German introduction to linux (see my web page)
-S: M"ullerstr. 69
-S: 13349 Berlin
+D: Book: "Linux verstehen und anwenden" (Hanser-Verlag)
+S: Triftstraße 55
+S: 13353 Berlin
 S: Germany
 
 N: Ken Pizzini
 E: ken@halcyon.com
 D: CDROM driver "sonycd535" (Sony CDU-535/531)
 
-N: Frederic Potter 
-E: Frederic.Potter@masi.ibp.fr 
+N: Frederic Potter
+E: Frederic.Potter@masi.ibp.fr
 D: Some PCI kernel support
 
 N: Stefan Probst
@@ -1327,7 +1327,7 @@
 E: csmall@triode.apana.org.au
 E: vk2xlz@gonzo.vk2xlz.ampr.org (packet radio)
 D: Gracilis PackeTwin device driver
-D: RSPF daemon 
+D: RSPF daemon
 S: 10 Stockalls Place
 S: Minto, NSW, 2566
 S: Australia
@@ -1440,7 +1440,7 @@
 E: tsusheng@scf.usc.edu
 D: IGMP(Internet Group Management Protocol) version 2
 S: 2F 14 ALY 31 LN 166 SEC 1 SHIH-PEI RD
-S: Taipei 
+S: Taipei
 S: Taiwan 112
 S: Republic of China
 S: 24335 Delta Drive
@@ -1529,7 +1529,7 @@
 D: patches for ghostscript, worked on color 'ls', etc.
 S: 301 15th Street S.
 S: Moorhead, Minnesota 56560
-S: USA 
+S: USA
 
 N: Jos Vos
 E: jos@xos.nl
@@ -1537,7 +1537,7 @@
 D: Various IP firewall updates, ipfwadm
 S: X/OS Experts in Open Systems BV
 S: Kruislaan 419
-S: 1098 VA Amsterdam 
+S: 1098 VA Amsterdam
 S: The Netherlands
 
 N: Juergen Weigert
@@ -1628,7 +1628,7 @@
 E: R.E.Wolff@BitWizard.nl
 D: Written kmalloc/kfree
 D: Written Specialix IO8+ driver
-S: Van Bronckhorststraat 12 
+S: Van Bronckhorststraat 12
 S: 2612 XV  Delft
 S: The Netherlands
 
@@ -1688,7 +1688,7 @@
 S: France
 
 # Don't add your name here, unless you really _are_ after Marc
-# alphabetically. Leonard used to be very proud of being the 
+# alphabetically. Leonard used to be very proud of being the
 # last entry, and he'll get positively pissed if he can't even
 # be second-to-last.  (and this file really _is_ supposed to be
-# in alphabetic order) 
+# in alphabetic order)
diff -u --recursive --new-file linux-2.0.39/Documentation/Configure.help linux-2.0.40/Documentation/Configure.help
--- linux-2.0.39/Documentation/Configure.help	Wed Jun 28 14:45:46 2000
+++ linux-2.0.40/Documentation/Configure.help	Mon Oct  8 14:06:30 2001
@@ -4977,6 +4977,39 @@
   split subject to kernel constraints. If you don't know how it works
   don't pick it.
 
+Memory flooding
+CONFIG_SADISTIC_KMALLOC
+  A common class of errors, both in userspace programs and the kernel,
+  is accessing memory areas after freeing them.  Programs with such
+  errors often work anyway most of the time, since the bug only bites
+  if something else happens to allocate the same area in a short time
+  window.
+  This option will cause the memory allocator to immediately destroy 
+  any data that has been freed within the kernel, causing such bugs to
+  manifest consistently so they may be solved.  Newly allocated memory
+  is also flooded, making failure-to-initialize bugs easier to detect.
+  This feature does not affect bugs in userspace programs.
+  Non-kernel hackers should say N.  If there are any such bugs in the
+  kernel, there is no point provoking them if you are not prepared to
+  fix them.  And it will run slightly slower.
+
+Socket-buffer consistency checking
+CONFIG_SKB_CHECK
+  The networking facilities of Linux use a special system of memory
+  management, known as socket buffers or SKBs.  SKB structures are
+  moderately complicated and could be corrupted by kernel bugs, later 
+  causing puzzling crashes.
+  This option causes SKBs to be rechecked almost every time they are
+  used, leading to earlier detection of such problems.  This will
+  reduce performance -- however it does not affect the likelihood of
+  the kernel crashing.  Non-kernel hackers should say N.
+
+Whole-queue checking
+CONFIG_SKB_CHECK_WHOLE_QUEUE
+  This option is an extension of CONFIG_SKB_CHECK.  Whenever a list
+  header is validated, this mode will traverse the entire list looking
+  for inconsistent pointers.
+
 # need an empty line after last entry, for sed script in Configure.
 
 #
diff -u --recursive --new-file linux-2.0.39/Documentation/cdrom/sbpcd linux-2.0.40/Documentation/cdrom/sbpcd
--- linux-2.0.39/Documentation/cdrom/sbpcd	Wed Feb  7 07:17:49 1996
+++ linux-2.0.40/Documentation/cdrom/sbpcd	Mon Sep 10 15:36:47 2001
@@ -569,11 +569,11 @@
 
 #ifdef AZT_PRIVATE_IOCTLS
 #include <linux/aztcd.h>
-#endif AZT_PRIVATE_IOCTLS
+#endif /* AZT_PRIVATE_IOCTLS */
 #ifdef SBP_PRIVATE_IOCTLS
 #include <linux/sbpcd.h>
 #include <linux/fs.h>
-#endif SBP_PRIVATE_IOCTLS
+#endif /* SBP_PRIVATE_IOCTLS */
 
 struct cdrom_tochdr hdr;
 struct cdrom_tochdr tocHdr;
@@ -591,7 +591,7 @@
 	struct cdrom_msf msf;
 	unsigned char buf[CD_FRAMESIZE_RAW];
 } azt;
-#endif AZT_PRIVATE_IOCTLS
+#endif /* AZT_PRIVATE_IOCTLS */
 int i, i1, i2, i3, j, k;
 unsigned char sequence=0;
 unsigned char command[80];
@@ -1053,7 +1053,7 @@
 			rc=ioctl(drive,CDROMAUDIOBUFSIZ,j);
 			printf("%d frames granted.\n",rc);
 			break;
-#endif SBP_PRIVATE_IOCTLS
+#endif /* SBP_PRIVATE_IOCTLS */
 		default:
 			printf("unknown command: \"%s\".\n",command);
 			break;
diff -u --recursive --new-file linux-2.0.39/Documentation/magic-number.txt linux-2.0.40/Documentation/magic-number.txt
--- linux-2.0.39/Documentation/magic-number.txt	Thu May 16 15:35:39 1996
+++ linux-2.0.40/Documentation/magic-number.txt	Mon Oct  8 14:06:30 2001
@@ -34,7 +34,12 @@
 					<mec@duracef.shout.net>
 					6 May 1996
 
+Added SKB-debugging values.  Note that they only appear under 
+CONFIG_SKB_CHECK, and are 12 bytes inside the structure.
 
+					Michael Deutschmann
+					<michael@talamasca.ocis.net>
+					2000-07-24
 
 Magic Name          Number      Structure            File
 ===========================================================================
@@ -60,4 +65,7 @@
 STL_PORTMAGIC       0x5a7182c9  stlport_t            include/linux/stallion.h
 PCXX_MAGIC          0x5c6df104  struct channel       drivers/char/pcxx.h
 BAYCOM_MAGIC        0x3105bac0  struct baycom_state  drivers/char/baycom.c
+SK_FREED_SKB        0x0de2code  struct sk_buff       include/linux/skbuff.h
+SK_GOOD_SKB         0xdec0ded1  struct sk_buff       include/linux/skbuff.h
+SK_HEAD_SKB         0x12231298  struct sk_buff_head  include/linux/skbuff.h
 
diff -u --recursive --new-file linux-2.0.39/MAINTAINERS linux-2.0.40/MAINTAINERS
--- linux-2.0.39/MAINTAINERS	Thu Sep  7 23:40:30 2000
+++ linux-2.0.40/MAINTAINERS	Mon Sep 10 16:45:10 2001
@@ -84,7 +84,7 @@
 
 8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.]
 P:	Paul Gortmaker
-M:	gpg109@rsphy1.anu.edu.au
+M:	p_gortmaker@yahoo.com
 L:	linux-net@vger.kernel.org
 S:	Maintained
 
@@ -97,20 +97,20 @@
 
 AHA152X SCSI DRIVER
 P:	Juergen E. Fischer
-M:	Juergen Fischer <fischer@et-inf.fho-emden.de>
+M:	Juergen Fischer <fischer@norbit.de>
 L:	linux-scsi@vger.kernel.org
 S:	Maintained
 
 APM DRIVER
 P:	Stephen Rothwell
-M:	apm@linuxcare.com.au
+M:	sfr@canb.auug.org.au
 L:	linux-laptop@vger.kernel.org
-W:	http://linuxcare.com.au/apm/
-S:	Maintained
+W:	http://www.canb.auug.org.au/~sfr/
+S:	Supported
 
 APPLETALK NETWORK LAYER
 P:	Jay Schulist
-M:	Jay.Schulist@spacs.k12.wi.us
+M:	jschlst@samba.org
 L:	linux-atalk@netspace.org
 S:	Maintained
 
@@ -120,14 +120,6 @@
 L:	linux-net@vger.kernel.org
 S:	Maintained
 
-AX.25 DAMA SLAVE
-P:	Joerg Reuter
-M:	jreuter@poboxes.com
-W:	http://poboxes.com/jreuter/
-W:	http://qsl.net/dl1bke/
-L:	linux-hams@vger.kernel.org
-S:	Maintained
-
 AX.25 NETWORK LAYER
 P:	Matthias Welwarsky
 M:	dg2fef@afthd.tu-darmstadt.de
@@ -148,7 +140,7 @@
 
 CYCLADES ASYNC MUX DRIVER
 P:	Ivan Passos
-M:	Ivan Passos <ivan@cyclades.com>
+M:	ivan@cyclades.com
 W:	http://www.cyclades.com/
 S:	Supported
 
@@ -158,6 +150,14 @@
 L:	linux-raid@vger.kernel.org
 S:	Maintained
 
+DAMA SLAVE for AX.25
+P:	Joerg Reuter
+M:	jreuter@yaina.de
+W:	http://yaina.de/jreuter/
+W:	http://qsl.net/dl1bke/
+L:	linux-hams@vger.kernel.org
+S:	Maintained
+
 DC390/AM53C974 SCSI driver
 P:	Kurt Garloff
 M:	kurt@garloff.de
@@ -176,19 +176,20 @@
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
-DIGIBOARD DRIVER
-P:	Christoph Lameter
-M:	clameter@fuller.edu
-L:	digiboard@list.fuller.edu
-S:	Maintained
-
 DIGI RIGHTSWITCH NETWORK DRIVER
 P:	Rick Richardson
-M:	rick@dgii.com
+M:	rick@remotepoint.com
 L:	linux-net@vger.kernel.org
 W:	http://www.dgii.com/linux/
 S:	Maintained
 
+DIGIBOARD DRIVER
+P:	Christoph Lameter
+M:	clameter@fuller.edu
+W:	http://www.dgii.com/linux,http://lameter.com/digi
+L:	digilnux@dgii.com
+S:	Maintained
+
 EATA-DMA SCSI DRIVER
 P:	Michael Neuffer
 M:	mike@i-Connect.Net
@@ -197,7 +198,7 @@
 
 EATA ISA/EISA/PCI SCSI DRIVER
 P:	Dario Ballabio
-M:	dario@milano.europe.dg.com
+M:	ballabio_dario@emc.com
 L:	linux-scsi@vger.kernel.org
 S:	Maintained
 
@@ -259,8 +260,11 @@
 IDE DRIVER [GENERAL]
 P:	Andre Hedrick
 M:	andre@linux-ide.org
+M:	andre@aslab.com
+M:	andre@suse.com
 L:	linux-kernel@vger.kernel.org
-W:	http://linux.kernel.org/pub/linux/kernel/people/hedrick/
+W:	http://www.kernel.org/pub/linux/kernel/people/hedrick/
+W:	http://www.linux-ide.org/
 S:	Supported
 
 IDE/ATAPI CDROM DRIVER 
@@ -297,7 +301,9 @@
 
 ISDN SUBSYSTEM HISAX
 P:	Karsten Keil
-M:	keil@isdn4linux.de
+M:	kkeil@suse.de
+P:	Kai Germaschewski
+M:	kai.germaschewski@gmx.de
 L:	isdn4linux@listserv.isdn4linux.de
 W:	http://www.isdn4linux.de
 S:	Maintained
@@ -314,6 +320,13 @@
 L:	linux-net@vger.kernel.org
 S:	Maintained
 
+MCA-SUPPORT
+P:	David Weinehall
+M:	tao@acc.umu.se
+W:	http://www.acc.umu.se/~tao/
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+
 MENUCONFIG
 P:	William Roadcap
 M:	roadcapw@titus.org
@@ -427,16 +440,13 @@
 L:	linux-video@atrey.karlin.mff.cuni.cz
 S:	Maintained
 
-THE V2.0 KERNEL IN GENERAL
-P:	David Weinehall
-M:	tao@acc.umu.se
-L:	linux-kernel@vger.kernel.org
-S:	Maintained
-
 TLAN NETWORK DRIVER
 P:	Torben Mathiasen
 M:	torben.mathiasen@compaq.com
+M:	torben@kernel.dk
 L:	tlan@vuser.vu.union.edu
+L:	linux-net@vger.kernel.org
+W:	http://tlan.kernel.dk
 S:	Maintained
 
 TOKEN-RING NETWORK DRIVER
@@ -448,13 +458,13 @@
 
 U14-34F SCSI DRIVER
 P:	Dario Ballabio
-M:	dario@milano.europe.dg.com
+M:	ballabio_dario@emc.com
 L:	linux-scsi@vger.kernel.org
 S:	Maintained
 
 VFAT FILESYSTEM
 P:	Gordon Chaffee
-M:	chaffee@plateau.cs.berkeley.edu
+M:	chaffee@cs.berkeley.edu
 L:	linux-kernel@vger.kernel.org
 W:	http://bmrc.berkeley.edu/people/chaffee
 S:	Maintained
@@ -473,12 +483,14 @@
 
 Z8530 SCC DRIVER FOR AX.25
 P:	Joerg Reuter
-M:	jreuter@poboxes.com
-W:	http://poboxes.com/jreuter/
-W:	http://qsl.net/dl1bke/
+M:	jreuter@yaina.de
+W:	http://yaina.de/jreuter/
+W:	http://www.qsl.net/dl1bke/
 L:	linux-hams@vger.kernel.org
 S:	Maintained
 
 THE REST
-P:	Linus Torvalds
-S:	Buried alive in email
+P:	David Weinehall
+M:	tao@acc.umu.se
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
diff -u --recursive --new-file linux-2.0.39/Makefile linux-2.0.40/Makefile
--- linux-2.0.39/Makefile	Wed Dec 15 12:22:10 1999
+++ linux-2.0.40/Makefile	Tue Oct  9 13:06:11 2001
@@ -1,6 +1,9 @@
 VERSION = 2
 PATCHLEVEL = 0
-SUBLEVEL = 39
+SUBLEVEL = 40
+EXTRAVERSION =-pre3
+
+KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
@@ -185,6 +188,9 @@
 symlinks:
 	rm -f include/asm
 	( cd include ; ln -sf asm-$(ARCH) asm)
+	@if [ ! -d include/linux/modules ]; then \
+		mkdir include/linux/modules; \
+	fi
 
 oldconfig: symlinks
 	$(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
@@ -236,8 +242,9 @@
 	@mv -f .ver $@
 
 include/linux/version.h: ./Makefile
-	@echo \#define UTS_RELEASE \"$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)\" > .ver
+	@echo \#define UTS_RELEASE \"$(KERNELRELEASE)\" > .ver
 	@echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)` >> .ver
+	@echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))' >>.ver
 	@mv -f .ver $@
 
 init/version.o: init/version.c include/linux/compile.h
@@ -267,6 +274,18 @@
 net: dummy
 	$(MAKE) linuxsubdirs SUBDIRS=net
 
+TAGS: dummy
+	etags `find include/asm-$(ARCH) -name '*.h'`
+	find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs etags -a
+	find $(SUBDIRS) init -name '*.c' | xargs etags -a
+
+# Exuberant ctags works better with -I
+tags: dummy
+	CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \
+	ctags $$CTAGSF `find include/asm-$(ARCH) -name '*.h'` && \
+	find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs ctags $$CTAGSF -a && \
+	find $(SUBDIRS) init -name '*.c' | xargs ctags $$CTAGSF -a
+
 MODFLAGS = -DMODULE
 ifdef CONFIG_MODULES
 ifdef CONFIG_MODVERSIONS
@@ -281,7 +300,7 @@
 
 modules_install:
 	@( \
-	MODLIB=/lib/modules/$(VERSION).$(PATCHLEVEL).$(SUBLEVEL); \
+	MODLIB=/lib/modules/$(KERNELRELEASE); \
 	cd modules; \
 	MODULES=""; \
 	inst_mod() { These="`cat $$1`"; MODULES="$$MODULES $$These"; \
@@ -345,7 +364,7 @@
 distclean: mrproper
 	rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
                 -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
-                -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS
+                -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS tags
 
 backup: mrproper
 	cd .. && tar cf - linux/ | gzip -9 > backup.gz
@@ -377,7 +396,13 @@
 depend dep: dep-files $(MODVERFILE)
 
 checkconfig:
-	perl -w scripts/checkconfig.pl `find * -name '*.[hcS]' -print | sort`
+	find * -name '*.[hcS]' -type f -print | sort | xargs $(PERL) -w scripts/checkconfig.pl
+
+checkhelp:
+	find * -name [cC]onfig.in -print | sort | xargs $(PERL) -w scripts/checkhelp.pl
+
+checkincludes:
+	find * -name '*.[hcS]' -type f -print | sort | xargs $(PERL) -w scripts/checkincludes.pl
 
 ifdef CONFIGURATION
 ..$(CONFIGURATION):
diff -u --recursive --new-file linux-2.0.39/arch/alpha/config.in linux-2.0.40/arch/alpha/config.in
--- linux-2.0.39/arch/alpha/config.in	Thu Dec 30 00:08:26 1999
+++ linux-2.0.40/arch/alpha/config.in	Mon Oct  8 14:06:30 2001
@@ -227,6 +227,11 @@
 if [ "$CONFIG_PROFILE" = "y" ]; then
    int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
+bool 'Memory flooding' CONFIG_SADISTIC_KMALLOC
+bool 'Socket-buffer consistency checking' CONFIG_SKB_CHECK
+if [ "$CONFIG_SKB_CHECK" = "y" ]; then
+   bool '  Whole-queue checking' CONFIG_SKB_CHECK_WHOLE_QUEUE
+fi
 endmenu
 
 if [ "$CONFIG_TGA_CONSOLE" = "n" ]; then
diff -u --recursive --new-file linux-2.0.39/arch/i386/config.in linux-2.0.40/arch/i386/config.in
--- linux-2.0.39/arch/i386/config.in	Wed Dec 29 13:54:15 1999
+++ linux-2.0.40/arch/i386/config.in	Mon Oct  8 14:06:30 2001
@@ -141,4 +141,9 @@
 if [ "$CONFIG_PROFILE" = "y" ]; then
    int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
+bool 'Memory flooding' CONFIG_SADISTIC_KMALLOC
+bool 'Socket-buffer consistency checking' CONFIG_SKB_CHECK
+if [ "$CONFIG_SKB_CHECK" = "y" ]; then
+   bool '  Whole-queue checking' CONFIG_SKB_CHECK_WHOLE_QUEUE
+fi
 endmenu
diff -u --recursive --new-file linux-2.0.39/arch/i386/kernel/head.S linux-2.0.40/arch/i386/kernel/head.S
--- linux-2.0.39/arch/i386/kernel/head.S	Thu Aug 26 00:08:27 1999
+++ linux-2.0.40/arch/i386/kernel/head.S	Mon Sep 10 15:36:02 2001
@@ -51,7 +51,7 @@
 	jmp checkCPUtype
 1:
 	lss stack_start,%esp
-#endif __SMP__
+#endif /* __SMP__ */
 /*
  * Clear BSS first so that there are no surprises...
  */
diff -u --recursive --new-file linux-2.0.39/arch/i386/kernel/process.c linux-2.0.40/arch/i386/kernel/process.c
--- linux-2.0.39/arch/i386/kernel/process.c	Sun Jun 13 19:21:00 1999
+++ linux-2.0.40/arch/i386/kernel/process.c	Mon Oct  8 23:54:42 2001
@@ -520,35 +520,8 @@
 		/* We dump the emulator state here.
 		   We convert it into standard 387 format first.. */
 #ifdef CONFIG_MATH_EMULATION
-		int i;
-		unsigned long top;
-		char (*hardreg)[10];
-		struct i387_soft_struct *soft_fpu = &current->tss.i387.soft;
-		struct fpu_reg* softreg;
-		long int control_word = soft_fpu->cwd;
-
-		fpu->cwd = soft_fpu->cwd;
-		fpu->swd = soft_fpu->swd;
-		fpu->twd = soft_fpu->twd;
-		fpu->fip = soft_fpu->fip;
-		fpu->fcs = soft_fpu->fcs;
-		fpu->foo = soft_fpu->foo;
-		fpu->fos = soft_fpu->fos;
-		hardreg = (char (*)[10]) &fpu->st_space[0];
-		top = (unsigned long) soft_fpu->top % 8;
-		softreg = &soft_fpu->regs[top];
-		for (i = top ; i < 8; i ++) {
-			softreg_to_hardreg(softreg, *hardreg, control_word);
-			hardreg++;
-			softreg++;
-		}
-		softreg = &soft_fpu->regs[0];
-		for (i = 0; i < top; i++) {
-			softreg_to_hardreg(softreg, *hardreg, control_word);
-			hardreg++;
-			softreg++;
-		}
-		fpvalid = 1;   
+		fpvalid = save_i387_soft(&current->tss.i387.soft,
+					 (struct _fpstate *)fpu);
 #else /* defined(CONFIG_MATH_EMULATION) */
 		fpvalid = 0;
 #endif /* !defined(CONFIG_MATH_EMULATION) */
diff -u --recursive --new-file linux-2.0.39/arch/i386/kernel/ptrace.c linux-2.0.40/arch/i386/kernel/ptrace.c
--- linux-2.0.39/arch/i386/kernel/ptrace.c	Mon Jul 13 22:47:27 1998
+++ linux-2.0.40/arch/i386/kernel/ptrace.c	Mon Oct  8 23:54:42 2001
@@ -295,67 +295,11 @@
 		put_long(tsk, vma, addr, data);
 	return 0;
 }
-#ifdef CONFIG_MATH_EMULATION
-static void write_emulator_word(struct task_struct *child,
-				unsigned long register_offset,
-				long data)
-{
-	int i, j;
-	struct i387_soft_struct *soft_fpu;
-	struct fpu_reg *this_fpreg, *next_fpreg;
-	char hard_reg[2][10];
-	int control_word;
-	unsigned long top;
-	i = register_offset / 10;
-	j = register_offset % 10;
-	soft_fpu = &child->tss.i387.soft;
-	top = i + (unsigned long) soft_fpu->top;
-	control_word = soft_fpu->cwd;
-	this_fpreg = &soft_fpu->regs[(top + i) % 8];
-	next_fpreg = &soft_fpu->regs[(top + i + 1) % 8];
-	softreg_to_hardreg(this_fpreg, hard_reg[0], control_word);
-	if (j > 6)
-		softreg_to_hardreg(next_fpreg, hard_reg[1], control_word);
-	*(long *) &hard_reg[0][j] = data;
-	hardreg_to_softreg(hard_reg[0], this_fpreg);
-	if (j > 6)
-		hardreg_to_softreg(hard_reg[1], next_fpreg);
-}
-#endif /* defined(CONFIG_MATH_EMULATION) */
 
 /*
  * Floating point support added to ptrace by Ramon Garcia,
  * ramon@juguete.quim.ucm.es
  */
-
-#ifdef CONFIG_MATH_EMULATION
-
-static unsigned long get_emulator_word(struct task_struct *child,
-				       unsigned long register_offset)
-{
-	char hard_reg[2][10];
-	int i, j;
-	struct fpu_reg *this_fpreg, *next_fpreg;
-	struct i387_soft_struct *soft_fpu;
-	long int control_word;
-	unsigned long top;
-	unsigned long tmp;
-	i = register_offset / 10;
-	j = register_offset % 10;
-	soft_fpu = &child->tss.i387.soft;
-	top = (unsigned long) soft_fpu->top;
-	this_fpreg = &soft_fpu->regs[(top + i) % 8];
-	next_fpreg = &soft_fpu->regs[(top + i + 1) % 8];
-	control_word = soft_fpu->cwd;
-	softreg_to_hardreg(this_fpreg, hard_reg[0], control_word);
-	if (j > 6)
-		softreg_to_hardreg(next_fpreg, hard_reg[1], control_word);
-	tmp = *(long *)
-		&hard_reg[0][j];
-	return tmp;
-}
-
-#endif /* defined(CONFIG_MATH_EMULATION) */
 
 static int putreg(struct task_struct *child,
 	unsigned long regno, unsigned long value)
diff -u --recursive --new-file linux-2.0.39/arch/i386/kernel/setup.c linux-2.0.40/arch/i386/kernel/setup.c
--- linux-2.0.39/arch/i386/kernel/setup.c	Sun Jun 13 19:21:00 1999
+++ linux-2.0.40/arch/i386/kernel/setup.c	Wed Sep 12 15:03:39 2001
@@ -57,10 +57,10 @@
 static const char *x86_clkmult[] = {
 	"unknown", "1", "1.5", "2", "2.5", "3", "3.5", "4", "4.5", "5", "5.5",
 	"6", "6.5", "7", "7.5", "8"
-	};
+};
 
 char ignore_irq13 = 0;		/* set if exception 16 works */
-char wp_works_ok = -1;		/* set if paging hardware honours WP */ 
+char wp_works_ok = -1;		/* set if paging hardware honours WP */
 char hlt_works_ok = 1;		/* set if the "hlt" instruction works */
 
 /*
@@ -112,9 +112,9 @@
 #define COMMAND_LINE ((char *) (PARAM+2048))
 #define COMMAND_LINE_SIZE 256
 
-#define RAMDISK_IMAGE_START_MASK  	0x07FF
+#define RAMDISK_IMAGE_START_MASK	0x07FF
 #define RAMDISK_PROMPT_FLAG		0x8000
-#define RAMDISK_LOAD_FLAG		0x4000	
+#define RAMDISK_LOAD_FLAG		0x4000
 
 static char command_line[COMMAND_LINE_SIZE] = { 0, };
        char saved_command_line[COMMAND_LINE_SIZE];
@@ -136,9 +136,9 @@
 	}
 	smptrap=1;
 
- 	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
- 	drive_info = DRIVE_INFO;
- 	screen_info = SCREEN_INFO;
+	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
+	drive_info = DRIVE_INFO;
+	screen_info = SCREEN_INFO;
 #ifdef CONFIG_APM
 	apm_bios_info = APM_BIOS_INFO;
 #endif
@@ -167,14 +167,14 @@
 	/*
 	 *	The CONFIG_MAX_MEMSIZE sanity checker.
 	 */
-	 
+
 	if (memory_end > (CONFIG_MAX_MEMSIZE-128)*1024*1024)
 	{
 		memory_end = (CONFIG_MAX_MEMSIZE-128)*1024*1024;
 		printk(KERN_WARNING "ONLY %dMB RAM will be used, see Documentation/more-than-900MB-RAM.txt!.\n", CONFIG_MAX_MEMSIZE-128);
 		udelay(3*1000*1000);
 	}
-	
+
 	if (!MOUNT_ROOT_RDONLY)
 		root_mountflags &= ~MS_RDONLY;
 	memory_start = (unsigned long) &_end;
@@ -263,12 +263,12 @@
     unsigned char nr6x86 = 0;
     unsigned char cx_dir0 = 0;	/* Model and bus clock multiplier */
     unsigned char cx_dir1 = 0;	/* Stepping info */
-    unsigned int flags;
+    unsigned long flags;
     static const char *model[] = {
 	"unknown", "Cx486", "5x86", "MediaGX", "6x86", "6x86L", "6x86MX",
 	"M II"
     };
-    
+
     if (x86_model == -1) {	/* is this an old Cx486 without DIR0/DIR1? */
 	nr6x86 = 1;		/* Cx486 */
 	Cx86_mult = 0;		/* unknown multiplier */
@@ -276,65 +276,65 @@
     else {
 
 	/* Get DIR0, DIR1 since all other Cyrix CPUs have them */
-    
+
 	save_flags(flags);
 	cli();
 	cx_dir0 = getCx86(CX86_DIR0);	/* we use the access macros */
 	cx_dir1 = getCx86(CX86_DIR1);	/* defined in processor.h */
 	restore_flags(flags);
-	                                
+
 	/* Now cook; the recipe is by Channing Corn, from Cyrix.
 	 * We do the same thing for each generation: we work out
 	 * the model, multiplier and stepping.
 	 */
-	 
+
 	if (cx_dir0 < 0x20) {
 		nr6x86 = 1;				/* Cx486 */
 		Cx86_mult = 0;				/* unknown multiplier */
 		sprintf(Cx86_step, "%d.%d", (cx_dir1 >> 4) + 1, cx_dir1 & 0x0f);
 	}
-        
+
         if ((cx_dir0 > 0x20) && (cx_dir0 < 0x30)) {
 		nr6x86 = 2;				/* 5x86 */
 		Cx86_mult = ((cx_dir0 & 0x04) ? 5 : 3);	/* either 3x or 2x */
 		sprintf(Cx86_step, "%d.%d", (cx_dir1 >> 4) + 1, cx_dir1 & 0x0f);
 	}
-        
+
         if ((cx_dir0 >= 0x30) && (cx_dir0 < 0x38)) {
 		nr6x86 = ((x86_capability & (1 << 8)) ? 5 : 4);	/* 6x86(L) */
 		Cx86_mult = ((cx_dir0 & 0x04) ? 5 : 3);	/* either 3x or 2x */
 		sprintf(Cx86_step, "%d.%d", (cx_dir1 >> 3), cx_dir1 & 0x0f);
 	}
-        
+
         if ((cx_dir0 >= 0x40) && (cx_dir0 < 0x50)) {
 	    if (x86 == 4) { /* MediaGX */
 		nr6x86 = 3;
 		Cx86_mult = ((cx_dir0 & 0x01) ? 5 : 7);	/* either 3x or 4x */
-        	switch (cx_dir1 >> 4) {
-            		case (0) :
-            		case (1) :
-            			sprintf(Cx86_step, "2.%d", cx_dir1 & 0x0f);
-			break;
-            		case (2) :
-            			sprintf(Cx86_step, "1.%d", cx_dir1 & 0x0f);
-			break;
+		switch (cx_dir1 >> 4) {
+			case (0) :
+			case (1) :
+				sprintf(Cx86_step, "2.%d", cx_dir1 & 0x0f);
+				break;
+			case (2) :
+				sprintf(Cx86_step, "1.%d", cx_dir1 & 0x0f);
+				break;
                         default  :
-			break;
+				break;
                 }
             } /* endif MediaGX */
-            if (x86 == 5) { /* GXm */
-                char GXm_mult[8] = {7,11,7,11,13,15,13,9}; /* 4 to 8 */
-            	ext_cpuid = 0x80000005;	/* available */
-            	Cx86_mult = GXm_mult[cx_dir0 & 0x0f];
-            	sprintf(Cx86_step, "%d.%d", (cx_dir1 >> 4) - 1, cx_dir1 & 0x0f);
-            } /* endif GXm */
+	    if (x86 == 5) { /* GXm */
+		    char GXm_mult[8] = {7,11,7,11,13,15,13,9}; /* 4 to 8 */
+		    ext_cpuid = 0x80000005;	/* available */
+		    Cx86_mult = GXm_mult[cx_dir0 & 0x0f];
+		    sprintf(Cx86_step, "%d.%d", (cx_dir1 >> 4) - 1, cx_dir1 & 0x0f);
+	    } /* endif GXm */
         }
-        
+
         if ((cx_dir0 >= 0x50) && (cx_dir0 < 0x60)) {
 		nr6x86 = ((cx_dir1 > 7) ? 7 : 6);	/* 6x86Mx or M II */
 		Cx86_mult = (cx_dir0 & 0x07) + 2;	/* 2 to 5 in 0.5 steps */
-        	if (((cx_dir1 & 0x0f) > 4) || ((cx_dir1 >> 4) == 2)) cx_dir1 += 0x10;
-        	sprintf(Cx86_step, "%d.%d", (cx_dir1 >> 4) + 1, cx_dir1 & 0x0f);
+		if (((cx_dir1 & 0x0f) > 4) || ((cx_dir1 >> 4) == 2)) cx_dir1 += 0x10;
+		sprintf(Cx86_step, "%d.%d", (cx_dir1 >> 4) + 1, cx_dir1 & 0x0f);
 	}
     }
     x86_mask = 1;	/* we don't use it, but has to be set to something */
@@ -358,7 +358,7 @@
 {
 	const char *p=NULL;
 	int i;
-	
+
 	if ((x86_model == 0) || (x86 == 4)) {
 		for (i=0; i<sizeof(amd_models)/sizeof(struct cpu_model_info); i++)
 			if (amd_models[i].cpu_x86 == x86) {
@@ -390,31 +390,30 @@
 {
 	const char *p = "386 SX/DX";	/* default to a 386 */
 	int i;
-	
+
 	/*
 	 *	Old 486SX has no CPU ID. Set the model to 2 for this
 	 *	case.
 	 */
-	 
+
 	if( x86==4 && x86_model == 0 && hard_math == 0)
 		x86_model = 2;
-	
+
 	for (i=0; i<sizeof(intel_models)/sizeof(struct cpu_model_info); i++)
 		if (intel_models[i].cpu_x86 == x86) {
 			p = intel_models[i].model_names[(int)x86_model];
 			break;
 		}
-	
-	
+
 	return p;
 }
-	
+
 /* Recent Intel CPUs have an EEPROM and a ROM with CPU information. We'll use
  * this information in future versions of this code.
  * AMD and more recently Cyrix have decided to standardize on an extended
  * cpuid mechanism for their CPUs.
  */
- 
+
 static const char * get_cpu_mkt_name(void)
 {
         static char mktbuf[48];
@@ -439,7 +438,7 @@
 	else if (strcmp(x86_vendor_id, "CentaurHauls") == 0)	/* CentaurHauls */
 		p = IDTmodel();
 	/* This isnt quite right */
-	else if (strcmp(x86_vendor_id, "UMC UMC UMC ") == 0) 	/* UMC */
+	else if (strcmp(x86_vendor_id, "UMC UMC UMC ") == 0)	/* UMC */
 		p = Intelmodel();
 	else /* default - this could be anyone */
 		p = Intelmodel();
@@ -464,7 +463,7 @@
 		"fpcmov", "17", "psn",    "19",  "20",  "21", "22",   "mmx",
 		  "emmx", "25", "26",    "27",  "28",  "29", "30", "3dnow"
 	};
-         
+
 #ifdef __SMP__
         int n;
 
@@ -475,7 +474,7 @@
 
         for ( n = 0 ; n < 32 ; n++ ) {
                 if ( cpu_present_map & (1<<n) ) {
-                        if (len) buffer[len++] = '\n'; 
+                        if (len) buffer[len++] = '\n';
 
 #else
 #define CD(X) (X)
@@ -491,28 +490,28 @@
 			len += sprintf(buffer+len,
                                        "\nvendor_id\t: %s\n",
                                        x86_vendor_id);
-        
+
                         if (CD(x86_mask) || have_cpuid)
-                                if      ((strncmp(x86_vendor_id, "Au", 2) == 0)
-                                	&& (x86_model >= 6)) {
-                                	len += sprintf(buffer+len,
-                                        	       "stepping\t: %c\n",
-                                             	       x86_mask + 'A');
+                                if ((strncmp(x86_vendor_id, "Au", 2) == 0)
+					&& (x86_model >= 6)) {
+					len += sprintf(buffer+len,
+							"stepping\t: %c\n",
+							x86_mask + 'A');
                                 }
                                 else if (strncmp(x86_vendor_id, "Cy", 2) == 0) {
-                                	len += sprintf(buffer+len,
+					len += sprintf(buffer+len,
 							"stepping\t: %s, core/bus clock ratio: %sx\n",
-                              				Cx86_step, x86_clkmult[Cx86_mult]);
+							Cx86_step, x86_clkmult[Cx86_mult]);
                                 }
-                                else { 	
-                                	len += sprintf(buffer+len,
-                                        	       "stepping\t: %d\n",
-                                             	       CD(x86_mask));
+                                else {
+					len += sprintf(buffer+len,
+						       "stepping\t: %d\n",
+						       CD(x86_mask));
                                 }
                         else
-                                len += sprintf(buffer+len, 
+                                len += sprintf(buffer+len,
                                                "stepping\t: unknown\n");
-        
+
                         len += sprintf(buffer+len,
                                        "fdiv_bug\t: %s\n"
                                        "hlt_bug\t\t: %s\n"
@@ -530,7 +529,7 @@
                                          ? "yes" : "no",
                                        CD(have_cpuid) ? "yes" : "no",
                                        CD(wp_works_ok) ? "yes" : "no");
-        
+
                         for ( i = 0 ; i < 32 ; i++ ) {
                                 if ( CD(x86_capability) & (1 << i) ) {
                                         len += sprintf(buffer+len, " %s",
diff -u --recursive --new-file linux-2.0.39/arch/i386/kernel/signal.c linux-2.0.40/arch/i386/kernel/signal.c
--- linux-2.0.39/arch/i386/kernel/signal.c	Mon Aug  4 21:12:51 1997
+++ linux-2.0.40/arch/i386/kernel/signal.c	Mon Oct  8 23:54:42 2001
@@ -69,7 +69,7 @@
 		restore_i387_hard(buf);
 		return;
 	}
-	restore_i387_soft(buf);
+	restore_i387_soft(&current->tss.i387.soft, buf);
 #endif	
 }
 	
@@ -152,7 +152,8 @@
 #else
 	if (hard_math)
 		return save_i387_hard(buf);
-	return save_i387_soft(buf);
+	save_i387_soft(&current->tss.i387.soft, buf);
+	return buf;
 #endif
 }
 
diff -u --recursive --new-file linux-2.0.39/arch/i386/kernel/traps.c linux-2.0.40/arch/i386/kernel/traps.c
--- linux-2.0.39/arch/i386/kernel/traps.c	Sun Nov 15 19:32:46 1998
+++ linux-2.0.40/arch/i386/kernel/traps.c	Sun Sep 23 14:41:30 2001
@@ -61,19 +61,23 @@
 
 #define get_seg_byte(seg,addr) ({ \
 register unsigned char __res; \
-__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \
-	:"=a" (__res):"0" (seg),"m" (*(addr))); \
+__asm__("push %%fs; mov %%ax, %%fs; movb %%fs:%2, %%al; pop %%fs" \
+	: "=a" (__res) \
+	: "0" (seg), "m" (*(addr))); \
 __res;})
 
 #define get_seg_long(seg,addr) ({ \
 register unsigned long __res; \
-__asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \
-	:"=a" (__res):"0" (seg),"m" (*(addr))); \
+__asm__("push %%fs; mov %%ax, %%fs; movl %%fs:%2, %%eax; pop %%fs" \
+	: "=a" (__res) \
+	: "0" (seg), "m" (*(addr))); \
 __res;})
 
 #define _fs() ({ \
 register unsigned short __res; \
-__asm__("mov %%fs,%%ax":"=a" (__res):); \
+__asm__("mov %%fs, %%ax" \
+	: "=a" (__res) \
+	:); \
 __res;})
 
 void page_exception(void);
@@ -203,7 +207,7 @@
 		return;
 	}
 
-	/* 
+	/*
 	 * HACK HACK HACK  :)  Fixing the segment invalid on syscall return
 	 * barfage for 2.0 has been put into the too-hard basket but having
 	 * a user producing endless GPFs is unacceptable as well. - Paul G.
@@ -219,25 +223,25 @@
 			}
 			do_exit(SIGSEGV);
 		}
-		else 
+		else
 			die_if_kernel("general protection",regs,error_code);
 	}
 	current->tss.error_code = error_code;
 	current->tss.trap_no = 13;
-	force_sig(SIGSEGV, current);	
+	force_sig(SIGSEGV, current);
 }
 
 asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
 {
 #ifdef CONFIG_SMP_NMI_INVAL
 	smp_flush_tlb_rcv();
-#else
+#else /* CONFIG_SMP_NMI_INVAL */
 #ifndef CONFIG_IGNORE_NMI
 	printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
 	printk("You probably have a hardware problem with your RAM chips or a\n");
 	printk("power saving mode enabled.\n");
-#endif	
-#endif
+#endif /* !CONFIG_IGNORE_NMI */
+#endif /* !CONFIG_SMP_NMI_INVAL */
 }
 
 asmlinkage void do_debug(struct pt_regs * regs, long error_code)
@@ -251,7 +255,7 @@
 	current->tss.error_code = error_code;
 	if ((regs->cs & 3) == 0) {
 		/* If this is a kernel mode trap, then reset db7 and allow us to continue */
-		__asm__("movl %0,%%db7"
+		__asm__("movl %0, %%db7"
 			: /* no output */
 			: "r" (0));
 		return;
@@ -282,7 +286,8 @@
 	/*
 	 *	Save the info for the exception handler
 	 */
-	__asm__ __volatile__("fnsave %0":"=m" (task->tss.i387.hard));
+	__asm__ __volatile__("fnsave %0"
+		: "=m" (task->tss.i387.hard));
 	task->flags&=~PF_USEDFPU;
 	stts();
 
@@ -329,16 +334,18 @@
 	if (last_task_used_math == current)
 		return;
 	if (last_task_used_math)
-		__asm__("fnsave %0":"=m" (last_task_used_math->tss.i387));
+		__asm__("fnsave %0"
+			: "=m" (last_task_used_math->tss.i387));
 	else
 		__asm__("fnclex");
 	last_task_used_math = current;
 #endif
 
 	if(current->used_math)
-		__asm__("frstor %0": :"m" (current->tss.i387));
-	else
-	{
+		__asm__("frstor %0"
+			:
+			: "m" (current->tss.i387));
+	else {
 		/*
 		 *	Our first FPU usage, clean the chip.
 		 */
@@ -398,7 +405,8 @@
 	flush_tlb_all();
 
 		/* now we have the mapping ok, we can do LIDT */
-	 __asm__ __volatile__("\tlidt %0": "=m" (idt_descriptor));
+	 __asm__ __volatile__("\tlidt %0"
+		: "=m" (idt_descriptor));
 
 	printk(" ... done\n");
 }
@@ -409,10 +417,9 @@
 	int i;
 	struct desc_struct * p;
 	static int smptrap=0;
-	
-	if(smptrap)
-	{
-		__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
+
+	if(smptrap) {
+		__asm__("pushfl; andl $0xffffbfff, (%esp); popfl");
 		load_ldt(0);
 		return;
 	}
@@ -454,7 +461,7 @@
 		p++;
 	}
 /* Clear NT, so that we won't have troubles with that later on */
-	__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
+	__asm__("pushfl; andl $0xffffbfff, (%esp); popfl");
 	load_TR(0);
 	load_ldt(0);
 }
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/Makefile linux-2.0.40/arch/i386/math-emu/Makefile
--- linux-2.0.39/arch/i386/math-emu/Makefile	Fri Nov  7 18:11:42 1997
+++ linux-2.0.40/arch/i386/math-emu/Makefile	Mon Oct  8 23:54:42 2001
@@ -13,17 +13,17 @@
 	$(CC) -D__ASSEMBLY__ $(PARANOID) -c $<
 
 L_OBJS =fpu_entry.o div_small.o errors.o \
-	fpu_arith.o fpu_aux.o fpu_etc.o fpu_trig.o \
+	fpu_arith.o fpu_aux.o fpu_etc.o fpu_tags.o fpu_trig.o \
 	load_store.o get_address.o \
 	poly_atan.o poly_l2.o poly_2xm1.o poly_sin.o poly_tan.o \
-	reg_add_sub.o reg_compare.o reg_constant.o reg_ld_str.o \
-	reg_div.o reg_mul.o reg_norm.o \
+	reg_add_sub.o reg_compare.o reg_constant.o reg_convert.o \
+	reg_ld_str.o \
+	reg_divide.o reg_mul.o reg_norm.o \
 	reg_u_add.o reg_u_div.o reg_u_mul.o reg_u_sub.o \
 	reg_round.o \
 	wm_shrx.o wm_sqrt.o \
 	div_Xsig.o polynom_Xsig.o round_Xsig.o \
-	shr_Xsig.o mul_Xsig.o \
-	fpu_debug.o
+	shr_Xsig.o mul_Xsig.o
 
 include $(TOPDIR)/Rules.make
 
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/README linux-2.0.40/arch/i386/math-emu/README
--- linux-2.0.39/arch/i386/math-emu/README	Tue Oct 29 14:17:25 1996
+++ linux-2.0.40/arch/i386/math-emu/README	Mon Oct  8 23:54:42 2001
@@ -1,9 +1,9 @@
  +---------------------------------------------------------------------------+
  |  wm-FPU-emu   an FPU emulator for 80386 and 80486SX microprocessors.      |
  |                                                                           |
- | Copyright (C) 1992,1993,1994,1995,1996                                    |
+ | Copyright (C) 1992,1993,1994,1995,1996,1997,1999,2001                     |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail billm@suburbia.net               |
+ |                       Australia.  E-mail billm@melbpc.org.au              |
  |                                                                           |
  |    This program is free software; you can redistribute it and/or modify   |
  |    it under the terms of the GNU General Public License version 2 as      |
@@ -42,11 +42,14 @@
 some differences.
 
 Please report bugs, etc to me at:
-       billm@suburbia.net
+       billm@melbpc.org.au
+
+For more information on the emulator and on floating point topics, see
+my web pages, currently at  http://floatingpoint.sourceforge.net/
 
 
 --Bill Metzenthen
-  October 1996
+  August 2001
 
 
 ----------------------- Internals of wm-FPU-emu -----------------------
@@ -95,8 +98,9 @@
 ----------------------- Limitations of wm-FPU-emu -----------------------
 
 There are a number of differences between the current wm-FPU-emu
-(version 1.20) and the 80486 FPU (apart from bugs). Some of the more
-important differences are listed below:
+(version 2.01) and the 80486 FPU (apart from bugs).  The differences
+are fewer than those which applied to the 1.xx series of the emulator.
+Some of the more important differences are listed below:
 
 The Roundup flag does not have much meaning for the transcendental
 functions and its 80486 value with these functions is likely to differ
@@ -122,24 +126,12 @@
 emulator. Do not use them. The emulator treats them differently in
 detail from the way an 80486 does.
 
-The emulator treats PseudoDenormals differently from an 80486. These
-numbers are in fact properly normalised numbers with the exponent
-offset by 1, and the emulator treats them as such. Unlike the 80486,
-the emulator does not generate a Denormal Operand exception for these
-numbers. The arithmetical results produced when using such a number as
-an operand are the same for the emulator and a real 80486 (apart from
-any slight precision difference for the transcendental functions).
-Neither the emulator nor an 80486 produces one of these numbers as the
-result of any arithmetic operation. An 80486 can keep one of these
-numbers in an FPU register with its identity as a PseudoDenormal, but
-the emulator will not; they are always converted to a valid number.
-
 Self modifying code can cause the emulator to fail. An example of such
 code is:
           movl %esp,[%ebx]
 	  fld1
 The FPU instruction may be (usually will be) loaded into the pre-fetch
-queue of the cpu before the mov instruction is executed. If the
+queue of the CPU before the mov instruction is executed. If the
 destination of the 'movl' overlaps the FPU instruction then the bytes
 in the prefetch queue and memory will be inconsistent when the FPU
 instruction is executed. The emulator will be invoked but will not be
@@ -171,7 +163,7 @@
 The speed of floating point computation with the emulator will depend
 upon instruction mix. Relative performance is best for the instructions
 which require most computation. The simple instructions are adversely
-affected by the fpu instruction trap overhead.
+affected by the FPU instruction trap overhead.
 
 
 Timing: Some simple timing tests have been made on the emulator functions.
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/control_w.h linux-2.0.40/arch/i386/math-emu/control_w.h
--- linux-2.0.39/arch/i386/math-emu/control_w.h	Thu Jun 29 17:25:27 1995
+++ linux-2.0.40/arch/i386/math-emu/control_w.h	Thu Aug 23 18:56:18 2001
@@ -42,4 +42,4 @@
 /* FULL_PRECISION simulates all exceptions masked */
 #define FULL_PRECISION  (PR_64_BITS | RC_RND | 0x3f)
 
-#endif _CONTROLW_H_
+#endif /* _CONTROLW_H_ */
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/div_Xsig.S linux-2.0.40/arch/i386/math-emu/div_Xsig.S
--- linux-2.0.39/arch/i386/math-emu/div_Xsig.S	Thu Oct  5 14:30:43 1995
+++ linux-2.0.40/arch/i386/math-emu/div_Xsig.S	Mon Oct  8 23:54:42 2001
@@ -55,7 +55,7 @@
 	Local storage in a static area:
 	Accumulator:	FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0
  */
-	.align 2,0
+	.align 4,0
 FPU_accum_3:
 	.long	0
 FPU_accum_2:
@@ -70,7 +70,7 @@
 	.long	0
 FPU_result_1:
 	.long	0
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */
 
 
 .text
@@ -79,7 +79,7 @@
 	movl	%esp,%ebp
 #ifndef NON_REENTRANT_FPU
 	subl	$28,%esp
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */ 
 
 	pushl	%esi
 	pushl	%edi
@@ -91,7 +91,7 @@
 #ifdef PARANOID
 	testl	$0x80000000, XsigH(%ebx)	/* Divisor */
 	je	L_bugged
-#endif PARANOID
+#endif /* PARANOID */
 
 
 /*---------------------------------------------------------------------------+
@@ -164,7 +164,7 @@
 
 #ifdef PARANOID
 	jb	L_bugged_1
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	/* need to subtract another once of the denom */
 	incl	FPU_result_3	/* Correct the answer */
@@ -177,7 +177,7 @@
 #ifdef PARANOID
 	sbbl	$0,FPU_accum_3
 	jne	L_bugged_1	/* Must check for non-zero result here */
-#endif PARANOID
+#endif /* PARANOID */ 
 
 /*----------------------------------------------------------------------*/
 /* Half of the main problem is done, there is just a reduced numerator
@@ -207,7 +207,7 @@
 
 #ifdef PARANOID
 	je	L_bugged_2	/* Can't bump the result to 1.0 */
-#endif PARANOID
+#endif /* PARANOID */ 
 
 LDo_2nd_div:
 	cmpl	$0,%ecx		/* augmented denom msw */
@@ -230,7 +230,7 @@
 
 #ifdef PARANOID
 	jc	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */
 
 	movl	FPU_result_2,%eax	/* Get the result back */
 	mull	XsigL(%ebx)	/* now mul the ls dw of the denom */
@@ -241,14 +241,14 @@
 
 #ifdef PARANOID
 	jc	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */
 
 	jz	LDo_3rd_32_bits
 
 #ifdef PARANOID
 	cmpl	$1,FPU_accum_2
 	jne	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	/* need to subtract another once of the denom */
 	movl	XsigL(%ebx),%eax
@@ -260,14 +260,14 @@
 #ifdef PARANOID
 	jc	L_bugged_2
 	jne	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	addl	$1,FPU_result_2	/* Correct the answer */
 	adcl	$0,FPU_result_3
 
 #ifdef PARANOID
 	jc	L_bugged_2	/* Must check for non-zero result here */
-#endif PARANOID
+#endif /* PARANOID */ 
 
 /*----------------------------------------------------------------------*/
 /* The division is essentially finished here, we just need to perform
@@ -362,4 +362,4 @@
 	call	EXCEPTION
 	pop	%ebx
 	jmp	L_exit
-#endif PARANOID
+#endif /* PARANOID */ 
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/div_small.S linux-2.0.40/arch/i386/math-emu/div_small.S
--- linux-2.0.39/arch/i386/math-emu/div_small.S	Thu Oct  5 14:30:43 1995
+++ linux-2.0.40/arch/i386/math-emu/div_small.S	Mon Oct  8 23:54:42 2001
@@ -12,13 +12,13 @@
  +---------------------------------------------------------------------------*/
 
 /*---------------------------------------------------------------------------+
- |    unsigned long div_small(unsigned long long *x, unsigned long y)        |
+ |    unsigned long FPU_div_small(unsigned long long *x, unsigned long y)    |
  +---------------------------------------------------------------------------*/
 
 #include "fpu_emu.h"
 
 .text
-ENTRY(div_small)
+ENTRY(FPU_div_small)
 	pushl	%ebp
 	movl	%esp,%ebp
 
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/errors.c linux-2.0.40/arch/i386/math-emu/errors.c
--- linux-2.0.39/arch/i386/math-emu/errors.c	Mon May  6 15:31:17 1996
+++ linux-2.0.40/arch/i386/math-emu/errors.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  |  The error handling functions for wm-FPU-emu                              |
  |                                                                           |
- | Copyright (C) 1992,1993,1994,1996                                         |
+ | Copyright (C) 1992,1993,1994,1996,2001                                    |
  |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
- |                  E-mail   billm@jacobi.maths.monash.edu.au                |
+ |                  E-mail   billm@melbpc.org.au                             |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -19,11 +19,9 @@
 
 #include <linux/signal.h>
 
-#include <asm/segment.h>
-
+#include "fpu_emu.h"
 #include "fpu_system.h"
 #include "exception.h"
-#include "fpu_emu.h"
 #include "status_w.h"
 #include "control_w.h"
 #include "reg_constant.h"
@@ -36,23 +34,23 @@
 
 void Un_impl(void)
 {
-  unsigned char byte1, FPU_modrm;
+  u_char byte1, FPU_modrm;
   unsigned long address = FPU_ORIG_EIP;
 
   RE_ENTRANT_CHECK_OFF;
   /* No need to verify_area(), we have previously fetched these bytes. */
   printk("Unimplemented FPU Opcode at eip=%p : ", (void *) address);
-  if ( FPU_CS == USER_CS )
+  if ( FPU_CS == FPU_USER_CS )
     {
       while ( 1 )
 	{
-	  byte1 = get_fs_byte((unsigned char *) address);
+	  FPU_get_user(byte1, (u_char *) address);
 	  if ( (byte1 & 0xf8) == 0xd8 ) break;
 	  printk("[%02x]", byte1);
 	  address++;
 	}
       printk("%02x ", byte1);
-      FPU_modrm = get_fs_byte(1 + (unsigned char *) address);
+      FPU_get_user(FPU_modrm, 1 + (u_char *) address);
       
       if (FPU_modrm >= 0300)
 	printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
@@ -77,28 +75,28 @@
    */
 void FPU_illegal(void)
 {
-  math_abort(FPU_info,SIGILL);
+  math_abort(SIGILL);
 }
 
 
 
-void emu_printall(void)
+void FPU_printall(void)
 {
   int i;
-  static const char *tag_desc[] = { "Valid", "Zero", "ERROR", "ERROR",
-                              "DeNorm", "Inf", "NaN", "Empty" };
-  unsigned char byte1, FPU_modrm;
+  static const char *tag_desc[] = { "Valid", "Zero", "ERROR", "Empty",
+                              "DeNorm", "Inf", "NaN" };
+  u_char byte1, FPU_modrm;
   unsigned long address = FPU_ORIG_EIP;
 
   RE_ENTRANT_CHECK_OFF;
   /* No need to verify_area(), we have previously fetched these bytes. */
   printk("At %p:", (void *) address);
-  if ( FPU_CS == USER_CS )
+  if ( FPU_CS == FPU_USER_CS )
     {
 #define MAX_PRINTED_BYTES 20
       for ( i = 0; i < MAX_PRINTED_BYTES; i++ )
 	{
-	  byte1 = get_fs_byte((unsigned char *) address);
+	  FPU_get_user(byte1, (u_char *) address);
 	  if ( (byte1 & 0xf8) == 0xd8 )
 	    {
 	      printk(" %02x", byte1);
@@ -111,7 +109,7 @@
 	printk(" [more..]\n");
       else
 	{
-	  FPU_modrm = get_fs_byte(1 + (unsigned char *) address);
+	  FPU_get_user(FPU_modrm, 1 + (u_char *) address);
 	  
 	  if (FPU_modrm >= 0300)
 	    printk(" %02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
@@ -122,7 +120,7 @@
     }
   else
     {
-      printk("%04x\n", FPU_CS);
+      printk("%04x (Not USER_CS)\n", FPU_CS);
     }
 
   partial_status = status_word();
@@ -141,7 +139,7 @@
 if ( partial_status & SW_Zero_Div )    printk("SW: divide by zero\n");
 if ( partial_status & SW_Denorm_Op )   printk("SW: denormalized operand\n");
 if ( partial_status & SW_Invalid )     printk("SW: invalid operation\n");
-#endif DEBUGGING
+#endif /* DEBUGGING */
 
   printk(" SW: b=%d st=%ld es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n",
 	 partial_status & 0x8000 ? 1 : 0,   /* busy */
@@ -166,29 +164,23 @@
   for ( i = 0; i < 8; i++ )
     {
       FPU_REG *r = &st(i);
-      char tagi = r->tag;
+      u_char tagi = FPU_gettagi(i);
       switch (tagi)
 	{
-	case TW_Empty:
+	case TAG_Empty:
 	  continue;
 	  break;
-	case TW_Zero:
-#if 0
-	  printk("st(%d)  %c .0000 0000 0000 0000         ",
-		 i, r->sign ? '-' : '+');
-	  break;
-#endif
-	case TW_Valid:
-	case TW_NaN:
-/*	case TW_Denormal: */
-	case TW_Infinity:
-	  printk("st(%d)  %c .%04lx %04lx %04lx %04lx e%+-6ld ", i,
-		 r->sign ? '-' : '+',
+	case TAG_Zero:
+	case TAG_Special:
+	  tagi = FPU_Special(r);
+	case TAG_Valid:
+	  printk("st(%d)  %c .%04lx %04lx %04lx %04lx e%+-6d ", i,
+		 getsign(r) ? '-' : '+',
 		 (long)(r->sigh >> 16),
 		 (long)(r->sigh & 0xFFFF),
 		 (long)(r->sigl >> 16),
 		 (long)(r->sigl & 0xFFFF),
-		 r->exp - EXP_BIAS + 1);
+		 exponent(r) - EXP_BIAS + 1);
 	  break;
 	default:
 	  printk("Whoops! Error in errors.c: tag%d is %d ", i, tagi);
@@ -262,6 +254,11 @@
 	      0x161  in reg_ld_str.c
 	      0x162  in reg_ld_str.c
 	      0x163  in reg_ld_str.c
+	      0x164  in reg_ld_str.c
+	      0x170  in fpu_tags.c
+	      0x171  in fpu_tags.c
+	      0x172  in fpu_tags.c
+	      0x180  in reg_convert.c
        0x2nn  in an *.S file:
               0x201  in reg_u_add.S
               0x202  in reg_u_div.S
@@ -292,7 +289,7 @@
 	      0x242  in div_Xsig.S
  */
 
-void exception(int n)
+void FPU_exception(int n)
 {
   int i, int_type;
 
@@ -328,7 +325,7 @@
 #ifdef PRINT_MESSAGES
       /* My message from the sponsor */
       printk(FPU_VERSION" "__DATE__" (C) W. Metzenthen.\n");
-#endif PRINT_MESSAGES
+#endif /* PRINT_MESSAGES */
       
       /* Get a name string for error reporting */
       for (i=0; exception_names[i].type; i++)
@@ -339,7 +336,7 @@
 	{
 #ifdef PRINT_MESSAGES
 	  printk("FP Exception: %s!\n", exception_names[i].name);
-#endif PRINT_MESSAGES
+#endif /* PRINT_MESSAGES */
 	}
       else
 	printk("FPU emulator: Unknown Exception: 0x%04x!\n", n);
@@ -347,12 +344,12 @@
       if ( n == EX_INTERNAL )
 	{
 	  printk("FPU emulator: Internal error type 0x%04x\n", int_type);
-	  emu_printall();
+	  FPU_printall();
 	}
 #ifdef PRINT_MESSAGES
       else
-	emu_printall();
-#endif PRINT_MESSAGES
+	FPU_printall();
+#endif /* PRINT_MESSAGES */
 
       /*
        * The 80486 generates an interrupt on the next non-control FPU
@@ -363,30 +360,103 @@
   RE_ENTRANT_CHECK_ON;
 
 #ifdef __DEBUG__
-  math_abort(FPU_info,SIGFPE);
-#endif __DEBUG__
+  math_abort(SIGFPE);
+#endif /* __DEBUG__ */
 
 }
 
 
-/* Real operation attempted on two operands, one a NaN. */
-/* Returns nz if the exception is unmasked */
-asmlinkage int real_2op_NaN(FPU_REG const *a, FPU_REG const *b, FPU_REG *dest)
+/* Real operation attempted on a NaN. */
+/* Returns < 0 if the exception is unmasked */
+int real_1op_NaN(FPU_REG *a)
 {
-  FPU_REG const *x;
-  int signalling;
+  int signalling, isNaN;
+
+  isNaN = (exponent(a) == EXP_OVER) && (a->sigh & 0x80000000);
 
   /* The default result for the case of two "equal" NaNs (signs may
      differ) is chosen to reproduce 80486 behaviour */
-  x = a;
-  if (a->tag == TW_NaN)
+  signalling = isNaN && !(a->sigh & 0x40000000);
+
+  if ( !signalling )
+    {
+      if ( !isNaN )  /* pseudo-NaN, or other unsupported? */
+	{
+	  if ( control_word & CW_Invalid )
+	    {
+	      /* Masked response */
+	      reg_copy(&CONST_QNaN, a);
+	    }
+	  EXCEPTION(EX_Invalid);
+	  return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
+	}
+      return TAG_Special;
+    }
+
+  if ( control_word & CW_Invalid )
+    {
+      /* The masked response */
+      if ( !(a->sigh & 0x80000000) )  /* pseudo-NaN ? */
+	{
+	  reg_copy(&CONST_QNaN, a);
+	}
+      /* ensure a Quiet NaN */
+      a->sigh |= 0x40000000;
+    }
+
+  EXCEPTION(EX_Invalid);
+
+  return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
+}
+
+
+/* Real operation attempted on two operands, one a NaN. */
+/* Returns < 0 if the exception is unmasked */
+int real_2op_NaN(FPU_REG const *b, u_char tagb,
+		 int deststnr,
+		 FPU_REG const *defaultNaN)
+{
+  FPU_REG *dest = &st(deststnr);
+  FPU_REG const *a = dest;
+  u_char taga = FPU_gettagi(deststnr);
+  FPU_REG const *x;
+  int signalling, unsupported;
+
+  if ( taga == TAG_Special )
+    taga = FPU_Special(a);
+  if ( tagb == TAG_Special )
+    tagb = FPU_Special(b);
+
+  /* TW_NaN is also used for unsupported data types. */
+  unsupported = ((taga == TW_NaN)
+		 && !((exponent(a) == EXP_OVER) && (a->sigh & 0x80000000)))
+    || ((tagb == TW_NaN)
+	&& !((exponent(b) == EXP_OVER) && (b->sigh & 0x80000000)));
+  if ( unsupported )
+    {
+      if ( control_word & CW_Invalid )
+	{
+	  /* Masked response */
+	  FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr);
+	}
+      EXCEPTION(EX_Invalid);
+      return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
+    }
+
+  if (taga == TW_NaN)
     {
-      if (b->tag == TW_NaN)
+      x = a;
+      if (tagb == TW_NaN)
 	{
 	  signalling = !(a->sigh & b->sigh & 0x40000000);
-	  /* find the "larger" */
-	  if ( significand(a) < significand(b) )
+	  if ( significand(b) > significand(a) )
 	    x = b;
+	  else if ( significand(b) == significand(a) )
+	    {
+	      /* The default result for the case of two "equal" NaNs (signs may
+		 differ) is chosen to reproduce 80486 behaviour */
+	      x = defaultNaN;
+	    }
 	}
       else
 	{
@@ -396,8 +466,8 @@
     }
   else
 #ifdef PARANOID
-    if (b->tag == TW_NaN)
-#endif PARANOID
+    if (tagb == TW_NaN)
+#endif /* PARANOID */
     {
       signalling = !(b->sigh & 0x40000000);
       x = b;
@@ -409,35 +479,34 @@
       EXCEPTION(EX_INTERNAL|0x113);
       x = &CONST_QNaN;
     }
-#endif PARANOID
+#endif /* PARANOID */
 
-  if ( !signalling )
+  if ( (!signalling) || (control_word & CW_Invalid) )
     {
-      if ( !(x->sigh & 0x80000000) )  /* pseudo-NaN ? */
-	x = &CONST_QNaN;
-      reg_move(x, dest);
-      return 0;
-    }
+      if ( ! x )
+	x = b;
 
-  if ( control_word & CW_Invalid )
-    {
-      /* The masked response */
       if ( !(x->sigh & 0x80000000) )  /* pseudo-NaN ? */
 	x = &CONST_QNaN;
-      reg_move(x, dest);
+
+      FPU_copy_to_regi(x, TAG_Special, deststnr);
+
+      if ( !signalling )
+	return TAG_Special;
+
       /* ensure a Quiet NaN */
       dest->sigh |= 0x40000000;
     }
 
   EXCEPTION(EX_Invalid);
-  
-  return !(control_word & CW_Invalid);
+
+  return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
 }
 
 
 /* Invalid arith operation on Valid registers */
-/* Returns nz if the exception is unmasked */
-asmlinkage int arith_invalid(FPU_REG *dest)
+/* Returns < 0 if the exception is unmasked */
+asmlinkage int arith_invalid(int deststnr)
 {
 
   EXCEPTION(EX_Invalid);
@@ -445,28 +514,31 @@
   if ( control_word & CW_Invalid )
     {
       /* The masked response */
-      reg_move(&CONST_QNaN, dest);
+      FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr);
     }
   
-  return !(control_word & CW_Invalid);
+  return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Valid;
 
 }
 
 
 /* Divide a finite number by zero */
-asmlinkage int divide_by_zero(int sign, FPU_REG *dest)
+asmlinkage int FPU_divide_by_zero(int deststnr, u_char sign)
 {
+  FPU_REG *dest = &st(deststnr);
+  int tag = TAG_Valid;
 
   if ( control_word & CW_ZeroDiv )
     {
       /* The masked response */
-      reg_move(&CONST_INF, dest);
-      dest->sign = (unsigned char)sign;
+      FPU_copy_to_regi(&CONST_INF, TAG_Special, deststnr);
+      setsign(dest, sign);
+      tag = TAG_Special;
     }
  
   EXCEPTION(EX_ZeroDiv);
 
-  return !(control_word & CW_ZeroDiv);
+  return (!(control_word & CW_ZeroDiv) ? FPU_Exception : 0) | tag;
 
 }
 
@@ -482,7 +554,7 @@
     }
   else
     {
-      exception(flags);
+      EXCEPTION(flags);
       return 1;
     }
 }
@@ -494,8 +566,7 @@
   if ( control_word & CW_Precision )
     partial_status |= (SW_Precision | SW_C1);   /* The masked response */
   else
-    exception(EX_Precision | SW_C1);
-
+    EXCEPTION(EX_Precision | SW_C1);
 }
 
 
@@ -508,7 +579,7 @@
       partial_status |= SW_Precision;
     }
   else
-    exception(EX_Precision);
+    EXCEPTION(EX_Precision);
 }
 
 
@@ -517,32 +588,69 @@
   if ( control_word & CW_Denormal )
     {   /* The masked response */
       partial_status |= SW_Denorm_Op;
-      return 0;
+      return TAG_Special;
     }
   else
     {
-      exception(EX_Denormal);
-      return 1;
+      EXCEPTION(EX_Denormal);
+      return TAG_Special | FPU_Exception;
     }
 }
 
 
-asmlinkage int arith_overflow(FPU_REG *dest)
+asmlinkage int arith_overflow(FPU_REG *dest, int negative)
 {
+  int tag = TAG_Valid;
+  int big_real = 0;
 
   if ( control_word & CW_Overflow )
     {
-      char sign;
       /* The masked response */
-/* ###### The response here depends upon the rounding mode */
-      sign = dest->sign;
-      reg_move(&CONST_INF, dest);
-      dest->sign = sign;
+      /* The response here depends upon the rounding mode */
+      switch ( control_word & CW_RC )
+	{
+	case RC_UP:
+	  big_real = negative;
+	  break;
+	case RC_DOWN:
+	  big_real = ! negative;
+	  break;
+	case RC_CHOP:
+	  big_real = 1;
+	  break;
+	default:
+	}
+      if ( big_real )
+	{
+	  switch ( control_word & CW_PC )
+	    {
+	    case PR_24_BITS:
+	      significand(dest) = 0xffffff0000000000LL;
+	      exponent16(dest) = 0x7ffe;
+	      break;
+	    case PR_53_BITS:
+	      significand(dest) = 0xfffffffffffff800LL;
+	      exponent16(dest) = 0x7ffe;
+	      break;
+	    case PR_64_BITS:
+	      significand(dest) = 0xffffffffffffffffLL;
+	      exponent16(dest) = 0x7ffe;
+	      break;
+	    }
+	  EXCEPTION(EX_Overflow);
+	  EXCEPTION(EX_Precision);
+	  return tag;
+	}
+      else
+	{
+	  reg_copy(&CONST_INF, dest);
+	  tag = TAG_Special;
+	}
     }
   else
     {
       /* Subtract the magic number from the exponent */
-      dest->exp -= (3 * (1 << 13));
+      addexponent(dest, (-3 * (1 << 13)));
     }
 
   EXCEPTION(EX_Overflow);
@@ -553,30 +661,36 @@
 	 The roundup bit (C1) is also set because we have
 	 "rounded" upwards to Infinity. */
       EXCEPTION(EX_Precision | SW_C1);
-      return !(control_word & CW_Precision);
+      return tag;
     }
 
-  return 0;
+  return tag;
 
 }
 
 
 asmlinkage int arith_underflow(FPU_REG *dest)
 {
+  int tag = TAG_Valid;
 
   if ( control_word & CW_Underflow )
     {
       /* The masked response */
-      if ( dest->exp <= EXP_UNDER - 63 )
+      if ( exponent16(dest) <= EXP_UNDER - 63 )
 	{
-	  reg_move(&CONST_Z, dest);
+	  reg_copy(&CONST_Z, dest);
 	  partial_status &= ~SW_C1;       /* Round down. */
+	  tag = TAG_Zero;
+	}
+      else
+	{
+	  stdexp(dest);
 	}
     }
   else
     {
       /* Add the magic number to the exponent. */
-      dest->exp += (3 * (1 << 13));
+      addexponent(dest, (3 * (1 << 13)) + EXTENDED_Ebias);
     }
 
   EXCEPTION(EX_Underflow);
@@ -584,22 +698,22 @@
     {
       /* The underflow exception is masked. */
       EXCEPTION(EX_Precision);
-      return !(control_word & CW_Precision);
+      return tag;
     }
 
-  return 0;
+  return tag;
 
 }
 
 
-void stack_overflow(void)
+void FPU_stack_overflow(void)
 {
 
  if ( control_word & CW_Invalid )
     {
       /* The masked response */
-      top--;
-      reg_move(&CONST_QNaN, &st(0));
+      FPU_top--;
+      FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
     }
 
   EXCEPTION(EX_StackOver);
@@ -609,13 +723,13 @@
 }
 
 
-void stack_underflow(void)
+void FPU_stack_underflow(void)
 {
 
  if ( control_word & CW_Invalid )
     {
       /* The masked response */
-      reg_move(&CONST_QNaN, &st(0));
+      FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
     }
 
   EXCEPTION(EX_StackUnder);
@@ -625,13 +739,13 @@
 }
 
 
-void stack_underflow_i(int i)
+void FPU_stack_underflow_i(int i)
 {
 
  if ( control_word & CW_Invalid )
     {
       /* The masked response */
-      reg_move(&CONST_QNaN, &(st(i)));
+      FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i);
     }
 
   EXCEPTION(EX_StackUnder);
@@ -641,14 +755,14 @@
 }
 
 
-void stack_underflow_pop(int i)
+void FPU_stack_underflow_pop(int i)
 {
 
  if ( control_word & CW_Invalid )
     {
       /* The masked response */
-      reg_move(&CONST_QNaN, &(st(i)));
-      pop();
+      FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i);
+      FPU_pop();
     }
 
   EXCEPTION(EX_StackUnder);
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/exception.h linux-2.0.40/arch/i386/math-emu/exception.h
--- linux-2.0.39/arch/i386/math-emu/exception.h	Sat Mar 29 01:12:25 1997
+++ linux-2.0.40/arch/i386/math-emu/exception.h	Mon Oct  8 23:54:43 2001
@@ -18,7 +18,7 @@
 
 #ifndef SW_C1
 #include "fpu_emu.h"
-#endif SW_C1
+#endif /* SW_C1 */
 
 #define FPU_BUSY        Const_(0x8000)   /* FPU busy bit (8087 compatibility) */
 #define EX_ErrorSummary Const_(0x0080)   /* Error summary status */
@@ -43,11 +43,11 @@
 
 #ifdef DEBUG
 #define	EXCEPTION(x)	{ printk("exception in %s at line %d\n", \
-	__FILE__, __LINE__); exception(x); }
+	__FILE__, __LINE__); FPU_exception(x); }
 #else
-#define	EXCEPTION(x)	exception(x)
+#define	EXCEPTION(x)	FPU_exception(x)
 #endif
 
-#endif __ASSEMBLY__
+#endif /* __ASSEMBLY__ */ 
 
-#endif _EXCEPTION_H_
+#endif /* _EXCEPTION_H_ */
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/fpu_arith.c linux-2.0.40/arch/i386/math-emu/fpu_arith.c
--- linux-2.0.39/arch/i386/math-emu/fpu_arith.c	Thu Jun  2 09:28:23 1994
+++ linux-2.0.40/arch/i386/math-emu/fpu_arith.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  | Code to implement the FPU register/register arithmetic instructions       |
  |                                                                           |
- | Copyright (C) 1992,1993                                                   |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ | Copyright (C) 1992,1993,1997                                              |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -19,16 +19,18 @@
 void fadd__()
 {
   /* fadd st,st(i) */
+  int i = FPU_rm;
   clear_C1();
-  reg_add(&st(0), &st(FPU_rm), &st(0), control_word);
+  FPU_add(&st(i), FPU_gettagi(i), 0, control_word);
 }
 
 
 void fmul__()
 {
   /* fmul st,st(i) */
+  int i = FPU_rm;
   clear_C1();
-  reg_mul(&st(0), &st(FPU_rm), &st(0), control_word);
+  FPU_mul(&st(i), FPU_gettagi(i), 0, control_word);
 }
 
 
@@ -37,7 +39,7 @@
 {
   /* fsub st,st(i) */
   clear_C1();
-  reg_sub(&st(0), &st(FPU_rm), &st(0), control_word);
+  FPU_sub(0, FPU_rm, control_word);
 }
 
 
@@ -45,7 +47,7 @@
 {
   /* fsubr st,st(i) */
   clear_C1();
-  reg_sub(&st(FPU_rm), &st(0), &st(0), control_word);
+  FPU_sub(REV, FPU_rm, control_word);
 }
 
 
@@ -53,7 +55,7 @@
 {
   /* fdiv st,st(i) */
   clear_C1();
-  reg_div(&st(0), &st(FPU_rm), &st(0), control_word);
+  FPU_div(0, FPU_rm, control_word);
 }
 
 
@@ -61,7 +63,7 @@
 {
   /* fdivr st,st(i) */
   clear_C1();
-  reg_div(&st(FPU_rm), &st(0), &st(0), control_word);
+  FPU_div(REV, FPU_rm, control_word);
 }
 
 
@@ -69,8 +71,9 @@
 void fadd_i()
 {
   /* fadd st(i),st */
+  int i = FPU_rm;
   clear_C1();
-  reg_add(&st(0), &st(FPU_rm), &st(FPU_rm), control_word);
+  FPU_add(&st(i), FPU_gettagi(i), i, control_word);
 }
 
 
@@ -78,27 +81,23 @@
 {
   /* fmul st(i),st */
   clear_C1();
-  reg_mul(&st(0), &st(FPU_rm), &st(FPU_rm), control_word);
+  FPU_mul(&st(0), FPU_gettag0(), FPU_rm, control_word);
 }
 
 
 void fsubri()
 {
   /* fsubr st(i),st */
-  /* This is the sense of the 80486 manual
-     reg_sub(&st(FPU_rm), &st(0), &st(FPU_rm), control_word); */
   clear_C1();
-  reg_sub(&st(0), &st(FPU_rm), &st(FPU_rm), control_word);
+  FPU_sub(DEST_RM, FPU_rm, control_word);
 }
 
 
 void fsub_i()
 {
   /* fsub st(i),st */
-  /* This is the sense of the 80486 manual
-     reg_sub(&st(0), &st(FPU_rm), &st(FPU_rm), control_word); */
   clear_C1();
-  reg_sub(&st(FPU_rm), &st(0), &st(FPU_rm), control_word);
+  FPU_sub(REV|DEST_RM, FPU_rm, control_word);
 }
 
 
@@ -106,7 +105,7 @@
 {
   /* fdivr st(i),st */
   clear_C1();
-  reg_div(&st(0), &st(FPU_rm), &st(FPU_rm), control_word);
+  FPU_div(DEST_RM, FPU_rm, control_word);
 }
 
 
@@ -114,7 +113,7 @@
 {
   /* fdiv st(i),st */
   clear_C1();
-  reg_div(&st(FPU_rm), &st(0), &st(FPU_rm), control_word);
+  FPU_div(REV|DEST_RM, FPU_rm, control_word);
 }
 
 
@@ -122,9 +121,10 @@
 void faddp_()
 {
   /* faddp st(i),st */
+  int i = FPU_rm;
   clear_C1();
-  if ( !reg_add(&st(0), &st(FPU_rm), &st(FPU_rm), control_word) )
-    pop();
+  if ( FPU_add(&st(i), FPU_gettagi(i), i, control_word) >= 0 )
+    FPU_pop();
 }
 
 
@@ -132,8 +132,8 @@
 {
   /* fmulp st(i),st */
   clear_C1();
-  if ( !reg_mul(&st(0), &st(FPU_rm), &st(FPU_rm), control_word) )
-    pop();
+  if ( FPU_mul(&st(0), FPU_gettag0(), FPU_rm, control_word) >= 0 )
+    FPU_pop();
 }
 
 
@@ -141,22 +141,18 @@
 void fsubrp()
 {
   /* fsubrp st(i),st */
-  /* This is the sense of the 80486 manual
-     reg_sub(&st(FPU_rm), &st(0), &st(FPU_rm), control_word); */
   clear_C1();
-  if ( !reg_sub(&st(0), &st(FPU_rm), &st(FPU_rm), control_word) )
-    pop();
+  if ( FPU_sub(DEST_RM, FPU_rm, control_word) >= 0 )
+    FPU_pop();
 }
 
 
 void fsubp_()
 {
   /* fsubp st(i),st */
-  /* This is the sense of the 80486 manual
-     reg_sub(&st(0), &st(FPU_rm), &st(FPU_rm), control_word); */
   clear_C1();
-  if ( !reg_sub(&st(FPU_rm), &st(0), &st(FPU_rm), control_word) )
-    pop();
+  if ( FPU_sub(REV|DEST_RM, FPU_rm, control_word) >= 0 )
+    FPU_pop();
 }
 
 
@@ -164,8 +160,8 @@
 {
   /* fdivrp st(i),st */
   clear_C1();
-  if ( !reg_div(&st(0), &st(FPU_rm), &st(FPU_rm), control_word) )
-    pop();
+  if ( FPU_div(DEST_RM, FPU_rm, control_word) >= 0 )
+    FPU_pop();
 }
 
 
@@ -173,7 +169,6 @@
 {
   /* fdivp st(i),st */
   clear_C1();
-  if ( !reg_div(&st(FPU_rm), &st(0), &st(FPU_rm), control_word) )
-    pop();
+  if ( FPU_div(REV|DEST_RM, FPU_rm, control_word) >= 0 )
+    FPU_pop();
 }
-
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/fpu_asm.h linux-2.0.40/arch/i386/math-emu/fpu_asm.h
--- linux-2.0.39/arch/i386/math-emu/fpu_asm.h	Thu Oct  5 14:30:43 1995
+++ linux-2.0.40/arch/i386/math-emu/fpu_asm.h	Mon Oct  8 23:54:43 2001
@@ -1,9 +1,9 @@
 /*---------------------------------------------------------------------------+
  |  fpu_asm.h                                                                |
  |                                                                           |
- | Copyright (C) 1992,1995                                                   |
+ | Copyright (C) 1992,1995,1997                                              |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                       Australia.  E-mail billm@suburbia.net               |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
@@ -12,20 +12,21 @@
 
 #include <linux/linkage.h>
 
-#define	EXCEPTION	SYMBOL_NAME(exception)
+#define	EXCEPTION	SYMBOL_NAME(FPU_exception)
 
 
 #define PARAM1	8(%ebp)
 #define	PARAM2	12(%ebp)
 #define	PARAM3	16(%ebp)
 #define	PARAM4	20(%ebp)
+#define	PARAM5	24(%ebp)
+#define	PARAM6	28(%ebp)
+#define	PARAM7	32(%ebp)
 
-#define SIGL_OFFSET 8
-#define SIGN(x)	(x)
-#define	TAG(x)	1(x)
-#define	EXP(x)	4(x)
+#define SIGL_OFFSET 0
+#define	EXP(x)	8(x)
 #define SIG(x)	SIGL_OFFSET##(x)
 #define	SIGL(x)	SIGL_OFFSET##(x)
-#define	SIGH(x)	12(x)
+#define	SIGH(x)	4(x)
 
-#endif _FPU_ASM_H_
+#endif /* _FPU_ASM_H_ */
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/fpu_aux.c linux-2.0.40/arch/i386/math-emu/fpu_aux.c
--- linux-2.0.39/arch/i386/math-emu/fpu_aux.c	Thu Jun  2 09:28:23 1994
+++ linux-2.0.40/arch/i386/math-emu/fpu_aux.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  | Code to implement some of the FPU auxiliary instructions.                 |
  |                                                                           |
- | Copyright (C) 1992,1993,1994                                              |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ | Copyright (C) 1992,1993,1994,1997,2001                                    |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@melbpc.org.au                             |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -32,15 +32,11 @@
 /* Needs to be externally visible */
 void finit()
 {
-  int r;
   control_word = 0x037f;
   partial_status = 0;
-  top = 0;            /* We don't keep top in the status word internally. */
-  for (r = 0; r < 8; r++)
-    {
-      regs[r].tag = TW_Empty;
-    }
-  /* The behaviour is different to that detailed in
+  FPU_top = 0;            /* We don't keep top in the status word internally. */
+  fpu_tag_word = 0xffff;
+  /* The behaviour is different from that detailed in
      Section 15.1.6 of the Intel manual */
   operand_address.offset = 0;
   operand_address.selector = 0;
@@ -99,19 +95,27 @@
 void fld_i_()
 {
   FPU_REG *st_new_ptr;
+  int i;
+  u_char tag;
 
   if ( STACK_OVERFLOW )
-    { stack_overflow(); return; }
+    { FPU_stack_overflow(); return; }
 
   /* fld st(i) */
-  if ( NOT_EMPTY(FPU_rm) )
-    { reg_move(&st(FPU_rm), st_new_ptr); push(); }
+  i = FPU_rm;
+  if ( NOT_EMPTY(i) )
+    {
+      reg_copy(&st(i), st_new_ptr);
+      tag = FPU_gettagi(i);
+      push();
+      FPU_settag0(tag);
+    }
   else
     {
       if ( control_word & CW_Invalid )
 	{
 	  /* The masked response */
-	  stack_underflow();
+	  FPU_stack_underflow();
 	}
       else
 	EXCEPTION(EX_StackUnder);
@@ -124,61 +128,155 @@
 {
   /* fxch st(i) */
   FPU_REG t;
-  register FPU_REG *sti_ptr = &st(FPU_rm), *st0_ptr = &st(0);
+  int i = FPU_rm;
+  FPU_REG *st0_ptr = &st(0), *sti_ptr = &st(i);
+  long tag_word = fpu_tag_word;
+  int regnr = FPU_top & 7, regnri = ((regnr + i) & 7);
+  u_char st0_tag = (tag_word >> (regnr*2)) & 3;
+  u_char sti_tag = (tag_word >> (regnri*2)) & 3;
 
-  if ( st0_ptr->tag == TW_Empty )
+  if ( st0_tag == TAG_Empty )
     {
-      if ( sti_ptr->tag == TW_Empty )
+      if ( sti_tag == TAG_Empty )
 	{
-	  stack_underflow();
-	  stack_underflow_i(FPU_rm);
+	  FPU_stack_underflow();
+	  FPU_stack_underflow_i(i);
 	  return;
 	}
       if ( control_word & CW_Invalid )
-	reg_move(sti_ptr, st0_ptr);   /* Masked response */
-      stack_underflow_i(FPU_rm);
+	{
+	  /* Masked response */
+	  FPU_copy_to_reg0(sti_ptr, sti_tag);
+	}
+      FPU_stack_underflow_i(i);
       return;
     }
-  if ( sti_ptr->tag == TW_Empty )
+  if ( sti_tag == TAG_Empty )
     {
       if ( control_word & CW_Invalid )
-	reg_move(st0_ptr, sti_ptr);   /* Masked response */
-      stack_underflow();
+	{
+	  /* Masked response */
+	  FPU_copy_to_regi(st0_ptr, st0_tag, i);
+	}
+      FPU_stack_underflow();
       return;
     }
   clear_C1();
-  reg_move(st0_ptr, &t);
-  reg_move(sti_ptr, st0_ptr);
-  reg_move(&t, sti_ptr);
+
+  reg_copy(st0_ptr, &t);
+  reg_copy(sti_ptr, st0_ptr);
+  reg_copy(&t, sti_ptr);
+
+  tag_word &= ~(3 << (regnr*2)) & ~(3 << (regnri*2));
+  tag_word |= (sti_tag << (regnr*2)) | (st0_tag << (regnri*2));
+  fpu_tag_word = tag_word;
 }
 
 
 void ffree_()
 {
   /* ffree st(i) */
-  st(FPU_rm).tag = TW_Empty;
+  FPU_settagi(FPU_rm, TAG_Empty);
 }
 
 
 void ffreep()
 {
   /* ffree st(i) + pop - unofficial code */
-  st(FPU_rm).tag = TW_Empty;
-  pop();
+  FPU_settagi(FPU_rm, TAG_Empty);
+  FPU_pop();
 }
 
 
 void fst_i_()
 {
   /* fst st(i) */
-  reg_move(&st(0), &st(FPU_rm));
+  FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm);
 }
 
 
 void fstp_i()
 {
   /* fstp st(i) */
-  reg_move(&st(0), &st(FPU_rm));
-  pop();
+  FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm);
+  FPU_pop();
+}
+
+
+#ifndef ONLY_486_FPU
+static void fmov_i(void)
+{
+  int i;
+  u_char tag;
+
+  /* for the fcmovxx instructions */
+  i = FPU_rm;
+  if ( NOT_EMPTY(i) )
+    {
+      reg_copy(&st(i), &st(0));
+      tag = FPU_gettagi(i);
+      FPU_settag0(tag);
+    }
+  else
+    {
+      if ( control_word & CW_Invalid )
+	{
+	  /* The masked response */
+	  FPU_stack_underflow();
+	}
+      else
+	EXCEPTION(EX_StackUnder);
+    }
+
+}
+
+
+void fcmovnb(void)
+{
+  if ( ! (FPU_EFLAGS & CFLAG) )
+    fmov_i();
+}
+
+void fcmovne(void)
+{
+  if ( ! (FPU_EFLAGS & ZFLAG) )
+    fmov_i();
+}
+
+void fcmovnbe(void)
+{
+  if ( ! (FPU_EFLAGS & (CFLAG | ZFLAG)) )
+    fmov_i();
+}
+
+void fcmovnu(void)
+{
+  if ( ! (FPU_EFLAGS & PFLAG) )
+    fmov_i();
+}
+
+void fcmovb (void)
+{
+  if ( (FPU_EFLAGS & CFLAG) )
+    fmov_i();
+}
+
+void fcmove (void)
+{
+  if ( (FPU_EFLAGS & ZFLAG) )
+    fmov_i();
+}
+
+void fcmovbe(void)
+{
+  if ( (FPU_EFLAGS & (CFLAG | ZFLAG)) )
+    fmov_i();
+}
+
+void fcmovu (void)
+{
+  if ( (FPU_EFLAGS & PFLAG) )
+    fmov_i();
 }
 
+#endif /* ONLY_486_FPU */
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/fpu_debug.c linux-2.0.40/arch/i386/math-emu/fpu_debug.c
--- linux-2.0.39/arch/i386/math-emu/fpu_debug.c	Fri Nov  7 18:11:42 1997
+++ linux-2.0.40/arch/i386/math-emu/fpu_debug.c	Thu Jan  1 01:00:00 1970
@@ -1,230 +0,0 @@
-/* Interface with ptrace and core-dumping routines */
-
-
-#include "fpu_system.h"
-#include "exception.h"
-#include "reg_constant.h"
-#include "fpu_emu.h"
-#include "control_w.h"
-#include "status_w.h"
-
-
-#define EXTENDED_Ebias 0x3fff
-#define EXTENDED_Emin (-0x3ffe)  /* smallest valid exponent */
-
-#define DOUBLE_Emax 1023         /* largest valid exponent */
-#define DOUBLE_Ebias 1023
-#define DOUBLE_Emin (-1022)      /* smallest valid exponent */
-
-#define SINGLE_Emax 127          /* largest valid exponent */
-#define SINGLE_Ebias 127
-#define SINGLE_Emin (-126)       /* smallest valid exponent */
-
-
-/* Copy and paste from round_to_int. Original comments maintained */
-/*===========================================================================*/
-
-/* r gets mangled such that sig is int, sign: 
-   it is NOT normalized */
-/* The return value (in eax) is zero if the result is exact,
-   if bits are changed due to rounding, truncation, etc, then
-   a non-zero value is returned */
-/* Overflow is signalled by a non-zero return value (in eax).
-   In the case of overflow, the returned significand always has the
-   largest possible value */
-
-static int round_to_int_cwd(FPU_REG *r, long int user_control_word)
-{
-  char     very_big;
-  unsigned eax;
-
-  if (r->tag == TW_Zero)
-    {
-      /* Make sure that zero is returned */
-      significand(r) = 0;
-      return 0;        /* o.k. */
-    }
-  
-  if (r->exp > EXP_BIAS + 63)
-    {
-      r->sigl = r->sigh = ~0;      /* The largest representable number */
-      return 1;        /* overflow */
-    }
-
-  eax = shrxs(&r->sigl, EXP_BIAS + 63 - r->exp);
-  very_big = !(~(r->sigh) | ~(r->sigl));  /* test for 0xfff...fff */
-#define	half_or_more	(eax & 0x80000000)
-#define	frac_part	(eax)
-#define more_than_half  ((eax & 0x80000001) == 0x80000001)
-  switch (user_control_word & CW_RC)
-    {
-    case RC_RND:
-      if ( more_than_half               	/* nearest */
-	  || (half_or_more && (r->sigl & 1)) )	/* odd -> even */
-	{
-	  if ( very_big ) return 1;        /* overflow */
-	  significand(r) ++;
-	  return PRECISION_LOST_UP;
-	}
-      break;
-    case RC_DOWN:
-      if (frac_part && r->sign)
-	{
-	  if ( very_big ) return 1;        /* overflow */
-	  significand(r) ++;
-	  return PRECISION_LOST_UP;
-	}
-      break;
-    case RC_UP:
-      if (frac_part && !r->sign)
-	{
-	  if ( very_big ) return 1;        /* overflow */
-	  significand(r) ++;
-	  return PRECISION_LOST_UP;
-	}
-      break;
-    case RC_CHOP:
-      break;
-    }
-
-  return eax ? PRECISION_LOST_DOWN : 0;
-
-}
-
-
-
-/* Conver a number in the emulator format to the
- * hardware format.
- * Taken from the emulator sources, function reg_load_extended
- */
-
-/* Get a long double from the debugger */
-void hardreg_to_softreg(const char hardreg[10],
-			      FPU_REG *soft_reg)
-
-{
-	unsigned long sigl, sigh, exp;
-		
-	sigl = *((unsigned long *) hardreg);
-	sigh = *(1 + (unsigned long *) hardreg);
-	exp = *(4 + (unsigned short *) hardreg);
-	
-	soft_reg->tag = TW_Valid;   /* Default */
-	soft_reg->sigl = sigl;
-	soft_reg->sigh = sigh;
-	if (exp & 0x8000)
-		soft_reg->sign = SIGN_NEG;
-	else
-		soft_reg->sign = SIGN_POS;
-	exp &= 0x7fff;
-	soft_reg->exp = exp - EXTENDED_Ebias + EXP_BIAS;
-	
-	if ( exp == 0 )
-	{
-		if ( !(sigh | sigl) )
-		{
-			soft_reg->tag = TW_Zero;
-			return;
-		}
-		/* The number is a de-normal or pseudodenormal. */
-		if (sigh & 0x80000000)
-		{
-			/* Is a pseudodenormal. */
-			/* Convert it for internal use. */
-			/* This is non-80486 behaviour because the number
-			   loses its 'denormal' identity. */
-			soft_reg->exp++;
-			return;
-		}
-		else
-		{
-			/* Is a denormal. */
-			/* Convert it for internal use. */
-			soft_reg->exp++;
-			normalize_nuo(soft_reg);
-			return;
-		}
-	}
-	else if ( exp == 0x7fff )
-	{
-		if ( !((sigh ^ 0x80000000) | sigl) )
-		{
-			/* Matches the bit pattern for Infinity. */
-			soft_reg->exp = EXP_Infinity;
-			soft_reg->tag = TW_Infinity;
-			return;
-		}
-		
-		soft_reg->exp = EXP_NaN;
-		soft_reg->tag = TW_NaN;
-		if ( !(sigh & 0x80000000) )
-		{
-			/* NaNs have the ms bit set to 1. */
-			/* This is therefore an Unsupported NaN data type. */
-			/* This is non 80486 behaviour */
-			/* This should generate an Invalid Operand exception
-			   later, so we convert it to a SNaN */
-			soft_reg->sigh = 0x80000000;
-			soft_reg->sigl = 0x00000001;
-			soft_reg->sign = SIGN_NEG;
-			return;
-		}
-		return;
-	}
-	
-	if ( !(sigh & 0x80000000) )
-	{
-		/* Unsupported data type. */
-		/* Valid numbers have the ms bit set to 1. */
-		/* Unnormal. */
-		/* Convert it for internal use. */
-		/* This is non-80486 behaviour */
-		/* This should generate an Invalid Operand exception
-		   later, so we convert it to a SNaN */
-		soft_reg->sigh = 0x80000000;
-		soft_reg->sigl = 0x00000001;
-		soft_reg->sign = SIGN_NEG;
-		soft_reg->exp = EXP_NaN;
-		soft_reg->tag = TW_NaN;
-		return;
-	}
-	return;
-}
-
-/* Conver a number in the emulator format to the
- * hardware format.
- * Adapted from function write_to_extended
- */
-
-
-void softreg_to_hardreg(const FPU_REG *rp, char d[10], long int user_control_word)
-{
-	long e;
-	FPU_REG tmp;
-	e = rp->exp - EXP_BIAS + EXTENDED_Ebias;
-
-	/*
-	  All numbers except denormals are stored internally in a
-	  format which is compatible with the extended real number
-	  format.
-	  */
-	if (e > 0) {
-		*(unsigned long *) d = rp->sigl;
-		*(unsigned long *) (d + 4) = rp->sigh;
-	} else {
-		/*
-		  The number is a de-normal stored as a normal using our
-		  extra exponent range, or is Zero.
-		  Convert it back to a de-normal, or leave it as Zero.
-		  */
-		reg_move(rp, &tmp);
-		tmp.exp += -EXTENDED_Emin + 63;  /* largest exp to be 63 */
-		round_to_int_cwd(&tmp, user_control_word);
-		e = 0;
-		*(unsigned long *) d= tmp.sigl;
-		*(unsigned long *) (d + 4) = tmp.sigh;
-	}
-	e |= rp->sign == SIGN_POS ? 0 : 0x8000;
-	*(unsigned short *) (d + 8) = e;
-}
-
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/fpu_emu.h linux-2.0.40/arch/i386/math-emu/fpu_emu.h
--- linux-2.0.39/arch/i386/math-emu/fpu_emu.h	Sun Sep 22 09:13:54 1996
+++ linux-2.0.40/arch/i386/math-emu/fpu_emu.h	Mon Oct  8 23:54:43 2001
@@ -1,9 +1,9 @@
 /*---------------------------------------------------------------------------+
  |  fpu_emu.h                                                                |
  |                                                                           |
- | Copyright (C) 1992,1993,1994                                              |
+ | Copyright (C) 1992,1993,1994,1997,2001                                    |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                       Australia.  E-mail   billm@melbpc.org.au            |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
@@ -12,14 +12,6 @@
 #define _FPU_EMU_H_
 
 /*
- * Define DENORM_OPERAND to make the emulator detect denormals
- * and use the denormal flag of the status word. Note: this only
- * affects the flag and corresponding interrupt, the emulator
- * will always generate denormals and operate upon them as required.
- */
-#define DENORM_OPERAND
-
-/*
  * Define PECULIAR_486 to get a closer approximation to 80486 behaviour,
  * rather than behaviour which appears to be cleaner.
  * This is a matter of opinion: for all I know, the 80486 may simply
@@ -38,28 +30,51 @@
 #define EXP_BIAS	Const(0)
 #define EXP_OVER	Const(0x4000)    /* smallest invalid large exponent */
 #define	EXP_UNDER	Const(-0x3fff)   /* largest invalid small exponent */
+#define EXP_WAY_UNDER   Const(-0x6000)   /* Below the smallest denormal, but
+					    still a 16 bit nr. */
 #define EXP_Infinity    EXP_OVER
 #define EXP_NaN         EXP_OVER
 
+#define EXTENDED_Ebias Const(0x3fff)
+#define EXTENDED_Emin (-0x3ffe)  /* smallest valid exponent */
+
 #define SIGN_POS	Const(0)
-#define SIGN_NEG	Const(1)
+#define SIGN_NEG	Const(0x80)
 
-/* Keep the order TW_Valid, TW_Zero, TW_Denormal */
-#define TW_Valid	Const(0)	/* valid */
-#define TW_Zero		Const(1)	/* zero */
+#define SIGN_Positive	Const(0)
+#define SIGN_Negative	Const(0x8000)
+
+
+/* Keep the order TAG_Valid, TAG_Zero, TW_Denormal */
 /* The following fold to 2 (Special) in the Tag Word */
-/* #define TW_Denormal     Const(4) */       /* De-normal */
+#define TW_Denormal     Const(4)        /* De-normal */
 #define TW_Infinity	Const(5)	/* + or - infinity */
 #define	TW_NaN		Const(6)	/* Not a Number */
+#define	TW_Unsupported	Const(7)	/* Not supported by an 80486 */
+
+#define TAG_Valid	Const(0)	/* valid */
+#define TAG_Zero	Const(1)	/* zero */
+#define TAG_Special	Const(2)	/* De-normal, + or - infinity,
+					   or Not a Number */
+#define TAG_Empty	Const(3)	/* empty */
+
+#define LOADED_DATA	Const(10101)	/* Special st() number to identify
+					   loaded data (not on stack). */
+
+/* A few flags (must be >= 0x10). */
+#define REV             0x10
+#define DEST_RM         0x20
+#define LOADED          0x40
 
-#define TW_Empty	Const(7)	/* empty */
+#define FPU_Exception   Const(0x80000000)   /* Added to tag returns. */
 
 
 #ifndef __ASSEMBLY__
 
-#include <asm/sigcontext.h>	/* for struct _fpstate */
-#include <asm/math_emu.h>
+#include "fpu_system.h"
 
+#include <asm/sigcontext.h>   /* for struct _fpstate */
+#include <asm/math_emu.h>
 #include <linux/linkage.h>
 
 /*
@@ -67,13 +82,13 @@
  */
 
 #ifdef RE_ENTRANT_CHECKING
-extern char emulating;
+extern u_char emulating;
 #  define RE_ENTRANT_CHECK_OFF emulating = 0
 #  define RE_ENTRANT_CHECK_ON emulating = 1
 #else
 #  define RE_ENTRANT_CHECK_OFF
 #  define RE_ENTRANT_CHECK_ON
-#endif RE_ENTRANT_CHECKING
+#endif /* RE_ENTRANT_CHECKING */
 
 #define FWAIT_OPCODE 0x9b
 #define OP_SIZE_PREFIX 0x66
@@ -97,18 +112,24 @@
 
 struct address {
   unsigned int offset;
-  unsigned short selector;
-  unsigned short opcode:11,
-		 empty:5;
+  unsigned int selector:16;
+  unsigned int opcode:11;
+  unsigned int empty:5;
+};
+struct fpu__reg {
+  unsigned sigl;
+  unsigned sigh;
+  short exp;
 };
+
 typedef void (*FUNC)(void);
-typedef struct fpu_reg FPU_REG;
-typedef void (*FUNC_ST0)(FPU_REG *st0_ptr);
-typedef struct { unsigned char address_size, operand_size, segment; }
+typedef struct fpu__reg FPU_REG;
+typedef void (*FUNC_ST0)(FPU_REG *st0_ptr, u_char st0_tag);
+typedef struct { u_char address_size, operand_size, segment; }
         overrides;
 /* This structure is 32 bits: */
 typedef struct { overrides override;
-		 unsigned char default_mode; } fpu_addr_modes;
+		 u_char default_mode; } fpu_addr_modes;
 /* PROTECTED has a restricted meaning in the emulator; it is used
    to signal that the emulator needs to do special things to ensure
    that protection is respected in a segmented model. */
@@ -117,27 +138,48 @@
 #define VM86      SIXTEEN
 #define PM16      (SIXTEEN | PROTECTED)
 #define SEG32     PROTECTED
-extern unsigned char const data_sizes_16[32];
+extern u_char const data_sizes_16[32];
+
+#define register_base ((u_char *) registers )
+#define fpu_register(x)  ( * ((FPU_REG *)( register_base + 10 * (x & 7) )) )
+#define	st(x)      ( * ((FPU_REG *)( register_base + 10 * ((FPU_top+x) & 7) )) )
+
+#define	STACK_OVERFLOW	(FPU_stackoverflow(&st_new_ptr))
+#define	NOT_EMPTY(i)	(!FPU_empty_i(i))
 
-#define	st(x)	( regs[((top+x) &7 )] )
+#define	NOT_EMPTY_ST0	(st0_tag ^ TAG_Empty)
 
-#define	STACK_OVERFLOW	(st_new_ptr = &st(-1), st_new_ptr->tag != TW_Empty)
-#define	NOT_EMPTY(i)	(st(i).tag != TW_Empty)
-#define	NOT_EMPTY_ST0	(st0_tag ^ TW_Empty)
-
-#define pop()	{ regs[(top++ & 7 )].tag = TW_Empty; }
-#define poppop() { regs[((top + 1) & 7 )].tag \
-		     = regs[(top & 7 )].tag = TW_Empty; \
-		   top += 2; }
+#define poppop() { FPU_pop(); FPU_pop(); }
 
 /* push() does not affect the tags */
-#define push()	{ top--; }
+#define push()	{ FPU_top--; }
 
+#define signbyte(a) (((u_char *)(a))[9])
+#define getsign(a) (signbyte(a) & 0x80)
+#define setsign(a,b) { if (b) signbyte(a) |= 0x80; else signbyte(a) &= 0x7f; }
+#define copysign(a,b) { if (getsign(a)) signbyte(b) |= 0x80; \
+                        else signbyte(b) &= 0x7f; }
+#define changesign(a) { signbyte(a) ^= 0x80; }
+#define setpositive(a) { signbyte(a) &= 0x7f; }
+#define setnegative(a) { signbyte(a) |= 0x80; }
+#define signpositive(a) ( (signbyte(a) & 0x80) == 0 )
+#define signnegative(a) (signbyte(a) & 0x80)
+
+static inline void reg_copy(FPU_REG const *x, FPU_REG *y)
+{
+  *(short *)&(y->exp) = *(const short *)&(x->exp); 
+  *(long long *)&(y->sigl) = *(const long long *)&(x->sigl);
+}
+
+#define exponent(x)  (((*(short *)&((x)->exp)) & 0x7fff) - EXTENDED_Ebias)
+#define setexponentpos(x,y) { (*(short *)&((x)->exp)) = \
+  ((y) + EXTENDED_Ebias) & 0x7fff; }
+#define exponent16(x)         (*(short *)&((x)->exp))
+#define setexponent16(x,y)  { (*(short *)&((x)->exp)) = (y); }
+#define addexponent(x,y)    { (*(short *)&((x)->exp)) += (y); }
+#define stdexp(x)           { (*(short *)&((x)->exp)) += EXTENDED_Ebias; }
 
-#define reg_move(x, y) { \
-		 *(short *)&((y)->sign) = *(const short *)&((x)->sign); \
-		 *(long *)&((y)->exp) = *(const long *)&((x)->exp); \
-		 *(long long *)&((y)->sigl) = *(const long long *)&((x)->sigl); }
+#define isdenormal(ptr)   (exponent(ptr) == EXP_BIAS+EXP_UNDER)
 
 #define significand(x) ( ((unsigned long long *)&((x)->sigl))[0] )
 
@@ -145,29 +187,31 @@
 /*----- Prototypes for functions written in assembler -----*/
 /* extern void reg_move(FPU_REG *a, FPU_REG *b); */
 
-asmlinkage void normalize(FPU_REG *x);
-asmlinkage void normalize_nuo(FPU_REG *x);
-asmlinkage int reg_div(FPU_REG const *arg1, FPU_REG const *arg2,
-		       FPU_REG *answ, unsigned int control_w);
-asmlinkage int reg_u_sub(FPU_REG const *arg1, FPU_REG const *arg2,
-			 FPU_REG *answ, unsigned int control_w);
-asmlinkage int reg_u_mul(FPU_REG const *arg1, FPU_REG const *arg2,
-			 FPU_REG *answ, unsigned int control_w);
-asmlinkage int reg_u_div(FPU_REG const *arg1, FPU_REG const *arg2,
-			 FPU_REG *answ, unsigned int control_w);
-asmlinkage int reg_u_add(FPU_REG const *arg1, FPU_REG const *arg2,
-			 FPU_REG *answ, unsigned int control_w);
-asmlinkage int wm_sqrt(FPU_REG *n, unsigned int control_w);
-asmlinkage unsigned	shrx(void *l, unsigned x);
-asmlinkage unsigned	shrxs(void *v, unsigned x);
-asmlinkage unsigned long div_small(unsigned long long *x, unsigned long y);
-asmlinkage void round_reg(FPU_REG *arg, unsigned int extent,
-		      unsigned int control_w);
+asmlinkage int FPU_normalize(FPU_REG *x, int sign);
+asmlinkage int FPU_normalize_nuo(FPU_REG *x);
+asmlinkage int FPU_u_sub(FPU_REG const *arg1, FPU_REG const *arg2,
+			 FPU_REG *answ, unsigned int control_w, u_char sign,
+			 int expa, int expb);
+asmlinkage int FPU_u_mul(FPU_REG const *arg1, FPU_REG const *arg2,
+			 FPU_REG *answ, unsigned int control_w, u_char sign,
+			 int expon);
+asmlinkage int FPU_u_div(FPU_REG const *arg1, FPU_REG const *arg2,
+			 FPU_REG *answ, unsigned int control_w, u_char sign);
+asmlinkage int FPU_u_add(FPU_REG const *arg1, FPU_REG const *arg2,
+			 FPU_REG *answ, unsigned int control_w, u_char sign,
+			 int expa, int expb);
+asmlinkage int wm_sqrt(FPU_REG *n, int dummy1, int dummy2,
+		       unsigned int control_w, u_char sign);
+asmlinkage unsigned	FPU_shrx(void *l, unsigned x);
+asmlinkage unsigned	FPU_shrxs(void *v, unsigned x);
+asmlinkage unsigned long FPU_div_small(unsigned long long *x, unsigned long y);
+asmlinkage int FPU_round(FPU_REG *arg, unsigned int extent, int dummy,
+			 unsigned int control_w, u_char sign);
 
 #ifndef MAKING_PROTO
 #include "fpu_proto.h"
 #endif
 
-#endif __ASSEMBLY__
+#endif /* __ASSEMBLY__ */
 
-#endif _FPU_EMU_H_
+#endif /* _FPU_EMU_H_ */
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/fpu_entry.c linux-2.0.40/arch/i386/math-emu/fpu_entry.c
--- linux-2.0.39/arch/i386/math-emu/fpu_entry.c	Mon May  6 15:31:17 1996
+++ linux-2.0.40/arch/i386/math-emu/fpu_entry.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  | The entry functions for wm-FPU-emu                                        |
  |                                                                           |
- | Copyright (C) 1992,1993,1994,1996                                         |
+ | Copyright (C) 1992,1993,1994,1996,1997,2001                               |
  |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
- |                  E-mail   billm@jacobi.maths.monash.edu.au                |
+ |                  E-mail   billm@suburbia.net                              |
  |                                                                           |
  | See the files "README" and "COPYING" for further copyright and warranty   |
  | information.                                                              |
@@ -26,8 +26,6 @@
 
 #include <linux/signal.h>
 
-#include <asm/segment.h>
-
 #include "fpu_system.h"
 #include "fpu_emu.h"
 #include "exception.h"
@@ -36,6 +34,19 @@
 
 #define __BAD__ FPU_illegal   /* Illegal on an 80486, causes SIGILL */
 
+#ifdef ONLY_486_FPU
+#define fcmovnb  __BAD__   /* Not present on 80486 */
+#define fcmovne  __BAD__   /* Not present on 80486 */
+#define fcmovnbe __BAD__   /* Not present on 80486 */
+#define fcmovnu  __BAD__   /* Not present on 80486 */
+#define fcmovb   __BAD__   /* Not present on 80486 */
+#define fcmove   __BAD__   /* Not present on 80486 */
+#define fcmovbe  __BAD__   /* Not present on 80486 */
+#define fcmovu   __BAD__   /* Not present on 80486 */
+#define fucomi   __BAD__   /* Not present on 80486 */
+#define fcomi    __BAD__   /* Not present on 80486 */
+#endif
+
 #ifndef NO_UNDOC_CODE    /* Un-documented FPU op-codes supported by default. */
 
 /* WARNING: These codes are not documented by Intel in their 80486 manual
@@ -54,30 +65,30 @@
 #define _df_d8_ fstp_i    /* unofficial code (1f) */
 
 static FUNC const st_instr_table[64] = {
-  fadd__,   fld_i_,  __BAD__, __BAD__, fadd_i,  ffree_,  faddp_,  _df_c0_,
-  fmul__,   fxch_i,  __BAD__, __BAD__, fmul_i,  _dd_c8_, fmulp_,  _df_c8_,
-  fcom_st,  fp_nop,  __BAD__, __BAD__, _dc_d0_, fst_i_,  _de_d0_, _df_d0_,
-  fcompst,  _d9_d8_, __BAD__, __BAD__, _dc_d8_, fstp_i,  fcompp,  _df_d8_,
-  fsub__,   fp_etc,  __BAD__, finit_,  fsubri,  fucom_,  fsubrp,  fstsw_,
-  fsubr_,   fconst,  fucompp, __BAD__, fsub_i,  fucomp,  fsubp_,  __BAD__,
-  fdiv__,   trig_a,  __BAD__, __BAD__, fdivri,  __BAD__, fdivrp,  __BAD__,
-  fdivr_,   trig_b,  __BAD__, __BAD__, fdiv_i,  __BAD__, fdivp_,  __BAD__,
+  fadd__,   fld_i_,     fcmovb,  fcmovnb,  fadd_i,  ffree_,  faddp_,  _df_c0_,
+  fmul__,   fxch_i,     fcmove,  fcmovne,  fmul_i,  _dd_c8_, fmulp_,  _df_c8_,
+  fcom_st,  fp_nop,     fcmovbe, fcmovnbe, _dc_d0_, fst_i_,  _de_d0_, _df_d0_,
+  fcompst,  _d9_d8_,    fcmovu,  fcmovnu,  _dc_d8_, fstp_i,  fcompp,  _df_d8_,
+  fsub__,   FPU_etc,    __BAD__, finit_,   fsubri,  fucom_,  fsubrp,  fstsw_,
+  fsubr_,   fconst,     fucompp, fucomi,   fsub_i,  fucomp,  fsubp_,  __BAD__,
+  fdiv__,   FPU_triga,  __BAD__, fcomi,    fdivri,  __BAD__, fdivrp,  __BAD__,
+  fdivr_,   FPU_trigb,  __BAD__, __BAD__,  fdiv_i,  __BAD__, fdivp_,  __BAD__,
 };
 
 #else     /* Support only documented FPU op-codes */
 
 static FUNC const st_instr_table[64] = {
-  fadd__,   fld_i_,  __BAD__, __BAD__, fadd_i,  ffree_,  faddp_,  __BAD__,
-  fmul__,   fxch_i,  __BAD__, __BAD__, fmul_i,  __BAD__, fmulp_,  __BAD__,
-  fcom_st,  fp_nop,  __BAD__, __BAD__, __BAD__, fst_i_,  __BAD__, __BAD__,
-  fcompst,  __BAD__, __BAD__, __BAD__, __BAD__, fstp_i,  fcompp,  __BAD__,
-  fsub__,   fp_etc,  __BAD__, finit_,  fsubri,  fucom_,  fsubrp,  fstsw_,
-  fsubr_,   fconst,  fucompp, __BAD__, fsub_i,  fucomp,  fsubp_,  __BAD__,
-  fdiv__,   trig_a,  __BAD__, __BAD__, fdivri,  __BAD__, fdivrp,  __BAD__,
-  fdivr_,   trig_b,  __BAD__, __BAD__, fdiv_i,  __BAD__, fdivp_,  __BAD__,
+  fadd__,   fld_i_,     fcmovb,  fcmovnb,  fadd_i,  ffree_,  faddp_,  __BAD__,
+  fmul__,   fxch_i,     fcmove,  fcmovne,  fmul_i,  __BAD__, fmulp_,  __BAD__,
+  fcom_st,  fp_nop,     fcmovbe, fcmovnbe, __BAD__, fst_i_,  __BAD__, __BAD__,
+  fcompst,  __BAD__,    fcmovu,  fcmovnu,  __BAD__, fstp_i,  fcompp,  __BAD__,
+  fsub__,   FPU_etc,    __BAD__, finit_,   fsubri,  fucom_,  fsubrp,  fstsw_,
+  fsubr_,   fconst,     fucompp, fucomi,   fsub_i,  fucomp,  fsubp_,  __BAD__,
+  fdiv__,   FPU_triga,  __BAD__, fcomi,    fdivri,  __BAD__, fdivrp,  __BAD__,
+  fdivr_,   FPU_trigb,  __BAD__, __BAD__,  fdiv_i,  __BAD__, fdivp_,  __BAD__,
 };
 
-#endif NO_UNDOC_CODE
+#endif /* NO_UNDOC_CODE */
 
 
 #define _NONE_ 0   /* Take no special action */
@@ -95,54 +106,54 @@
 
 /* Un-documented FPU op-codes supported by default. (see above) */
 
-static unsigned char const type_table[64] = {
-  _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _REGi_,
-  _REGI_, _REGIn, _null_, _null_, _REGIi, _REGI_, _REGIp, _REGI_,
-  _REGIc, _NONE_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
-  _REGIc, _REG0_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
+static u_char const type_table[64] = {
+  _REGI_, _NONE_, _REGi_, _REGi_, _REGIi, _REGi_, _REGIp, _REGi_,
+  _REGI_, _REGIn, _REGi_, _REGi_, _REGIi, _REGI_, _REGIp, _REGI_,
+  _REGIc, _NONE_, _REGi_, _REGi_, _REGIc, _REG0_, _REGIc, _REG0_,
+  _REGIc, _REG0_, _REGi_, _REGi_, _REGIc, _REG0_, _REGIc, _REG0_,
   _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
-  _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
-  _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
+  _REGI_, _NONE_, _REGIc, _REGIc, _REGIi, _REGIc, _REGIp, _null_,
+  _REGI_, _NONE_, _null_, _REGIc, _REGIi, _null_, _REGIp, _null_,
   _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
 };
 
 #else     /* Support only documented FPU op-codes */
 
-static unsigned char const type_table[64] = {
-  _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _null_,
-  _REGI_, _REGIn, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
-  _REGIc, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_,
-  _REGIc, _null_, _null_, _null_, _null_, _REG0_, _REGIc, _null_,
+static u_char const type_table[64] = {
+  _REGI_, _NONE_, _REGi_, _REGi_, _REGIi, _REGi_, _REGIp, _null_,
+  _REGI_, _REGIn, _REGi_, _REGi_, _REGIi, _null_, _REGIp, _null_,
+  _REGIc, _NONE_, _REGi_, _REGi_, _null_, _REG0_, _null_, _null_,
+  _REGIc, _null_, _REGi_, _REGi_, _null_, _REG0_, _REGIc, _null_,
   _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
-  _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
-  _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
+  _REGI_, _NONE_, _REGIc, _REGIc, _REGIi, _REGIc, _REGIp, _null_,
+  _REGI_, _NONE_, _null_, _REGIc, _REGIi, _null_, _REGIp, _null_,
   _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
 };
 
-#endif NO_UNDOC_CODE
+#endif /* NO_UNDOC_CODE */
 
 
 #ifdef RE_ENTRANT_CHECKING
-char emulating=0;
-#endif RE_ENTRANT_CHECKING
+u_char emulating=0;
+#endif /* RE_ENTRANT_CHECKING */
 
-static int valid_prefix(unsigned char *Byte, unsigned char **fpu_eip,
+static int valid_prefix(u_char *Byte, u_char **fpu_eip,
 			overrides *override);
 
 asmlinkage void math_emulate(long arg)
 {
-  unsigned char  FPU_modrm, byte1;
+  u_char  FPU_modrm, byte1;
   unsigned short code;
   fpu_addr_modes addr_modes;
   int unmasked;
   FPU_REG loaded_data;
+  FPU_REG *st0_ptr;
+  u_char	  loaded_tag, st0_tag;
   void *data_address;
   struct address data_sel_off;
   struct address entry_sel_off;
   unsigned long code_base = 0;
   unsigned long code_limit = 0;  /* Initialized to stop compiler warnings */
-  char	       st0_tag;
-  FPU_REG      *st0_ptr;
   struct desc_struct code_descriptor;
 
 #ifdef RE_ENTRANT_CHECKING
@@ -151,21 +162,12 @@
       printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
     }
   RE_ENTRANT_CHECK_ON;
-#endif RE_ENTRANT_CHECKING
+#endif /* RE_ENTRANT_CHECKING */
 
-  if (!current->used_math)
+  if (!FPU_current->used_math)
     {
-      int i;
-      for ( i = 0; i < 8; i++ )
-	{
-	  /* Make sure that the registers are compatible
-	     with the assumptions of the emulator. */
-	  if ( !((regs[i].exp == EXP_UNDER) && (regs[i].sigh == 0)
-		 && (regs[i].sigl == 0)) )
-	    regs[i].sigh |= 0x80000000;
-	}
       finit();
-      current->used_math = 1;
+      FPU_current->used_math = 1;
     }
 
   SETUP_DATA_AREA(arg);
@@ -179,11 +181,11 @@
       FPU_EIP += code_base = FPU_CS << 4;
       code_limit = code_base + 0xffff;  /* Assumes code_base <= 0xffff0000 */
     }
-  else if ( FPU_CS == USER_CS && FPU_DS == USER_DS )
+  else if ( FPU_CS == FPU_USER_CS && FPU_DS == FPU_USER_DS )
     {
       addr_modes.default_mode = 0;
     }
-  else if ( FPU_CS == KERNEL_CS )
+  else if ( FPU_CS == FPU_KERNEL_CS )
     {
       printk("math_emulate: %04x:%08lx\n",FPU_CS,FPU_EIP);
       panic("Math emulation needed in kernel");
@@ -196,7 +198,7 @@
 	  /* Can only handle segmented addressing via the LDT
 	     for now, and it must be 16 bit */
 	  printk("FPU emulator: Unsupported addressing mode\n");
-	  math_abort(FPU_info, SIGILL);
+	  math_abort(SIGILL);
 	}
 
       if ( SEG_D_SIZE(code_descriptor = LDT_DESCRIPTOR(FPU_CS)) )
@@ -218,10 +220,10 @@
     }
 
   FPU_lookahead = 1;
-  if (current->flags & PF_PTRACED)
+  if ( FPU_TRACING )
     FPU_lookahead = 0;
 
-  if ( !valid_prefix(&byte1, (unsigned char **)&FPU_EIP,
+  if ( !valid_prefix(&byte1, (u_char **)&FPU_EIP,
 		     &addr_modes.override) )
     {
       RE_ENTRANT_CHECK_OFF;
@@ -230,7 +232,7 @@
 	     byte1);
       RE_ENTRANT_CHECK_ON;
       EXCEPTION(EX_INTERNAL|0x126);
-      math_abort(FPU_info,SIGILL);
+      math_abort(SIGILL);
     }
 
 do_another_FPU_instruction:
@@ -244,7 +246,7 @@
       /* This checks for the minimum instruction bytes.
 	 We also need to check any extra (address mode) code access. */
       if ( FPU_EIP > code_limit )
-	math_abort(FPU_info,SIGSEGV);
+	math_abort(SIGSEGV);
     }
 
   if ( (byte1 & 0xf8) != 0xd8 )
@@ -258,13 +260,13 @@
 	}
 #ifdef PARANOID
       EXCEPTION(EX_INTERNAL|0x128);
-      math_abort(FPU_info,SIGILL);
-#endif PARANOID
+      math_abort(SIGILL);
+#endif /* PARANOID */
     }
 
   RE_ENTRANT_CHECK_OFF;
   FPU_code_verify_area(1);
-  FPU_modrm = get_fs_byte((unsigned char *) FPU_EIP);
+  FPU_get_user(FPU_modrm, (u_char *) FPU_EIP);
   RE_ENTRANT_CHECK_ON;
   FPU_EIP++;
 
@@ -287,12 +289,11 @@
 	   *  interrupts here.
 	   */
 	do_the_FPU_interrupt:
+
 	  FPU_EIP = FPU_ORIG_EIP;	/* Point to current FPU instruction. */
 
 	  RE_ENTRANT_CHECK_OFF;
-	  current->tss.trap_no = 16;
-	  current->tss.error_code = 0;
-	  send_sig(SIGFPE, current, 1);
+	  FPU_SEND_SIGNAL(SIGFPE);
 	  return;
 	}
     }
@@ -309,16 +310,16 @@
 
       if ( (addr_modes.default_mode & SIXTEEN)
 	  ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX) )
-	data_address = get_address_16(FPU_modrm, &FPU_EIP, &data_sel_off,
-				      addr_modes);
+	data_address = FPU_get_address_16(FPU_modrm, &FPU_EIP, &data_sel_off,
+					  addr_modes);
       else
-	data_address = get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
-				   addr_modes);
+	data_address = FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
+				       addr_modes);
 
       if ( addr_modes.default_mode )
 	{
 	  if ( FPU_EIP-1 > code_limit )
-	    math_abort(FPU_info,SIGSEGV);
+	    math_abort(SIGSEGV);
 	}
 
       if ( !(byte1 & 1) )
@@ -326,7 +327,7 @@
 	  unsigned short status1 = partial_status;
 
 	  st0_ptr = &st(0);
-	  st0_tag = st0_ptr->tag;
+	  st0_tag = FPU_gettag0();
 
 	  /* Stack underflow has priority */
 	  if ( NOT_EMPTY_ST0 )
@@ -335,36 +336,41 @@
 		{
 		  /* This table works for 16 and 32 bit protected mode */
 		  if ( access_limit < data_sizes_16[(byte1 >> 1) & 3] )
-		    math_abort(FPU_info,SIGSEGV);
+		    math_abort(SIGSEGV);
 		}
 
 	      unmasked = 0;  /* Do this here to stop compiler warnings. */
 	      switch ( (byte1 >> 1) & 3 )
 		{
 		case 0:
-		  unmasked = reg_load_single((float *)data_address,
+		  unmasked = FPU_load_single((float *)data_address,
 					     &loaded_data);
+		  loaded_tag = unmasked & 0xff;
+		  unmasked &= ~0xff;
 		  break;
 		case 1:
-		  reg_load_int32((long *)data_address, &loaded_data);
+		  loaded_tag = FPU_load_int32((long *)data_address, &loaded_data);
 		  break;
 		case 2:
-		  unmasked = reg_load_double((double *)data_address,
+		  unmasked = FPU_load_double((double *)data_address,
 					     &loaded_data);
+		  loaded_tag = unmasked & 0xff;
+		  unmasked &= ~0xff;
 		  break;
 		case 3:
-		  reg_load_int16((short *)data_address, &loaded_data);
+		default:  /* Used here to suppress gcc warnings. */
+		  loaded_tag = FPU_load_int16((short *)data_address, &loaded_data);
 		  break;
 		}
-	      
+
 	      /* No more access to user memory, it is safe
 		 to use static data now */
 
 	      /* NaN operands have the next priority. */
 	      /* We have to delay looking at st(0) until after
 		 loading the data, because that data might contain an SNaN */
-	      if ( (st0_tag == TW_NaN) ||
-		  (loaded_data.tag == TW_NaN) )
+	      if ( ((st0_tag == TAG_Special) && isNaN(st0_ptr)) ||
+		  ((loaded_tag == TAG_Special) && isNaN(&loaded_data)) )
 		{
 		  /* Restore the status word; we might have loaded a
 		     denormal. */
@@ -375,22 +381,22 @@
 		      EXCEPTION(EX_Invalid);
 		      setcc(SW_C3 | SW_C2 | SW_C0);
 		      if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
-			pop();             /* fcomp, masked, so we pop. */
+			FPU_pop();             /* fcomp, masked, so we pop. */
 		    }
 		  else
 		    {
+		      if ( loaded_tag == TAG_Special )
+			loaded_tag = FPU_Special(&loaded_data);
 #ifdef PECULIAR_486
 		      /* This is not really needed, but gives behaviour
 			 identical to an 80486 */
 		      if ( (FPU_modrm & 0x28) == 0x20 )
 			/* fdiv or fsub */
-			real_2op_NaN(&loaded_data, st0_ptr,
-				     st0_ptr);
+			real_2op_NaN(&loaded_data, loaded_tag, 0, &loaded_data);
 		      else
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */ 
 			/* fadd, fdivr, fmul, or fsubr */
-			real_2op_NaN(st0_ptr, &loaded_data,
-				     st0_ptr);
+			real_2op_NaN(&loaded_data, loaded_tag, 0, st0_ptr);
 		    }
 		  goto reg_mem_instr_done;
 		}
@@ -401,11 +407,13 @@
 		  if ( (FPU_modrm & 0x38) == 0x38 )
 		    {
 		      /* fdivr */
-		      if ( (st0_tag == TW_Zero) &&
-			  (loaded_data.tag == TW_Valid) )
+		      if ( (st0_tag == TAG_Zero) &&
+			   ((loaded_tag == TAG_Valid)
+			    || (loaded_tag == TAG_Special
+				&& isdenormal(&loaded_data))) )
 			{
-			  if ( divide_by_zero(loaded_data.sign,
-					      st0_ptr) )
+			  if ( FPU_divide_by_zero(0, getsign(&loaded_data))
+			       < 0 )
 			    {
 			      /* We use the fact here that the unmasked
 				 exception in the loaded data was for a
@@ -414,6 +422,8 @@
 			      partial_status &= ~SW_Denorm_Op;
 			      partial_status |= status1 & SW_Denorm_Op;
 			    }
+			  else
+			    setsign(st0_ptr, getsign(&loaded_data));
 			}
 		    }
 		  goto reg_mem_instr_done;
@@ -423,43 +433,38 @@
 		{
 		case 0:         /* fadd */
 		  clear_C1();
-		  reg_add(st0_ptr, &loaded_data, st0_ptr,
-			  control_word);
+		  FPU_add(&loaded_data, loaded_tag, 0, control_word);
 		  break;
 		case 1:         /* fmul */
 		  clear_C1();
-		  reg_mul(st0_ptr, &loaded_data, st0_ptr,
-			  control_word);
+		  FPU_mul(&loaded_data, loaded_tag, 0, control_word);
 		  break;
 		case 2:         /* fcom */
-		  compare_st_data(&loaded_data);
+		  FPU_compare_st_data(&loaded_data, loaded_tag);
 		  break;
 		case 3:         /* fcomp */
-		  if ( !compare_st_data(&loaded_data) && !unmasked )
-		    pop();
+		  if ( !FPU_compare_st_data(&loaded_data, loaded_tag)
+		       && !unmasked )
+		    FPU_pop();
 		  break;
 		case 4:         /* fsub */
 		  clear_C1();
-		  reg_sub(st0_ptr, &loaded_data, st0_ptr,
-			  control_word);
+		  FPU_sub(LOADED|loaded_tag, (int)&loaded_data, control_word);
 		  break;
 		case 5:         /* fsubr */
 		  clear_C1();
-		  reg_sub(&loaded_data, st0_ptr, st0_ptr,
-			  control_word);
+		  FPU_sub(REV|LOADED|loaded_tag, (int)&loaded_data, control_word);
 		  break;
 		case 6:         /* fdiv */
 		  clear_C1();
-		  reg_div(st0_ptr, &loaded_data, st0_ptr,
-			  control_word);
+		  FPU_div(LOADED|loaded_tag, (int)&loaded_data, control_word);
 		  break;
 		case 7:         /* fdivr */
 		  clear_C1();
-		  if ( st0_tag == TW_Zero )
+		  if ( st0_tag == TAG_Zero )
 		    partial_status = status1;  /* Undo any denorm tag,
-					       zero-divide has priority. */
-		  reg_div(&loaded_data, st0_ptr, st0_ptr,
-			  control_word);
+						  zero-divide has priority. */
+		  FPU_div(REV|LOADED|loaded_tag, (int)&loaded_data, control_word);
 		  break;
 		}
 	    }
@@ -471,10 +476,10 @@
 		  EXCEPTION(EX_StackUnder);
 		  setcc(SW_C3 | SW_C2 | SW_C0);
 		  if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
-		    pop();             /* fcomp */
+		    FPU_pop();             /* fcomp */
 		}
 	      else
-		stack_underflow();
+		FPU_stack_underflow();
 	    }
 	reg_mem_instr_done:
 	  operand_address = data_sel_off;
@@ -482,8 +487,8 @@
       else
 	{
 	  if ( !(no_ip_update =
-		 load_store_instr(((FPU_modrm & 0x38) | (byte1 & 6)) >> 1,
-				  addr_modes, data_address)) )
+		 FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6)) >> 1,
+				addr_modes, data_address)) )
 	    {
 	      operand_address = data_sel_off;
 	    }
@@ -493,17 +498,17 @@
   else
     {
       /* None of these instructions access user memory */
-      unsigned char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
+      u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
 
 #ifdef PECULIAR_486
       /* This is supposed to be undefined, but a real 80486 seems
 	 to do this: */
       operand_address.offset = 0;
       operand_address.selector = FPU_DS;
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 
       st0_ptr = &st(0);
-      st0_tag = st0_ptr->tag;
+      st0_tag = FPU_gettag0();
       switch ( type_table[(int) instr_index] )
 	{
 	case _NONE_:   /* also _REGIc: _REGIn */
@@ -511,28 +516,28 @@
 	case _REG0_:
 	  if ( !NOT_EMPTY_ST0 )
 	    {
-	      stack_underflow();
+	      FPU_stack_underflow();
 	      goto FPU_instruction_done;
 	    }
 	  break;
 	case _REGIi:
 	  if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
 	    {
-	      stack_underflow_i(FPU_rm);
+	      FPU_stack_underflow_i(FPU_rm);
 	      goto FPU_instruction_done;
 	    }
 	  break;
 	case _REGIp:
 	  if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
 	    {
-	      stack_underflow_pop(FPU_rm);
+	      FPU_stack_underflow_pop(FPU_rm);
 	      goto FPU_instruction_done;
 	    }
 	  break;
 	case _REGI_:
 	  if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
 	    {
-	      stack_underflow();
+	      FPU_stack_underflow();
 	      goto FPU_instruction_done;
 	    }
 	  break;
@@ -558,14 +563,14 @@
 
 #ifdef DEBUG
   RE_ENTRANT_CHECK_OFF;
-  emu_printall();
+  FPU_printall();
   RE_ENTRANT_CHECK_ON;
-#endif DEBUG
+#endif /* DEBUG */
 
-  if (FPU_lookahead && !need_resched)
+  if (FPU_lookahead && !FPU_need_resched)
     {
       FPU_ORIG_EIP = FPU_EIP - code_base;
-      if ( valid_prefix(&byte1, (unsigned char **)&FPU_EIP,
+      if ( valid_prefix(&byte1, (u_char **)&FPU_EIP,
 			&addr_modes.override) )
 	goto do_another_FPU_instruction;
     }
@@ -581,17 +586,17 @@
    all prefix bytes, further changes are needed in the emulator code
    which accesses user address space. Access to separate segments is
    important for msdos emulation. */
-static int valid_prefix(unsigned char *Byte, unsigned char **fpu_eip,
+static int valid_prefix(u_char *Byte, u_char **fpu_eip,
 			overrides *override)
 {
-  unsigned char byte;
-  unsigned char *ip = *fpu_eip;
+  u_char byte;
+  u_char *ip = *fpu_eip;
 
   *override = (overrides) { 0, 0, PREFIX_DEFAULT };       /* defaults */
 
   RE_ENTRANT_CHECK_OFF;
-  FPU_code_verify_area(1);
-  byte = get_fs_byte(ip);
+  FPU_verify_area(VERIFY_READ,ip,1);
+  FPU_get_user(byte, ip);
   RE_ENTRANT_CHECK_ON;
 
   while ( 1 )
@@ -636,8 +641,8 @@
 	do_next_byte:
 	  ip++;
 	  RE_ENTRANT_CHECK_OFF;
-	  FPU_code_verify_area(1);
-	  byte = get_fs_byte(ip);
+	  FPU_verify_area(VERIFY_READ,ip,1);
+	  FPU_get_user(byte, ip);
 	  RE_ENTRANT_CHECK_ON;
 	  break;
 	case FWAIT_OPCODE:
@@ -662,34 +667,100 @@
 }
 
 
-void math_abort(struct info * info, unsigned int signal)
+void math_abort(unsigned int signal)
 {
-	FPU_EIP = FPU_ORIG_EIP;
-	current->tss.trap_no = 16;
-	current->tss.error_code = 0;
-	send_sig(signal,current,1);
-	RE_ENTRANT_CHECK_OFF;
-	__asm__("movl %0,%%esp ; ret": :"g" (((long) info)-4));
+  FPU_EIP = FPU_ORIG_EIP;
+  FPU_SEND_SIGNAL(signal);
+  RE_ENTRANT_CHECK_OFF;
+  FPU_EXIT;
 #ifdef PARANOID
-      printk("ERROR: wm-FPU-emu math_abort failed!\n");
-#endif PARANOID
+  printk("ERROR: wm-FPU-emu math_abort failed!\n");
+#endif /* PARANOID */
 }
 
 
 
-void restore_i387_soft(struct _fpstate *buf)
+#define S387 ((struct i387_soft_struct *)s387)
+#define FPU_s_top	S387->ftop
+#define FPU_s_regs	S387->st_space
+#define sstatus_word() \
+  ((S387->swd & ~SW_Top & 0xffff) | ((FPU_s_top << SW_Top_Shift) & SW_Top))
+
+int restore_i387_soft(void *s387, struct _fpstate *buf)
 {
-  fpu_addr_modes addr_modes = {{ 0, 0, PREFIX_DEFAULT }, 0};
+  u_char *d = (u_char *)buf;
+  int offset, other, i, tags, regnr, tag, newtop;
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_READ, d, 7*4 + 8*10);
+  if (FPU_copy_from_user(&S387->cwd, d, 7*4))
+    return -1;
+  RE_ENTRANT_CHECK_ON;
 
-  frstor(addr_modes, (char *)buf);
+  d += 7*4;
+
+  FPU_s_top = (S387->swd >> SW_Top_Shift) & 7;
+  offset = (FPU_s_top & 7) * 10;
+  other = 80 - offset;
+
+  RE_ENTRANT_CHECK_OFF;
+  /* Copy all registers in stack order. */
+  if (FPU_copy_from_user(((u_char *)&FPU_s_regs)+offset, d, other))
+    return -1;
+  if ( offset )
+    if (FPU_copy_from_user((u_char *)&FPU_s_regs, d+other, offset))
+      return -1;
+  RE_ENTRANT_CHECK_ON;
+
+  /* The tags may need to be corrected now. */
+  tags = S387->twd;
+  newtop = FPU_s_top;
+  for ( i = 0; i < 8; i++ )
+    {
+      regnr = (i+newtop) & 7;
+      if ( ((tags >> ((regnr & 7)*2)) & 3) != TAG_Empty )
+	{
+	  /* The loaded data over-rides all other cases. */
+	  tag = FPU_tagof((FPU_REG *)((u_char *)FPU_s_regs + 10*regnr));
+	  tags &= ~(3 << (regnr*2));
+	  tags |= (tag & 3) << (regnr*2);
+	}
+    }
+  S387->twd = tags;
+
+  return 0;
 }
 
 
-struct _fpstate * save_i387_soft(struct _fpstate * buf)
+int save_i387_soft(void *s387, struct _fpstate * buf)
 {
-  fpu_addr_modes addr_modes = {{ 0, 0, PREFIX_DEFAULT }, 0};
+  u_char *d = (u_char *)buf;
+  int offset = (FPU_s_top & 7) * 10, other = 80 - offset;
 
-  fsave(addr_modes, (char *)buf);
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_WRITE, d, 7*4 + 8*10);
+#ifdef PECULIAR_486
+  S387->cwd &= ~0xe080;
+  /* An 80486 sets nearly all of the reserved bits to 1. */
+  S387->cwd |= 0xffff0040;
+  S387->swd = sstatus_word() | 0xffff0000;
+  S387->twd |= 0xffff0000;
+  S387->fcs &= ~0xf8000000;
+  S387->fos |= 0xffff0000;
+#endif /* PECULIAR_486 */
+  FPU_copy_to_user(d, &S387->cwd, 7*4);
+  RE_ENTRANT_CHECK_ON;
+
+  d += 7*4;
+
+  RE_ENTRANT_CHECK_OFF;
+  /* Copy all registers in stack order. */
+  if (FPU_copy_to_user(d, ((u_char *)&FPU_s_regs)+offset, other))
+    return -1;
+  if ( offset )
+    if (FPU_copy_to_user(d+other, (u_char *)&FPU_s_regs, offset))
+      return -1
+  RE_ENTRANT_CHECK_ON;
 
-  return buf;
+  return 1;
 }
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/fpu_etc.c linux-2.0.40/arch/i386/math-emu/fpu_etc.c
--- linux-2.0.39/arch/i386/math-emu/fpu_etc.c	Fri Aug 19 07:54:01 1994
+++ linux-2.0.40/arch/i386/math-emu/fpu_etc.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  | Implement a few FPU instructions.                                         |
  |                                                                           |
- | Copyright (C) 1992,1993,1994                                              |
+ | Copyright (C) 1992,1993,1994,1997                                         |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                       Australia.  E-mail   billm@suburbia.net             |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -17,102 +17,116 @@
 #include "reg_constant.h"
 
 
-static void fchs(FPU_REG *st0_ptr)
+static void fchs(FPU_REG *st0_ptr, u_char st0tag)
 {
-  if ( st0_ptr->tag ^ TW_Empty )
+  if ( st0tag ^ TAG_Empty )
     {
-      st0_ptr->sign ^= SIGN_POS^SIGN_NEG;
+      signbyte(st0_ptr) ^= SIGN_NEG;
       clear_C1();
     }
   else
-    stack_underflow();
+    FPU_stack_underflow();
 }
 
-static void fabs(FPU_REG *st0_ptr)
+
+static void fabs(FPU_REG *st0_ptr, u_char st0tag)
 {
-  if ( st0_ptr->tag ^ TW_Empty )
+  if ( st0tag ^ TAG_Empty )
     {
-      st0_ptr->sign = SIGN_POS;
+      setpositive(st0_ptr);
       clear_C1();
     }
   else
-    stack_underflow();
+    FPU_stack_underflow();
 }
 
 
-static void ftst_(FPU_REG *st0_ptr)
+static void ftst_(FPU_REG *st0_ptr, u_char st0tag)
 {
-  switch (st0_ptr->tag)
+  switch (st0tag)
     {
-    case TW_Zero:
+    case TAG_Zero:
       setcc(SW_C3);
       break;
-    case TW_Valid:
-      if (st0_ptr->sign == SIGN_POS)
+    case TAG_Valid:
+      if (getsign(st0_ptr) == SIGN_POS)
         setcc(0);
       else
         setcc(SW_C0);
-
-#ifdef DENORM_OPERAND
-      if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+      break;
+    case TAG_Special:
+      switch ( FPU_Special(st0_ptr) )
 	{
+	case TW_Denormal:
+	  if (getsign(st0_ptr) == SIGN_POS)
+	    setcc(0);
+	  else
+	    setcc(SW_C0);
+	  if ( denormal_operand() < 0 )
+	    {
 #ifdef PECULIAR_486
-	  /* This is weird! */
-	  if (st0_ptr->sign == SIGN_POS)
-	    setcc(SW_C3);
-#endif PECULIAR_486
-	  return;
+	      /* This is weird! */
+	      if (getsign(st0_ptr) == SIGN_POS)
+		setcc(SW_C3);
+#endif /* PECULIAR_486 */
+	      return;
+	    }
+	  break;
+	case TW_NaN:
+	  setcc(SW_C0|SW_C2|SW_C3);   /* Operand is not comparable */ 
+	  EXCEPTION(EX_Invalid);
+	  break;
+	case TW_Infinity:
+	  if (getsign(st0_ptr) == SIGN_POS)
+	    setcc(0);
+	  else
+	    setcc(SW_C0);
+	  break;
+	default:
+	  setcc(SW_C0|SW_C2|SW_C3);   /* Operand is not comparable */ 
+	  EXCEPTION(EX_INTERNAL|0x14);
+	  break;
 	}
-#endif DENORM_OPERAND
-
-      break;
-    case TW_NaN:
-      setcc(SW_C0|SW_C2|SW_C3);   /* Operand is not comparable */ 
-      EXCEPTION(EX_Invalid);
-      break;
-    case TW_Infinity:
-      if (st0_ptr->sign == SIGN_POS)
-        setcc(0);
-      else
-        setcc(SW_C0);
       break;
-    case TW_Empty:
+    case TAG_Empty:
       setcc(SW_C0|SW_C2|SW_C3);
       EXCEPTION(EX_StackUnder);
       break;
-    default:
-      setcc(SW_C0|SW_C2|SW_C3);   /* Operand is not comparable */ 
-      EXCEPTION(EX_INTERNAL|0x14);
-      break;
     }
 }
 
-static void fxam(FPU_REG *st0_ptr)
+
+static void fxam(FPU_REG *st0_ptr, u_char st0tag)
 {
-  int c=0;
-  switch (st0_ptr->tag)
+  int c = 0;
+  switch (st0tag)
     {
-    case TW_Empty:
+    case TAG_Empty:
       c = SW_C3|SW_C0;
       break;
-    case TW_Zero:
+    case TAG_Zero:
       c = SW_C3;
       break;
-    case TW_Valid:
-      /* This will need to be changed if TW_Denormal is ever used. */
-      if ( st0_ptr->exp <= EXP_UNDER )
-        c = SW_C2|SW_C3;  /* Denormal */
-      else
-        c = SW_C2;
-      break;
-    case TW_NaN:
-      c = SW_C0;
-      break;
-    case TW_Infinity:
-      c = SW_C2|SW_C0;
+    case TAG_Valid:
+      c = SW_C2;
       break;
+    case TAG_Special:
+      switch ( FPU_Special(st0_ptr) )
+	{
+	case TW_Denormal:
+	  c = SW_C2|SW_C3;  /* Denormal */
+	  break;
+	case TW_NaN:
+	  /* We also use NaN for unsupported types. */
+	  if ( (st0_ptr->sigh & 0x80000000) && (exponent(st0_ptr) == EXP_OVER) )
+	    c = SW_C0;
+	  break;
+	case TW_Infinity:
+	  c = SW_C2|SW_C0;
+	  break;
+	}
     }
-  if (st0_ptr->sign == SIGN_NEG)
+  if ( getsign(st0_ptr) == SIGN_NEG )
     c |= SW_C1;
   setcc(c);
 }
@@ -123,7 +137,7 @@
   ftst_, fxam, (FUNC_ST0)FPU_illegal, (FUNC_ST0)FPU_illegal
 };
 
-void fp_etc()
+void FPU_etc()
 {
-  (fp_etc_table[FPU_rm])(&st(0));
+  (fp_etc_table[FPU_rm])(&st(0), FPU_gettag0());
 }
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/fpu_proto.h linux-2.0.40/arch/i386/math-emu/fpu_proto.h
--- linux-2.0.39/arch/i386/math-emu/fpu_proto.h	Mon Aug  1 07:19:13 1994
+++ linux-2.0.40/arch/i386/math-emu/fpu_proto.h	Mon Oct  8 23:54:43 2001
@@ -1,22 +1,26 @@
+#ifndef _FPU_PROTO_H
+#define _FPU_PROTO_H
+
 /* errors.c */
 extern void Un_impl(void);
 extern void FPU_illegal(void);
-extern void emu_printall(void);
-extern void stack_overflow(void);
-extern void stack_underflow(void);
-extern void stack_underflow_i(int i);
-extern void stack_underflow_pop(int i);
+extern void FPU_printall(void);
+asmlinkage void FPU_exception(int n);
+extern int real_1op_NaN(FPU_REG *a);
+extern int real_2op_NaN(FPU_REG const *b, u_char tagb, int deststnr,
+			FPU_REG const *defaultNaN);
+extern int arith_invalid(int deststnr);
+extern int FPU_divide_by_zero(int deststnr, u_char sign);
 extern int set_precision_flag(int flags);
-asmlinkage void exception(int n);
-asmlinkage int real_2op_NaN(FPU_REG const *a, FPU_REG const *b, FPU_REG *dest);
-asmlinkage int arith_invalid(FPU_REG *dest);
-asmlinkage int divide_by_zero(int sign, FPU_REG *dest);
-asmlinkage void set_precision_flag_up(void);
-asmlinkage void set_precision_flag_down(void);
-asmlinkage int denormal_operand(void);
-asmlinkage int arith_overflow(FPU_REG *dest);
-asmlinkage int arith_underflow(FPU_REG *dest);
-
+extern void set_precision_flag_up(void);
+extern void set_precision_flag_down(void);
+extern int denormal_operand(void);
+extern int arith_overflow(FPU_REG *dest, int sign);
+extern int arith_underflow(FPU_REG *dest);
+extern void FPU_stack_overflow(void);
+extern void FPU_stack_underflow(void);
+extern void FPU_stack_underflow_i(int i);
+extern void FPU_stack_underflow_pop(int i);
 /* fpu_arith.c */
 extern void fadd__(void);
 extern void fmul__(void);
@@ -36,7 +40,6 @@
 extern void fsubp_(void);
 extern void fdivrp(void);
 extern void fdivp_(void);
-
 /* fpu_aux.c */
 extern void fclex(void);
 extern void finit(void);
@@ -50,56 +53,66 @@
 extern void fst_i_(void);
 extern void fstp_i(void);
 
-/* fpu_entry.c */
-asmlinkage void math_emulate(long arg);
-extern void math_abort(struct info *info, unsigned int signal);
+extern void fcmovnb(void);
+extern void fcmovne(void);
+extern void fcmovnbe(void);
+extern void fcmovnu(void);
+extern void fcmovb(void);
+extern void fcmove(void);
+extern void fcmovbe(void);
+extern void fcmovu(void);
 
+/* fpu_entry.c */
+extern void math_emulate(long arg);
+extern void math_abort(unsigned int signal);
 /* fpu_etc.c */
-extern void fp_etc(void);
-
+extern void FPU_etc(void);
+/* fpu_tags.c */
+extern int FPU_gettag0(void);
+extern int FPU_gettagi(int stnr);
+extern int FPU_gettag(int regnr);
+extern void FPU_settag0(int tag);
+extern void FPU_settagi(int stnr, int tag);
+extern void FPU_settag(int regnr, int tag);
+extern int FPU_Special(FPU_REG const *ptr);
+extern int isNaN(FPU_REG const *ptr);
+extern void FPU_pop(void);
+extern int FPU_empty_i(int stnr);
+extern int FPU_stackoverflow(FPU_REG **st_new_ptr);
+extern void FPU_sync_tags(void);
+extern void FPU_copy_to_regi(FPU_REG const *r, u_char tag, int stnr);
+extern void FPU_copy_to_reg1(FPU_REG const *r, u_char tag);
+extern void FPU_copy_to_reg0(FPU_REG const *r, u_char tag);
 /* fpu_trig.c */
-extern void convert_l2reg(long const *arg, FPU_REG *dest);
-extern void trig_a(void);
-extern void trig_b(void);
-
+extern void FPU_triga(void);
+extern void FPU_trigb(void);
 /* get_address.c */
-extern void *get_address(unsigned char FPU_modrm, unsigned long *fpu_eip,
-			 struct address *addr,
-			 fpu_addr_modes);
-extern void *get_address_16(unsigned char FPU_modrm, unsigned long *fpu_eip,
-			    struct address *addr,
-			    fpu_addr_modes);
-
+extern void *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
+			 struct address *addr, fpu_addr_modes addr_modes);
+extern void *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
+			    struct address *addr, fpu_addr_modes addr_modes);
 /* load_store.c */
-extern int load_store_instr(unsigned char type, fpu_addr_modes addr_modes,
-			     void *address);
-
+extern int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
+			    void *data_address);
 /* poly_2xm1.c */
-extern int poly_2xm1(FPU_REG const *arg, FPU_REG *result);
-
+extern int poly_2xm1(u_char sign, FPU_REG *arg, FPU_REG *result);
 /* poly_atan.c */
-extern void poly_atan(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *result);
-
+extern void poly_atan(FPU_REG *st0_ptr, u_char st0_tag, FPU_REG *st1_ptr,
+		      u_char st1_tag);
 /* poly_l2.c */
-extern void poly_l2(FPU_REG const *arg, FPU_REG const *y, FPU_REG *result);
-extern int poly_l2p1(FPU_REG const *arg, FPU_REG const *y, FPU_REG *result);
-
+extern void poly_l2(FPU_REG *st0_ptr, FPU_REG *st1_ptr, u_char st1_sign);
+extern int poly_l2p1(u_char s0, u_char s1, FPU_REG *r0, FPU_REG *r1,
+		     FPU_REG *d);
 /* poly_sin.c */
-extern void poly_sine(FPU_REG const *arg, FPU_REG *result);
-extern void poly_cos(FPU_REG const *arg, FPU_REG *result);
-
+extern void poly_sine(FPU_REG *st0_ptr);
+extern void poly_cos(FPU_REG *st0_ptr);
 /* poly_tan.c */
-extern void poly_tan(FPU_REG const *arg, FPU_REG *result);
-
+extern void poly_tan(FPU_REG *st0_ptr);
 /* reg_add_sub.c */
-extern int reg_add(FPU_REG const *a, FPU_REG const *b,
-		   FPU_REG *dest, int control_w);
-extern int reg_sub(FPU_REG const *a, FPU_REG const *b,
-		   FPU_REG *dest, int control_w);
-
+extern int FPU_add(FPU_REG const *b, u_char tagb, int destrnr, int control_w);
+extern int FPU_sub(int flags, int rm, int control_w);
 /* reg_compare.c */
-extern int compare(FPU_REG const *b);
-extern int compare_st_data(FPU_REG const *b);
+extern int FPU_compare_st_data(FPU_REG const *loaded_data, u_char loaded_tag);
 extern void fcom_st(void);
 extern void fcompst(void);
 extern void fcompp(void);
@@ -107,31 +120,37 @@
 extern void fucomp(void);
 extern void fucompp(void);
 
+extern void fucomi(void);
+extern void fcomi(void);
 /* reg_constant.c */
 extern void fconst(void);
-
 /* reg_ld_str.c */
-extern int reg_load_extended(long double *addr, FPU_REG *loaded_data);
-extern int reg_load_double(double *dfloat, FPU_REG *loaded_data);
-extern int reg_load_single(float *single, FPU_REG *loaded_data);
-extern void reg_load_int64(long long *_s, FPU_REG *loaded_data);
-extern void reg_load_int32(long *_s, FPU_REG *loaded_data);
-extern void reg_load_int16(short *_s, FPU_REG *loaded_data);
-extern void reg_load_bcd(char *s, FPU_REG *loaded_data);
-extern int reg_store_extended(long double *d, FPU_REG *st0_ptr);
-extern int reg_store_double(double *dfloat, FPU_REG *st0_ptr);
-extern int reg_store_single(float *single, FPU_REG *st0_ptr);
-extern int reg_store_int64(long long *d, FPU_REG *st0_ptr);
-extern int reg_store_int32(long *d, FPU_REG *st0_ptr);
-extern int reg_store_int16(short *d, FPU_REG *st0_ptr);
-extern int reg_store_bcd(char *d, FPU_REG *st0_ptr);
-extern int round_to_int(FPU_REG *r);
-extern char *fldenv(fpu_addr_modes addr_modes, char *address);
-extern void frstor(fpu_addr_modes addr_modes, char *address);
-extern unsigned short tag_word(void);
-extern char *fstenv(fpu_addr_modes addr_modes, char *address);
-extern void fsave(fpu_addr_modes addr_modes, char *address);
-
+extern int FPU_load_extended(long double *s, int stnr);
+extern int FPU_load_double(double *dfloat, FPU_REG *loaded_data);
+extern int FPU_load_single(float *single, FPU_REG *loaded_data);
+extern int FPU_load_int64(long long *_s);
+extern int FPU_load_int32(long *_s, FPU_REG *loaded_data);
+extern int FPU_load_int16(short *_s, FPU_REG *loaded_data);
+extern int FPU_load_bcd(u_char *s);
+extern int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag,
+			      long double *d);
+extern int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double *dfloat);
+extern int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float *single);
+extern int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long *d);
+extern int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long *d);
+extern int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short *d);
+extern int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char *d);
+extern int FPU_round_to_int(FPU_REG *r, u_char tag);
+extern u_char *fldenv(fpu_addr_modes addr_modes, u_char *s);
+extern void frstor(fpu_addr_modes addr_modes, u_char *data_address);
+extern u_char *fstenv(fpu_addr_modes addr_modes, u_char *d);
+extern void fsave(fpu_addr_modes addr_modes, u_char *data_address);
+extern int FPU_tagof(FPU_REG *ptr);
 /* reg_mul.c */
-extern int reg_mul(FPU_REG const *a, FPU_REG const *b,
-		   FPU_REG *dest, unsigned int control_w);
+extern int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w);
+
+extern int FPU_div(int flags, int regrm, int control_w);
+/* reg_convert.c */
+extern int FPU_to_exp16(FPU_REG const *a, FPU_REG *x);
+#endif /* _FPU_PROTO_H */
+
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/fpu_system.h linux-2.0.40/arch/i386/math-emu/fpu_system.h
--- linux-2.0.39/arch/i386/math-emu/fpu_system.h	Thu Oct 16 00:27:56 1997
+++ linux-2.0.40/arch/i386/math-emu/fpu_system.h	Mon Oct  8 23:54:43 2001
@@ -1,9 +1,9 @@
 /*---------------------------------------------------------------------------+
  |  fpu_system.h                                                             |
  |                                                                           |
- | Copyright (C) 1992,1994                                                   |
+ | Copyright (C) 1992,1994,1997,2001                                         |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                       Australia.  E-mail   billm@melbpc.org.au            |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
@@ -12,28 +12,38 @@
 
 /* system dependent definitions */
 
+#include <asm/segment.h>
+
+#include <linux/isdnif.h>  /* for copy to and from user */
+
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 
+#ifdef FPU_current
+extern struct task_struct * FPU_current;
+#else
+#define FPU_current current
+#endif
+
 /* This sets the pointer FPU_info to point to the argument part
    of the stack frame of math_emulate() */
-#define SETUP_DATA_AREA(arg)    FPU_info = (struct info *) &arg
+#define SETUP_DATA_AREA(arg)	FPU_info = (struct info *) &arg
 
-#define LDT_DESCRIPTOR(s)       (current->ldt[(s) >> 3])
-#define SEG_D_SIZE(x)           ((x).b & (3 << 21))
-#define SEG_G_BIT(x)            ((x).b & (1 << 23))
-#define SEG_GRANULARITY(x)      (((x).b & (1 << 23)) ? 4096 : 1)
-#define SEG_286_MODE(x)         ((x).b & ( 0xff000000 | 0xf0000 | (1 << 23)))
-#define SEG_BASE_ADDR(s)        (((s).b & 0xff000000) \
+#define LDT_DESCRIPTOR(s)	(FPU_current->ldt[(s) >> 3])
+#define SEG_D_SIZE(x)		((x).b & (3 << 21))
+#define SEG_G_BIT(x)		((x).b & (1 << 23))
+#define SEG_GRANULARITY(x)	(((x).b & (1 << 23)) ? 4096 : 1)
+#define SEG_286_MODE(x)		((x).b & ( 0xff000000 | 0xf0000 | (1 << 23)))
+#define SEG_BASE_ADDR(s)	(((s).b & 0xff000000) \
 				 | (((s).b & 0xff) << 16) | ((s).a >> 16))
-#define SEG_LIMIT(s)            (((s).b & 0xff0000) | ((s).a & 0xffff))
-#define SEG_EXECUTE_ONLY(s)     (((s).b & ((1 << 11) | (1 << 9))) == (1 << 11))
-#define SEG_WRITE_PERM(s)       (((s).b & ((1 << 11) | (1 << 9))) == (1 << 9))
-#define SEG_EXPAND_DOWN(s)      (((s).b & ((1 << 11) | (1 << 10))) \
+#define SEG_LIMIT(s)		(((s).b & 0xff0000) | ((s).a & 0xffff))
+#define SEG_EXECUTE_ONLY(s)	(((s).b & ((1 << 11) | (1 << 9))) == (1 << 11))
+#define SEG_WRITE_PERM(s)	(((s).b & ((1 << 11) | (1 << 9))) == (1 << 9))
+#define SEG_EXPAND_DOWN(s)	(((s).b & ((1 << 11) | (1 << 10))) \
 				 == (1 << 10))
 
-#define I387			(current->tss.i387)
+#define I387			(FPU_current->tss.i387)
 #define FPU_info		(I387.soft.info)
 
 #define FPU_CS			(*(unsigned short *) &(FPU_info->___cs))
@@ -44,27 +54,39 @@
 #define FPU_EIP			(FPU_info->___eip)
 #define FPU_ORIG_EIP		(FPU_info->___orig_eip)
 
+#define FPU_USER_CS		USER_CS
+#define FPU_USER_DS		USER_DS
+#define FPU_KERNEL_CS		KERNEL_CS
+
+#define FPU_TRACING		(FPU_current->flags & PF_PTRACED)
+
+#define FPU_SEND_SIGNAL(signal)	FPU_current->tss.trap_no = 16; \
+				FPU_current->tss.error_code = 0; \
+				send_sig(signal,FPU_current,1);
+
 #define FPU_lookahead           (I387.soft.lookahead)
 
+#define FPU_need_resched	need_resched
+
 /* nz if ip_offset and cs_selector are not to be set for the current
    instruction. */
-#define no_ip_update            (((char *)&(I387.soft.twd))[0])
-#define FPU_rm                  (((unsigned char *)&(I387.soft.twd))[1])
+#define no_ip_update		(*(u_char *)&(I387.soft.no_update))
+#define FPU_rm			(*(u_char *)&(I387.soft.rm))
 
 /* Number of bytes of data which can be legally accessed by the current
    instruction. This only needs to hold a number <= 108, so a byte will do. */
-#define access_limit            (((unsigned char *)&(I387.soft.twd))[2])
+#define access_limit		(*(u_char *)&(I387.soft.alimit))
 
-#define partial_status       	(I387.soft.swd)
+#define partial_status		(I387.soft.swd)
 #define control_word		(I387.soft.cwd)
-#define regs			(I387.soft.regs)
-#define top			(I387.soft.top)
+#define fpu_tag_word		(I387.soft.twd)
+#define registers		(I387.soft.st_space)
+#define FPU_top			(I387.soft.ftop)
 
-#define instruction_address     (*(struct address *)&I387.soft.fip)
-#define operand_address         (*(struct address *)&I387.soft.foo)
+#define instruction_address	(*(struct address *)&I387.soft.fip)
+#define operand_address		(*(struct address *)&I387.soft.foo)
 
-#define FPU_verify_area(x,y,z)  if ( verify_area(x,y,z) ) \
-                                math_abort(FPU_info,SIGSEGV)
+#define FPU_verify_area(x,y,z)	if ( verify_area(x,y,z) ) math_abort(SIGSEGV)
 
 #undef FPU_IGNORE_CODE_SEGV
 #ifdef FPU_IGNORE_CODE_SEGV
@@ -79,5 +101,23 @@
    past the upper boundary of a legal code area. */
 #define	FPU_code_verify_area(z) FPU_verify_area(VERIFY_READ,(void *)FPU_EIP,z)
 #endif
+
+#ifndef FPU_get_user
+#define FPU_get_user(x,y)       (x) = get_user(y)
+#define FPU_put_user(x,y)       put_user((x),(y))
+#define FPU_copy_from_user(x,y,z)	copy_from_user((x),(y),(z))
+#define FPU_copy_to_user(x,y,z)	copy_to_user((x),(y),(z))
+#else
+int get_user_n(void *dst, void *ptr, int n);
+#define FPU_get_user(x,y)       { unsigned long int v; \
+			get_user_n(&v, (y),sizeof(*(y))); (x) = v; }
+int put_user_n(void *src, void *ptr, int n);
+#define FPU_put_user(x,y)       { unsigned long int v = (x); \
+ 			put_user_n(&v,(y),sizeof(*(y))); }
+#define FPU_copy_from_user(x,y,n)	get_user_n((x),(y),n)
+#define FPU_copy_to_user(x,y,n)	put_user_n((x),(y),n)
+#endif
+
+#define FPU_EXIT  __asm__("movl %0,%%esp ; ret": :"g" (((long) FPU_info)-4))
 
 #endif
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/fpu_tags.c linux-2.0.40/arch/i386/math-emu/fpu_tags.c
--- linux-2.0.39/arch/i386/math-emu/fpu_tags.c	Thu Jan  1 01:00:00 1970
+++ linux-2.0.40/arch/i386/math-emu/fpu_tags.c	Mon Oct  8 23:54:43 2001
@@ -0,0 +1,127 @@
+/*---------------------------------------------------------------------------+
+ |  fpu_tags.c                                                               |
+ |                                                                           |
+ |  Set FPU register tags.                                                   |
+ |                                                                           |
+ | Copyright (C) 1997,2001                                                   |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@melbpc.org.au                             |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "fpu_emu.h"
+#include "fpu_system.h"
+#include "exception.h"
+
+
+void FPU_pop(void)
+{
+  fpu_tag_word |= 3 << ((FPU_top & 7)*2);
+  FPU_top++;
+}
+
+
+int FPU_gettag0(void)
+{
+  return (fpu_tag_word >> ((FPU_top & 7)*2)) & 3;
+}
+
+
+int FPU_gettagi(int stnr)
+{
+  return (fpu_tag_word >> (((FPU_top+stnr) & 7)*2)) & 3;
+}
+
+
+int FPU_gettag(int regnr)
+{
+  return (fpu_tag_word >> ((regnr & 7)*2)) & 3;
+}
+
+
+void FPU_settag0(int tag)
+{
+  int regnr = FPU_top;
+  regnr &= 7;
+  fpu_tag_word &= ~(3 << (regnr*2));
+  fpu_tag_word |= (tag & 3) << (regnr*2);
+}
+
+
+void FPU_settagi(int stnr, int tag)
+{
+  int regnr = stnr+FPU_top;
+  regnr &= 7;
+  fpu_tag_word &= ~(3 << (regnr*2));
+  fpu_tag_word |= (tag & 3) << (regnr*2);
+}
+
+
+void FPU_settag(int regnr, int tag)
+{
+  regnr &= 7;
+  fpu_tag_word &= ~(3 << (regnr*2));
+  fpu_tag_word |= (tag & 3) << (regnr*2);
+}
+
+
+int FPU_Special(FPU_REG const *ptr)
+{
+  int exp = exponent(ptr);
+
+  if ( exp == EXP_BIAS+EXP_UNDER )
+    return TW_Denormal;
+  else if ( exp != EXP_BIAS+EXP_OVER )
+    return TW_NaN;
+  else if ( (ptr->sigh == 0x80000000) && (ptr->sigl == 0) )
+    return TW_Infinity;
+  return TW_NaN;
+}
+
+
+int isNaN(FPU_REG const *ptr)
+{
+  return ( (exponent(ptr) == EXP_BIAS+EXP_OVER)
+	   && !((ptr->sigh == 0x80000000) && (ptr->sigl == 0)) );
+}
+
+
+int FPU_empty_i(int stnr)
+{
+  int regnr = (FPU_top+stnr) & 7;
+
+  return ((fpu_tag_word >> (regnr*2)) & 3) == TAG_Empty;
+}
+
+
+int FPU_stackoverflow(FPU_REG **st_new_ptr)
+{
+  *st_new_ptr = &st(-1);
+
+  return ((fpu_tag_word >> (((FPU_top - 1) & 7)*2)) & 3) != TAG_Empty;
+}
+
+
+void FPU_copy_to_regi(FPU_REG const *r, u_char tag, int stnr)
+{
+  reg_copy(r, &st(stnr));
+  FPU_settagi(stnr, tag);
+}
+
+void FPU_copy_to_reg1(FPU_REG const *r, u_char tag)
+{
+  reg_copy(r, &st(1));
+  FPU_settagi(1, tag);
+}
+
+void FPU_copy_to_reg0(FPU_REG const *r, u_char tag)
+{
+  int regnr = FPU_top;
+  regnr &= 7;
+
+  reg_copy(r, &st(0));
+
+  fpu_tag_word &= ~(3 << (regnr*2));
+  fpu_tag_word |= (tag & 3) << (regnr*2);
+}
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/fpu_trig.c linux-2.0.40/arch/i386/math-emu/fpu_trig.c
--- linux-2.0.39/arch/i386/math-emu/fpu_trig.c	Mon Aug  1 07:19:13 1994
+++ linux-2.0.40/arch/i386/math-emu/fpu_trig.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  | Implementation of the FPU "transcendental" functions.                     |
  |                                                                           |
- | Copyright (C) 1992,1993,1994                                              |
+ | Copyright (C) 1992,1993,1994,1997,1999,2001                               |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                       Australia.  E-mail   billm@melbpc.org.au            |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -17,7 +17,6 @@
 #include "control_w.h"
 #include "reg_constant.h"	
 
-
 static void rem_kernel(unsigned long long st0, unsigned long long *y,
 		       unsigned long long st1,
 		       unsigned long long q, int n);
@@ -25,9 +24,6 @@
 #define BETTER_THAN_486
 
 #define FCOS  4
-/* Not needed now with new code
-#define FPTAN 1
- */
 
 /* Used only by fptan, fsin, fcos, and fsincos. */
 /* This routine produces very accurate results, similar to
@@ -35,13 +31,15 @@
 /* Limited measurements show no results worse than 64 bit precision
    except for the results for arguments close to 2^63, where the
    precision of the result sometimes degrades to about 63.9 bits */
-static int trig_arg(FPU_REG *X, int even)
+static int trig_arg(FPU_REG *st0_ptr, int even)
 {
   FPU_REG tmp;
+  u_char tmptag;
   unsigned long long q;
   int old_cw = control_word, saved_status = partial_status;
+  int tag, st0_tag = TAG_Valid;
 
-  if ( X->exp >= EXP_BIAS + 63 )
+  if ( exponent(st0_ptr) >= 63 )
     {
       partial_status |= SW_C2;     /* Reduction incomplete. */
       return -1;
@@ -50,62 +48,57 @@
   control_word &= ~CW_RC;
   control_word |= RC_CHOP;
 
-  reg_div(X, &CONST_PI2, &tmp, PR_64_BITS | RC_CHOP | 0x3f);
-  round_to_int(&tmp);  /* Fortunately, this can't overflow
-			  to 2^64 */
+  setpositive(st0_ptr);
+  tag = FPU_u_div(st0_ptr, &CONST_PI2, &tmp, PR_64_BITS | RC_CHOP | 0x3f,
+		  SIGN_POS);
+
+  FPU_round_to_int(&tmp, tag);  /* Fortunately, this can't overflow
+				   to 2^64 */
   q = significand(&tmp);
   if ( q )
     {
-      rem_kernel(significand(X),
+      rem_kernel(significand(st0_ptr),
 		 &significand(&tmp),
 		 significand(&CONST_PI2),
-		 q, X->exp - CONST_PI2.exp);
-      tmp.exp = CONST_PI2.exp;
-      normalize(&tmp);
-      reg_move(&tmp, X);
+		 q, exponent(st0_ptr) - exponent(&CONST_PI2));
+      setexponent16(&tmp, exponent(&CONST_PI2));
+      st0_tag = FPU_normalize(&tmp, 0);  /* Can't overflow */
+      FPU_copy_to_reg0(&tmp, st0_tag);
     }
 
-#ifdef FPTAN
-  if ( even == FPTAN )
-    {
-      if ( ((X->exp >= EXP_BIAS) ||
-	    ((X->exp == EXP_BIAS-1)
-	     && (X->sigh >= 0xc90fdaa2))) ^ (q & 1) )
-	even = FCOS;
-      else
-	even = 0;
-    }
-#endif FPTAN
-
   if ( (even && !(q & 1)) || (!even && (q & 1)) )
     {
-      reg_sub(&CONST_PI2, X, X, FULL_PRECISION);
+      st0_tag = FPU_sub(REV|LOADED|TAG_Valid, (int)&CONST_PI2, FULL_PRECISION);
+
 #ifdef BETTER_THAN_486
       /* So far, the results are exact but based upon a 64 bit
 	 precision approximation to pi/2. The technique used
 	 now is equivalent to using an approximation to pi/2 which
 	 is accurate to about 128 bits. */
-      if ( (X->exp <= CONST_PI2extra.exp + 64) || (q > 1) )
+      if ( (exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64) || (q > 1) )
 	{
-	  /* This code gives the effect of having p/2 to better than
+	  /* This code gives the effect of having pi/2 to better than
 	     128 bits precision. */
+
 	  significand(&tmp) = q + 1;
-	  tmp.exp = EXP_BIAS + 63;
-	  tmp.tag = TW_Valid;
-	  normalize(&tmp);
-	  reg_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION);
-	  reg_add(X, &tmp,  X, FULL_PRECISION);
-	  if ( X->sign == SIGN_NEG )
+	  setexponent16(&tmp, 63);
+	  FPU_normalize(&tmp, 0);   /* Can't overflow */
+	  tmptag =
+	    FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION, SIGN_POS,
+		      exponent(&CONST_PI2extra) + exponent(&tmp));
+	  setsign(&tmp, getsign(&CONST_PI2extra));
+	  st0_tag = FPU_add(&tmp, tmptag, 0, FULL_PRECISION);
+	  if ( signnegative(st0_ptr) )
 	    {
 	      /* CONST_PI2extra is negative, so the result of the addition
 		 can be negative. This means that the argument is actually
 		 in a different quadrant. The correction is always < pi/2,
 		 so it can't overflow into yet another quadrant. */
-	      X->sign = SIGN_POS;
+	      setpositive(st0_ptr);
 	      q++;
 	    }
 	}
-#endif BETTER_THAN_486
+#endif /* BETTER_THAN_486 */
     }
 #ifdef BETTER_THAN_486
   else
@@ -114,33 +107,40 @@
 	 precision approximation to pi/2. The technique used
 	 now is equivalent to using an approximation to pi/2 which
 	 is accurate to about 128 bits. */
-      if ( ((q > 0) && (X->exp <= CONST_PI2extra.exp + 64)) || (q > 1) )
+      if ( ((q > 0) && (exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64))
+	   || (q > 1) )
 	{
 	  /* This code gives the effect of having p/2 to better than
 	     128 bits precision. */
+
 	  significand(&tmp) = q;
-	  tmp.exp = EXP_BIAS + 63;
-	  tmp.tag = TW_Valid;
-	  normalize(&tmp);
-	  reg_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION);
-	  reg_sub(X, &tmp, X, FULL_PRECISION);
-	  if ( (X->exp == CONST_PI2.exp) &&
-	      ((X->sigh > CONST_PI2.sigh)
-	       || ((X->sigh == CONST_PI2.sigh)
-		   && (X->sigl > CONST_PI2.sigl))) )
+	  setexponent16(&tmp, 63);
+	  FPU_normalize(&tmp, 0);         /* This must return TAG_Valid */
+	  tmptag = FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION,
+			     SIGN_POS,
+			     exponent(&CONST_PI2extra) + exponent(&tmp));
+	  setsign(&tmp, getsign(&CONST_PI2extra));
+	  st0_tag = FPU_sub(LOADED|(tmptag & 0x0f), (int)&tmp,
+			    FULL_PRECISION);
+	  if ( (exponent(st0_ptr) == exponent(&CONST_PI2)) &&
+	      ((st0_ptr->sigh > CONST_PI2.sigh)
+	       || ((st0_ptr->sigh == CONST_PI2.sigh)
+		   && (st0_ptr->sigl > CONST_PI2.sigl))) )
 	    {
 	      /* CONST_PI2extra is negative, so the result of the
 		 subtraction can be larger than pi/2. This means
 		 that the argument is actually in a different quadrant.
 		 The correction is always < pi/2, so it can't overflow
 		 into yet another quadrant. */
-	      reg_sub(&CONST_PI, X, X, FULL_PRECISION);
+	      st0_tag = FPU_sub(REV|LOADED|TAG_Valid, (int)&CONST_PI2,
+				FULL_PRECISION);
 	      q++;
 	    }
 	}
     }
-#endif BETTER_THAN_486
+#endif /* BETTER_THAN_486 */
 
+  FPU_settag0(st0_tag);
   control_word = old_cw;
   partial_status = saved_status & ~SW_C2;     /* Reduction complete. */
 
@@ -149,57 +149,56 @@
 
 
 /* Convert a long to register */
-void convert_l2reg(long const *arg, FPU_REG *dest)
+static void convert_l2reg(long const *arg, int deststnr)
 {
+  int tag;
   long num = *arg;
+  u_char sign;
+  FPU_REG *dest = &st(deststnr);
 
   if (num == 0)
-    { reg_move(&CONST_Z, dest); return; }
+    {
+      FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
+      return;
+    }
 
   if (num > 0)
-    dest->sign = SIGN_POS;
+    { sign = SIGN_POS; }
   else
-    { num = -num; dest->sign = SIGN_NEG; }
+    { num = -num; sign = SIGN_NEG; }
 
   dest->sigh = num;
   dest->sigl = 0;
-  dest->exp = EXP_BIAS + 31;
-  dest->tag = TW_Valid;
-  normalize(dest);
+  setexponent16(dest, 31);
+  tag = FPU_normalize(dest, sign);
+  FPU_settagi(deststnr, tag);
+  setsign(dest, sign);
+  return;
 }
 
 
-static void single_arg_error(FPU_REG *st0_ptr)
+static void single_arg_error(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  switch ( st0_ptr->tag )
-    {
-    case TW_NaN:
-      if ( !(st0_ptr->sigh & 0x40000000) )   /* Signaling ? */
-	{
-	  EXCEPTION(EX_Invalid);
-	  if ( control_word & CW_Invalid )
-	    st0_ptr->sigh |= 0x40000000;	  /* Convert to a QNaN */
-	}
-      break;              /* return with a NaN in st(0) */
-    case TW_Empty:
-      stack_underflow();  /* Puts a QNaN in st(0) */
-      break;
+  if ( st0_tag == TAG_Empty )
+    FPU_stack_underflow();  /* Puts a QNaN in st(0) */
+  else if ( st0_tag == TW_NaN )
+    real_1op_NaN(st0_ptr);       /* return with a NaN in st(0) */
 #ifdef PARANOID
-    default:
-      EXCEPTION(EX_INTERNAL|0x0112);
-#endif PARANOID
-    }
+  else
+    EXCEPTION(EX_INTERNAL|0x0112);
+#endif /* PARANOID */
 }
 
 
-static void single_arg_2_error(FPU_REG *st0_ptr)
+static void single_arg_2_error(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  FPU_REG *st_new_ptr;
+  int isNaN;
 
-  switch ( st0_ptr->tag )
+  switch ( st0_tag )
     {
     case TW_NaN:
-      if ( !(st0_ptr->sigh & 0x40000000) )   /* Signaling ? */
+      isNaN = (exponent(st0_ptr) == EXP_OVER) && (st0_ptr->sigh & 0x80000000);
+      if ( isNaN && !(st0_ptr->sigh & 0x40000000) )   /* Signaling ? */
 	{
 	  EXCEPTION(EX_Invalid);
 	  if ( control_word & CW_Invalid )
@@ -207,115 +206,121 @@
 	      /* The masked response */
 	      /* Convert to a QNaN */
 	      st0_ptr->sigh |= 0x40000000;
-	      st_new_ptr = &st(-1);
 	      push();
-	      reg_move(&st(1), st_new_ptr);
+	      FPU_copy_to_reg0(st0_ptr, TAG_Special);
 	    }
 	}
-      else
+      else if ( isNaN )
 	{
 	  /* A QNaN */
-	  st_new_ptr = &st(-1);
 	  push();
-	  reg_move(&st(1), st_new_ptr);
+	  FPU_copy_to_reg0(st0_ptr, TAG_Special);
+	}
+      else
+	{
+	  /* pseudoNaN or other unsupported */
+	  EXCEPTION(EX_Invalid);
+	  if ( control_word & CW_Invalid )
+	    {
+	      /* The masked response */
+	      FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
+	      push();
+	      FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
+	    }
 	}
       break;              /* return with a NaN in st(0) */
 #ifdef PARANOID
     default:
       EXCEPTION(EX_INTERNAL|0x0112);
-#endif PARANOID
+#endif /* PARANOID */
     }
 }
 
 
 /*---------------------------------------------------------------------------*/
 
-static void f2xm1(FPU_REG *st0_ptr)
+static void f2xm1(FPU_REG *st0_ptr, u_char tag)
 {
+  FPU_REG a;
+
   clear_C1();
-  switch ( st0_ptr->tag )
+
+  if ( tag == TAG_Valid )
     {
-    case TW_Valid:
-      {
-	if ( st0_ptr->exp >= 0 )
-	  {
-	    /* For an 80486 FPU, the result is undefined. */
-	  }
-#ifdef DENORM_OPERAND
-	else if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
-	  return;
-#endif DENORM_OPERAND
-	else
-	  {
-	    /* poly_2xm1(x) requires 0 < x < 1. */
-	    poly_2xm1(st0_ptr, st0_ptr);
-	  }
-	if ( st0_ptr->exp <= EXP_UNDER )
-	  {
-	    /* A denormal result has been produced.
-	       Precision must have been lost, this is always
-	       an underflow. */
-	    arith_underflow(st0_ptr);
-	  }
-	set_precision_flag_up();   /* 80486 appears to always do this */
-	return;
-      }
-    case TW_Zero:
+      /* For an 80486 FPU, the result is undefined if the arg is >= 1.0 */
+      if ( exponent(st0_ptr) < 0 )
+	{
+	denormal_arg:
+
+	  FPU_to_exp16(st0_ptr, &a);
+
+	  /* poly_2xm1(x) requires 0 < st(0) < 1. */
+	  poly_2xm1(getsign(st0_ptr), &a, st0_ptr);
+	}
+      set_precision_flag_up();   /* 80486 appears to always do this */
       return;
+    }
+
+  if ( tag == TAG_Zero )
+    return;
+
+  if ( tag == TAG_Special )
+    tag = FPU_Special(st0_ptr);
+
+  switch ( tag )
+    {
+    case TW_Denormal:
+      if ( denormal_operand() < 0 )
+	return;
+      goto denormal_arg;
     case TW_Infinity:
-      if ( st0_ptr->sign == SIGN_NEG )
+      if ( signnegative(st0_ptr) )
 	{
 	  /* -infinity gives -1 (p16-10) */
-	  reg_move(&CONST_1, st0_ptr);
-	  st0_ptr->sign = SIGN_NEG;
+	  FPU_copy_to_reg0(&CONST_1, TAG_Valid);
+	  setnegative(st0_ptr);
 	}
       return;
     default:
-      single_arg_error(st0_ptr);
+      single_arg_error(st0_ptr, tag);
     }
 }
 
 
-static void fptan(FPU_REG *st0_ptr)
+static void fptan(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  char st0_tag = st0_ptr->tag;
   FPU_REG *st_new_ptr;
   int q;
-  char arg_sign = st0_ptr->sign;
+  u_char arg_sign = getsign(st0_ptr);
 
   /* Stack underflow has higher priority */
-  if ( st0_tag == TW_Empty )
+  if ( st0_tag == TAG_Empty )
     {
-      stack_underflow();  /* Puts a QNaN in st(0) */
+      FPU_stack_underflow();  /* Puts a QNaN in st(0) */
       if ( control_word & CW_Invalid )
 	{
 	  st_new_ptr = &st(-1);
 	  push();
-	  stack_underflow();  /* Puts a QNaN in the new st(0) */
+	  FPU_stack_underflow();  /* Puts a QNaN in the new st(0) */
 	}
       return;
     }
 
   if ( STACK_OVERFLOW )
-    { stack_overflow(); return; }
+    { FPU_stack_overflow(); return; }
 
-  switch ( st0_tag )
+  if ( st0_tag == TAG_Valid )
     {
-    case TW_Valid:
-      if ( st0_ptr->exp > EXP_BIAS - 40 )
+      if ( exponent(st0_ptr) > -40 )
 	{
-	  st0_ptr->sign = SIGN_POS;
-	  if ( (q = trig_arg(st0_ptr, 0)) != -1 )
-	    {
-	      poly_tan(st0_ptr, st0_ptr);
-	      st0_ptr->sign = (q & 1) ^ arg_sign;
-	    }
-	  else
+	  if ( (q = trig_arg(st0_ptr, 0)) == -1 )
 	    {
 	      /* Operand is out of range */
-	      st0_ptr->sign = arg_sign;         /* restore st(0) */
 	      return;
 	    }
+
+	  poly_tan(st0_ptr);
+	  setsign(st0_ptr, (q & 1) ^ (arg_sign != 0));
 	  set_precision_flag_up();  /* We do not really know if up or down */
 	}
       else
@@ -323,106 +328,134 @@
 	  /* For a small arg, the result == the argument */
 	  /* Underflow may happen */
 
-	  if ( st0_ptr->exp <= EXP_UNDER )
-	    {
-#ifdef DENORM_OPERAND
-	      if ( denormal_operand() )
-		return;
-#endif DENORM_OPERAND
-	      /* A denormal result has been produced.
-		 Precision must have been lost, this is always
-		 an underflow. */
-	      if ( arith_underflow(st0_ptr) )
-		return;
-	    }
-	  set_precision_flag_down();  /* Must be down. */
+	denormal_arg:
+
+	  FPU_to_exp16(st0_ptr, st0_ptr);
+      
+	  st0_tag = FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign);
+	  FPU_settag0(st0_tag);
 	}
       push();
-      reg_move(&CONST_1, st_new_ptr);
+      FPU_copy_to_reg0(&CONST_1, TAG_Valid);
       return;
-      break;
-    case TW_Infinity:
+    }
+
+  if ( st0_tag == TAG_Zero )
+    {
+      push();
+      FPU_copy_to_reg0(&CONST_1, TAG_Valid);
+      setcc(0);
+      return;
+    }
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+
+  if ( st0_tag == TW_Denormal )
+    {
+      if ( denormal_operand() < 0 )
+	return;
+
+      goto denormal_arg;
+    }
+
+  if ( st0_tag == TW_Infinity )
+    {
       /* The 80486 treats infinity as an invalid operand */
-      arith_invalid(st0_ptr);
-      if ( control_word & CW_Invalid )
+      if ( arith_invalid(0) >= 0 )
 	{
 	  st_new_ptr = &st(-1);
 	  push();
-	  arith_invalid(st_new_ptr);
+	  arith_invalid(0);
 	}
       return;
-    case TW_Zero:
-      push();
-      reg_move(&CONST_1, st_new_ptr);
-      setcc(0);
-      break;
-    default:
-      single_arg_2_error(st0_ptr);
-      break;
     }
+
+  single_arg_2_error(st0_ptr, st0_tag);
 }
 
 
-static void fxtract(FPU_REG *st0_ptr)
+static void fxtract(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  char st0_tag = st0_ptr->tag;
   FPU_REG *st_new_ptr;
+  u_char sign;
   register FPU_REG *st1_ptr = st0_ptr;  /* anticipate */
 
   if ( STACK_OVERFLOW )
-    {  stack_overflow(); return; }
+    {  FPU_stack_overflow(); return; }
+
   clear_C1();
-  if ( !(st0_tag ^ TW_Valid) )
+
+  if ( st0_tag == TAG_Valid )
     {
       long e;
 
-#ifdef DENORM_OPERAND
-      if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
-	return;
-#endif DENORM_OPERAND
-	  
       push();
-      reg_move(st1_ptr, st_new_ptr);
-      st_new_ptr->exp = EXP_BIAS;
-      e = st1_ptr->exp - EXP_BIAS;
-      convert_l2reg(&e, st1_ptr);
+      sign = getsign(st1_ptr);
+      reg_copy(st1_ptr, st_new_ptr);
+      setexponent16(st_new_ptr, exponent(st_new_ptr));
+
+    denormal_arg:
+
+      e = exponent16(st_new_ptr);
+      convert_l2reg(&e, 1);
+      setexponentpos(st_new_ptr, 0);
+      setsign(st_new_ptr, sign);
+      FPU_settag0(TAG_Valid);       /* Needed if arg was a denormal */
       return;
     }
-  else if ( st0_tag == TW_Zero )
+  else if ( st0_tag == TAG_Zero )
     {
-      char sign = st0_ptr->sign;
-      if ( divide_by_zero(SIGN_NEG, st0_ptr) )
+      sign = getsign(st0_ptr);
+
+      if ( FPU_divide_by_zero(0, SIGN_NEG) < 0 )
 	return;
+
       push();
-      reg_move(&CONST_Z, st_new_ptr);
-      st_new_ptr->sign = sign;
+      FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
+      setsign(st_new_ptr, sign);
       return;
     }
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+
+  if ( st0_tag == TW_Denormal )
+    {
+      if (denormal_operand() < 0 )
+	return;
+
+      push();
+      sign = getsign(st1_ptr);
+      FPU_to_exp16(st1_ptr, st_new_ptr);
+      goto denormal_arg;
+    }
   else if ( st0_tag == TW_Infinity )
     {
-      char sign = st0_ptr->sign;
-      st0_ptr->sign = SIGN_POS;
+      sign = getsign(st0_ptr);
+      setpositive(st0_ptr);
       push();
-      reg_move(&CONST_INF, st_new_ptr);
-      st_new_ptr->sign = sign;
+      FPU_copy_to_reg0(&CONST_INF, TAG_Special);
+      setsign(st_new_ptr, sign);
       return;
     }
   else if ( st0_tag == TW_NaN )
     {
-      if ( real_2op_NaN(st0_ptr, st0_ptr, st0_ptr) )
+      if ( real_1op_NaN(st0_ptr) < 0 )
 	return;
+
       push();
-      reg_move(st1_ptr, st_new_ptr);
+      FPU_copy_to_reg0(st0_ptr, TAG_Special);
       return;
     }
-  else if ( st0_tag == TW_Empty )
+  else if ( st0_tag == TAG_Empty )
     {
       /* Is this the correct behaviour? */
       if ( control_word & EX_Invalid )
 	{
-	  stack_underflow();
+	  FPU_stack_underflow();
 	  push();
-	  stack_underflow();
+	  FPU_stack_underflow();
 	}
       else
 	EXCEPTION(EX_StackUnder);
@@ -430,197 +463,237 @@
 #ifdef PARANOID
   else
     EXCEPTION(EX_INTERNAL | 0x119);
-#endif PARANOID
+#endif /* PARANOID */
 }
 
 
-static void fdecstp(FPU_REG *st0_ptr)
+static void fdecstp(void)
 {
   clear_C1();
-  top--;  /* st0_ptr will be fixed in math_emulate() before the next instr */
+  FPU_top--;
 }
 
-static void fincstp(FPU_REG *st0_ptr)
+static void fincstp(void)
 {
   clear_C1();
-  top++;  /* st0_ptr will be fixed in math_emulate() before the next instr */
+  FPU_top++;
 }
 
 
-static void fsqrt_(FPU_REG *st0_ptr)
+static void fsqrt_(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  char st0_tag = st0_ptr->tag;
+  int expon;
 
   clear_C1();
-  if ( !(st0_tag ^ TW_Valid) )
+
+  if ( st0_tag == TAG_Valid )
     {
-      int expon;
+      u_char tag;
       
-      if (st0_ptr->sign == SIGN_NEG)
+      if (signnegative(st0_ptr))
 	{
-	  arith_invalid(st0_ptr);  /* sqrt(negative) is invalid */
+	  arith_invalid(0);  /* sqrt(negative) is invalid */
 	  return;
 	}
 
-#ifdef DENORM_OPERAND
-      if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
-	return;
-#endif DENORM_OPERAND
+      /* make st(0) in  [1.0 .. 4.0) */
+      expon = exponent(st0_ptr);
 
-      expon = st0_ptr->exp - EXP_BIAS;
-      st0_ptr->exp = EXP_BIAS + (expon & 1);  /* make st(0) in  [1.0 .. 4.0) */
-      
-      wm_sqrt(st0_ptr, control_word);	/* Do the computation */
-      
-      st0_ptr->exp += expon >> 1;
-      st0_ptr->sign = SIGN_POS;
+    denormal_arg:
+
+      setexponent16(st0_ptr, (expon & 1));
+
+      /* Do the computation, the sign of the result will be positive. */
+      tag = wm_sqrt(st0_ptr, 0, 0, control_word, SIGN_POS);
+      addexponent(st0_ptr, expon >> 1);
+      FPU_settag0(tag);
+      return;
     }
-  else if ( st0_tag == TW_Zero )
+
+  if ( st0_tag == TAG_Zero )
     return;
-  else if ( st0_tag == TW_Infinity )
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+
+  if ( st0_tag == TW_Infinity )
     {
-      if ( st0_ptr->sign == SIGN_NEG )
-	arith_invalid(st0_ptr);  /* sqrt(-Infinity) is invalid */
+      if ( signnegative(st0_ptr) )
+	arith_invalid(0);  /* sqrt(-Infinity) is invalid */
       return;
     }
-  else
-    { single_arg_error(st0_ptr); return; }
+  else if ( st0_tag == TW_Denormal )
+    {
+      if (signnegative(st0_ptr))
+	{
+	  arith_invalid(0);  /* sqrt(negative) is invalid */
+	  return;
+	}
+
+      if ( denormal_operand() < 0 )
+	return;
+
+      FPU_to_exp16(st0_ptr, st0_ptr);
+
+      expon = exponent16(st0_ptr);
+
+      goto denormal_arg;
+    }
+
+  single_arg_error(st0_ptr, st0_tag);
 
 }
 
 
-static void frndint_(FPU_REG *st0_ptr)
+static void frndint_(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  char st0_tag = st0_ptr->tag;
-  int flags;
+  int flags, tag;
 
-  if ( !(st0_tag ^ TW_Valid) )
+  if ( st0_tag == TAG_Valid )
     {
-      if (st0_ptr->exp > EXP_BIAS+63)
-	return;
+      u_char sign;
+
+    denormal_arg:
+
+      sign = getsign(st0_ptr);
 
-#ifdef DENORM_OPERAND
-      if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+      if (exponent(st0_ptr) > 63)
 	return;
-#endif DENORM_OPERAND
+
+      if ( st0_tag == TW_Denormal )
+	{
+	  if (denormal_operand() < 0 )
+	    return;
+	}
 
       /* Fortunately, this can't overflow to 2^64 */
-      if ( (flags = round_to_int(st0_ptr)) )
+      if ( (flags = FPU_round_to_int(st0_ptr, st0_tag)) )
 	set_precision_flag(flags);
 
-      st0_ptr->exp = EXP_BIAS + 63;
-      normalize(st0_ptr);
+      setexponent16(st0_ptr, 63);
+      tag = FPU_normalize(st0_ptr, sign);
+      setsign(st0_ptr, sign);
+      FPU_settag0(tag);
       return;
     }
-  else if ( (st0_tag == TW_Zero) || (st0_tag == TW_Infinity) )
+
+  if ( st0_tag == TAG_Zero )
+    return;
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+
+  if ( st0_tag == TW_Denormal )
+    goto denormal_arg;
+  else if ( st0_tag == TW_Infinity )
     return;
   else
-    single_arg_error(st0_ptr);
+    single_arg_error(st0_ptr, st0_tag);
 }
 
 
-static void fsin(FPU_REG *st0_ptr)
+static int fsin(FPU_REG *st0_ptr, u_char tag)
 {
-  char st0_tag = st0_ptr->tag;
-  char arg_sign = st0_ptr->sign;
+  u_char arg_sign = getsign(st0_ptr);
 
-  if ( st0_tag == TW_Valid )
+  if ( tag == TAG_Valid )
     {
-      FPU_REG rv;
       int q;
 
-      if ( st0_ptr->exp > EXP_BIAS - 40 )
+      if ( exponent(st0_ptr) > -40 )
 	{
-	  st0_ptr->sign = SIGN_POS;
-	  if ( (q = trig_arg(st0_ptr, 0)) != -1 )
+	  if ( (q = trig_arg(st0_ptr, 0)) == -1 )
 	    {
+	      /* Operand is out of range */
+	      return 1;
+	    }
 
-	      poly_sine(st0_ptr, &rv);
+	  poly_sine(st0_ptr);
+	  
+	  if (q & 2)
+	    changesign(st0_ptr);
 
-	      if (q & 2)
-		rv.sign ^= SIGN_POS ^ SIGN_NEG;
-	      rv.sign ^= arg_sign;
-	      reg_move(&rv, st0_ptr);
+	  setsign(st0_ptr, getsign(st0_ptr) ^ arg_sign);
 
-	      /* We do not really know if up or down */
-	      set_precision_flag_up();
-	      return;
-	    }
-	  else
-	    {
-	      /* Operand is out of range */
-	      st0_ptr->sign = arg_sign;         /* restore st(0) */
-	      return;
-	    }
+	  /* We do not really know if up or down */
+	  set_precision_flag_up();
+	  return 0;
 	}
       else
 	{
 	  /* For a small arg, the result == the argument */
-	  /* Underflow may happen */
-
-	  if ( st0_ptr->exp <= EXP_UNDER )
-	    {
-#ifdef DENORM_OPERAND
-	      if ( denormal_operand() )
-		return;
-#endif DENORM_OPERAND
-	      /* A denormal result has been produced.
-		 Precision must have been lost, this is always
-		 an underflow. */
-	      arith_underflow(st0_ptr);
-	      return;
-	    }
-
 	  set_precision_flag_up();  /* Must be up. */
+	  return 0;
 	}
     }
-  else if ( st0_tag == TW_Zero )
+
+  if ( tag == TAG_Zero )
     {
       setcc(0);
-      return;
+      return 0;
     }
-  else if ( st0_tag == TW_Infinity )
+
+  if ( tag == TAG_Special )
+    tag = FPU_Special(st0_ptr);
+
+  if ( tag == TW_Denormal )
+    {
+      if ( denormal_operand() < 0 )
+	return 1;
+
+      /* For a small arg, the result == the argument */
+      /* Underflow may happen */
+      FPU_to_exp16(st0_ptr, st0_ptr);
+      
+      tag = FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign);
+
+      FPU_settag0(tag);
+
+      return 0;
+    }
+  else if ( tag == TW_Infinity )
     {
       /* The 80486 treats infinity as an invalid operand */
-      arith_invalid(st0_ptr);
-      return;
+      arith_invalid(0);
+      return 1;
     }
   else
-    single_arg_error(st0_ptr);
+    {
+      single_arg_error(st0_ptr, tag);
+      return 1;
+    }
 }
 
 
-static int f_cos(FPU_REG *arg)
+static int f_cos(FPU_REG *st0_ptr, u_char tag)
 {
-  char arg_sign = arg->sign;
+  u_char st0_sign;
+
+  st0_sign = getsign(st0_ptr);
 
-  if ( arg->tag == TW_Valid )
+  if ( tag == TAG_Valid )
     {
-      FPU_REG rv;
       int q;
 
-      if ( arg->exp > EXP_BIAS - 40 )
+      if ( exponent(st0_ptr) > -40 )
 	{
-	  arg->sign = SIGN_POS;
-	  if ( (arg->exp < EXP_BIAS)
-	      || ((arg->exp == EXP_BIAS)
-		  && (significand(arg) <= 0xc90fdaa22168c234LL)) )
+	  if ( (exponent(st0_ptr) < 0)
+	      || ((exponent(st0_ptr) == 0)
+		  && (significand(st0_ptr) <= 0xc90fdaa22168c234LL)) )
 	    {
-	      poly_cos(arg, &rv);
-	      reg_move(&rv, arg);
+	      poly_cos(st0_ptr);
 
 	      /* We do not really know if up or down */
 	      set_precision_flag_down();
 	  
 	      return 0;
 	    }
-	  else if ( (q = trig_arg(arg, FCOS)) != -1 )
+	  else if ( (q = trig_arg(st0_ptr, FCOS)) != -1 )
 	    {
-	      poly_sine(arg, &rv);
+	      poly_sine(st0_ptr);
 
 	      if ((q+1) & 2)
-		rv.sign ^= SIGN_POS ^ SIGN_NEG;
-	      reg_move(&rv, arg);
+		changesign(st0_ptr);
 
 	      /* We do not really know if up or down */
 	      set_precision_flag_down();
@@ -630,100 +703,116 @@
 	  else
 	    {
 	      /* Operand is out of range */
-	      arg->sign = arg_sign;         /* restore st(0) */
 	      return 1;
 	    }
 	}
       else
 	{
-#ifdef DENORM_OPERAND
-	  if ( (arg->exp <= EXP_UNDER) && (denormal_operand()) )
-	    return 1;
-#endif DENORM_OPERAND
+	denormal_arg:
 
 	  setcc(0);
-	  reg_move(&CONST_1, arg);
+	  FPU_copy_to_reg0(&CONST_1, TAG_Valid);
 #ifdef PECULIAR_486
 	  set_precision_flag_down();  /* 80486 appears to do this. */
 #else
 	  set_precision_flag_up();  /* Must be up. */
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 	  return 0;
 	}
     }
-  else if ( arg->tag == TW_Zero )
+  else if ( tag == TAG_Zero )
     {
-      reg_move(&CONST_1, arg);
+      FPU_copy_to_reg0(&CONST_1, TAG_Valid);
       setcc(0);
       return 0;
     }
-  else if ( arg->tag == TW_Infinity )
+
+  if ( tag == TAG_Special )
+    tag = FPU_Special(st0_ptr);
+
+  if ( tag == TW_Denormal )
+    {
+      if ( denormal_operand() < 0 )
+	return 1;
+
+      goto denormal_arg;
+    }
+  else if ( tag == TW_Infinity )
     {
       /* The 80486 treats infinity as an invalid operand */
-      arith_invalid(arg);
+      arith_invalid(0);
       return 1;
     }
   else
     {
-      single_arg_error(arg);  /* requires arg == &st(0) */
+      single_arg_error(st0_ptr, tag);  /* requires st0_ptr == &st(0) */
       return 1;
     }
 }
 
 
-static void fcos(FPU_REG *st0_ptr)
+static void fcos(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  f_cos(st0_ptr);
+  f_cos(st0_ptr, st0_tag);
 }
 
 
-static void fsincos(FPU_REG *st0_ptr)
+static void fsincos(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  char st0_tag = st0_ptr->tag;
   FPU_REG *st_new_ptr;
   FPU_REG arg;
+  u_char tag;
 
   /* Stack underflow has higher priority */
-  if ( st0_tag == TW_Empty )
+  if ( st0_tag == TAG_Empty )
     {
-      stack_underflow();  /* Puts a QNaN in st(0) */
+      FPU_stack_underflow();  /* Puts a QNaN in st(0) */
       if ( control_word & CW_Invalid )
 	{
 	  st_new_ptr = &st(-1);
 	  push();
-	  stack_underflow();  /* Puts a QNaN in the new st(0) */
+	  FPU_stack_underflow();  /* Puts a QNaN in the new st(0) */
 	}
       return;
     }
 
   if ( STACK_OVERFLOW )
-    { stack_overflow(); return; }
+    { FPU_stack_overflow(); return; }
 
-  if ( st0_tag == TW_NaN )
+  if ( st0_tag == TAG_Special )
+    tag = FPU_Special(st0_ptr);
+  else
+    tag = st0_tag;
+
+  if ( tag == TW_NaN )
     {
-      single_arg_2_error(st0_ptr);
+      single_arg_2_error(st0_ptr, TW_NaN);
       return;
     }
-  else if ( st0_tag == TW_Infinity )
+  else if ( tag == TW_Infinity )
     {
       /* The 80486 treats infinity as an invalid operand */
-      if ( !arith_invalid(st0_ptr) )
+      if ( arith_invalid(0) >= 0 )
 	{
-	  /* unmasked response */
+	  /* Masked response */
 	  push();
-	  arith_invalid(st_new_ptr);
+	  arith_invalid(0);
 	}
       return;
     }
 
-  reg_move(st0_ptr,&arg);
-  if ( !f_cos(&arg) )
+  reg_copy(st0_ptr, &arg);
+  if ( !fsin(st0_ptr, st0_tag) )
     {
-      fsin(st0_ptr);
       push();
-      reg_move(&arg,st_new_ptr);
+      FPU_copy_to_reg0(&arg, st0_tag);
+      f_cos(&st(0), st0_tag);
+    }
+  else
+    {
+      /* An error, so restore st(0) */
+      FPU_copy_to_reg0(&arg, st0_tag);
     }
-
 }
 
 
@@ -740,18 +829,29 @@
 		       unsigned long long st1,
 		       unsigned long long q, int n)
 {
+  int dummy;
   unsigned long long x;
 
   x = st0 << n;
 
   /* Do the required multiplication and subtraction in the one operation */
-  asm volatile ("movl %2,%%eax; mull %4; subl %%eax,%0; sbbl %%edx,%1;
-                 movl %3,%%eax; mull %4; subl %%eax,%1;
-                 movl %2,%%eax; mull %5; subl %%eax,%1;"
-		:"=m" (x), "=m" (((unsigned *)&x)[1])
-		:"m" (st1),"m" (((unsigned *)&st1)[1]),
-		 "m" (q),"m" (((unsigned *)&q)[1])
-		:"%ax","%dx");
+
+  /* lsw x -= lsw st1 * lsw q */
+  asm volatile ("mull %4; subl %%eax,%0; sbbl %%edx,%1"
+		:"=m" (((unsigned *)&x)[0]), "=m" (((unsigned *)&x)[1]),
+		"=a" (dummy)
+		:"2" (((unsigned *)&st1)[0]), "m" (((unsigned *)&q)[0])
+		:"%dx");
+  /* msw x -= msw st1 * lsw q */
+  asm volatile ("mull %3; subl %%eax,%0"
+		:"=m" (((unsigned *)&x)[1]), "=a" (dummy)
+		:"1" (((unsigned *)&st1)[1]), "m" (((unsigned *)&q)[0])
+		:"%dx");
+  /* msw x -= lsw st1 * msw q */
+  asm volatile ("mull %3; subl %%eax,%0"
+		:"=m" (((unsigned *)&x)[1]), "=a" (dummy)
+		:"1" (((unsigned *)&st1)[0]), "m" (((unsigned *)&q)[1])
+		:"%dx");
 
   *y = x;
 }
@@ -760,79 +860,86 @@
 /* Remainder of st(0) / st(1) */
 /* This routine produces exact results, i.e. there is never any
    rounding or truncation, etc of the result. */
-static void do_fprem(FPU_REG *st0_ptr, int round)
+static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
 {
   FPU_REG *st1_ptr = &st(1);
-  char st1_tag = st1_ptr->tag;
-  char st0_tag = st0_ptr->tag;
-  char sign = st0_ptr->sign;
+  u_char st1_tag = FPU_gettagi(1);
 
-  if ( !((st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
+  if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
     {
-      FPU_REG tmp;
-      int old_cw = control_word;
-      int expdif = st0_ptr->exp - st1_ptr->exp;
+      FPU_REG tmp, st0, st1;
+      u_char st0_sign, st1_sign;
+      u_char tmptag;
+      int tag;
+      int old_cw;
+      int expdif;
       long long q;
       unsigned short saved_status;
-      int cc = 0;
+      int cc;
+
+    fprem_valid:
+      /* Convert registers for internal use. */
+      st0_sign = FPU_to_exp16(st0_ptr, &st0);
+      st1_sign = FPU_to_exp16(st1_ptr, &st1);
+      expdif = exponent16(&st0) - exponent16(&st1);
+
+      old_cw = control_word;
+      cc = 0;
 
-#ifdef DENORM_OPERAND
-      if ( ((st0_ptr->exp <= EXP_UNDER) ||
-	    (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()) )
-	return;
-#endif DENORM_OPERAND
-      
       /* We want the status following the denorm tests, but don't want
 	 the status changed by the arithmetic operations. */
       saved_status = partial_status;
       control_word &= ~CW_RC;
       control_word |= RC_CHOP;
 
-      if (expdif < 64)
+      if ( expdif < 64 )
 	{
 	  /* This should be the most common case */
 
 	  if ( expdif > -2 )
 	    {
-	      reg_div(st0_ptr, st1_ptr, &tmp, PR_64_BITS | RC_CHOP | 0x3f);
+	      u_char sign = st0_sign ^ st1_sign;
+	      tag = FPU_u_div(&st0, &st1, &tmp,
+			      PR_64_BITS | RC_CHOP | 0x3f,
+			      sign);
+	      setsign(&tmp, sign);
 
-	      if ( tmp.exp >= EXP_BIAS )
+	      if ( exponent(&tmp) >= 0 )
 		{
-		  round_to_int(&tmp);  /* Fortunately, this can't overflow
-					  to 2^64 */
+		  FPU_round_to_int(&tmp, tag);  /* Fortunately, this can't
+						   overflow to 2^64 */
 		  q = significand(&tmp);
 
-		  rem_kernel(significand(st0_ptr),
+		  rem_kernel(significand(&st0),
 			     &significand(&tmp),
-			     significand(st1_ptr),
+			     significand(&st1),
 			     q, expdif);
 
-		  tmp.exp = st1_ptr->exp;
+		  setexponent16(&tmp, exponent16(&st1));
 		}
 	      else
 		{
-		  reg_move(st0_ptr, &tmp);
+		  reg_copy(&st0, &tmp);
 		  q = 0;
 		}
-	      tmp.sign = sign;
 
 	      if ( (round == RC_RND) && (tmp.sigh & 0xc0000000) )
 		{
 		  /* We may need to subtract st(1) once more,
 		     to get a result <= 1/2 of st(1). */
 		  unsigned long long x;
-		  expdif = st1_ptr->exp - tmp.exp;
+		  expdif = exponent16(&st1) - exponent16(&tmp);
 		  if ( expdif <= 1 )
 		    {
 		      if ( expdif == 0 )
-			x = significand(st1_ptr) - significand(&tmp);
+			x = significand(&st1) - significand(&tmp);
 		      else /* expdif is 1 */
-			x = (significand(st1_ptr) << 1) - significand(&tmp);
+			x = (significand(&st1) << 1) - significand(&tmp);
 		      if ( (x < significand(&tmp)) ||
 			  /* or equi-distant (from 0 & st(1)) and q is odd */
 			  ((x == significand(&tmp)) && (q & 1) ) )
 			{
-			  tmp.sign ^= (SIGN_POS^SIGN_NEG);
+			  st0_sign = ! st0_sign;
 			  significand(&tmp) = x;
 			  q++;
 			}
@@ -855,28 +962,35 @@
 	  /* There is a large exponent difference ( >= 64 ) */
 	  /* To make much sense, the code in this section should
 	     be done at high precision. */
-	  int exp_1;
+	  int exp_1, N;
+	  u_char sign;
 
 	  /* prevent overflow here */
 	  /* N is 'a number between 32 and 63' (p26-113) */
-	  reg_move(st0_ptr, &tmp);
-	  tmp.exp = EXP_BIAS + 56;
-	  exp_1 = st1_ptr->exp;      st1_ptr->exp = EXP_BIAS;
-	  expdif -= 56;
-
-	  reg_div(&tmp, st1_ptr, &tmp, PR_64_BITS | RC_CHOP | 0x3f);
-	  st1_ptr->exp = exp_1;
+	  reg_copy(&st0, &tmp);
+	  tmptag = st0_tag;
+	  N = (expdif & 0x0000001f) + 32;  /* This choice gives results
+					      identical to an AMD 486 */
+	  setexponent16(&tmp, N);
+	  exp_1 = exponent16(&st1);
+	  setexponent16(&st1, 0);
+	  expdif -= N;
+
+	  sign = getsign(&tmp) ^ st1_sign;
+	  tag = FPU_u_div(&tmp, &st1, &tmp, PR_64_BITS | RC_CHOP | 0x3f,
+			  sign);
+	  setsign(&tmp, sign);
 
-	  round_to_int(&tmp);  /* Fortunately, this can't overflow to 2^64 */
+	  FPU_round_to_int(&tmp, tag);  /* Fortunately, this can't
+					   overflow to 2^64 */
 
-	  rem_kernel(significand(st0_ptr),
+	  rem_kernel(significand(&st0),
 		     &significand(&tmp),
-		     significand(st1_ptr),
+		     significand(&st1),
 		     significand(&tmp),
-		     tmp.exp - EXP_BIAS
+		     exponent(&tmp)
 		     ); 
-	  tmp.exp = exp_1 + expdif;
-	  tmp.sign = sign;
+	  setexponent16(&tmp, exp_1 + expdif);
 
 	  /* It is possible for the operation to be complete here.
 	     What does the IEEE standard say? The Intel 80486 manual
@@ -888,13 +1002,13 @@
 	      /* The result is zero */
 	      control_word = old_cw;
 	      partial_status = saved_status;
-	      reg_move(&CONST_Z, st0_ptr);
-	      st0_ptr->sign = sign;
+	      FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
+	      setsign(&st0, st0_sign);
 #ifdef PECULIAR_486
 	      setcc(SW_C2);
 #else
 	      setcc(0);
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 	      return;
 	    }
 	  cc = SW_C2;
@@ -902,52 +1016,82 @@
 
       control_word = old_cw;
       partial_status = saved_status;
-      normalize_nuo(&tmp);
-      reg_move(&tmp, st0_ptr);
-      setcc(cc);
+      tag = FPU_normalize_nuo(&tmp);
+      reg_copy(&tmp, st0_ptr);
 
       /* The only condition to be looked for is underflow,
 	 and it can occur here only if underflow is unmasked. */
-      if ( (st0_ptr->exp <= EXP_UNDER) && (st0_ptr->tag != TW_Zero)
+      if ( (exponent16(&tmp) <= EXP_UNDER) && (tag != TAG_Zero)
 	  && !(control_word & CW_Underflow) )
-	arith_underflow(st0_ptr);
+	{
+	  setcc(cc);
+	  tag = arith_underflow(st0_ptr);
+	  setsign(st0_ptr, st0_sign);
+	  FPU_settag0(tag);
+	  return;
+	}
+      else if ( (exponent16(&tmp) > EXP_UNDER) || (tag == TAG_Zero) )
+	{
+	  stdexp(st0_ptr);
+	  setsign(st0_ptr, st0_sign);
+	}
+      else
+	{
+	  tag = FPU_round(st0_ptr, 0, 0, FULL_PRECISION, st0_sign);
+	}
+      FPU_settag0(tag);
+      setcc(cc);
 
       return;
     }
-  else if ( (st0_tag == TW_Empty) | (st1_tag == TW_Empty) )
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+  if ( st1_tag == TAG_Special )
+    st1_tag = FPU_Special(st1_ptr);
+
+  if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
+	    || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
+	    || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )
+    {
+      if ( denormal_operand() < 0 )
+	return;
+      goto fprem_valid;
+    }
+  else if ( (st0_tag == TAG_Empty) | (st1_tag == TAG_Empty) )
     {
-      stack_underflow();
+      FPU_stack_underflow();
       return;
     }
-  else if ( st0_tag == TW_Zero )
+  else if ( st0_tag == TAG_Zero )
     {
-      if ( st1_tag == TW_Valid )
+      if ( st1_tag == TAG_Valid )
 	{
-#ifdef DENORM_OPERAND
-	  if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+	  setcc(0); return;
+	}
+      else if ( st1_tag == TW_Denormal )
+	{
+	  if ( denormal_operand() < 0 )
 	    return;
-#endif DENORM_OPERAND
-
 	  setcc(0); return;
 	}
-      else if ( st1_tag == TW_Zero )
-	{ arith_invalid(st0_ptr); return; } /* fprem(?,0) always invalid */
+      else if ( st1_tag == TAG_Zero )
+	{ arith_invalid(0); return; } /* fprem(?,0) always invalid */
       else if ( st1_tag == TW_Infinity )
 	{ setcc(0); return; }
     }
-  else if ( st0_tag == TW_Valid )
+  else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
     {
-      if ( st1_tag == TW_Zero )
+      if ( st1_tag == TAG_Zero )
 	{
-	  arith_invalid(st0_ptr); /* fprem(Valid,Zero) is invalid */
+	  arith_invalid(0); /* fprem(Valid,Zero) is invalid */
 	  return;
 	}
       else if ( st1_tag != TW_NaN )
 	{
-#ifdef DENORM_OPERAND
-	  if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+	  if ( ((st0_tag == TW_Denormal) || (st1_tag == TW_Denormal))
+	       && (denormal_operand() < 0) )
 	    return;
-#endif DENORM_OPERAND
 
 	  if ( st1_tag == TW_Infinity )
 	    {
@@ -960,729 +1104,715 @@
     {
       if ( st1_tag != TW_NaN )
 	{
-	  arith_invalid(st0_ptr); /* fprem(Infinity,?) is invalid */
+	  arith_invalid(0); /* fprem(Infinity,?) is invalid */
 	  return;
 	}
     }
 
-  /* One of the registers must contain a NaN is we got here. */
+  /* One of the registers must contain a NaN if we got here. */
 
 #ifdef PARANOID
   if ( (st0_tag != TW_NaN) && (st1_tag != TW_NaN) )
       EXCEPTION(EX_INTERNAL | 0x118);
-#endif PARANOID
+#endif /* PARANOID */
 
-  real_2op_NaN(st1_ptr, st0_ptr, st0_ptr);
+  real_2op_NaN(st1_ptr, st1_tag, 0, st1_ptr);
 
 }
 
 
 /* ST(1) <- ST(1) * log ST;  pop ST */
-static void fyl2x(FPU_REG *st0_ptr)
+static void fyl2x(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  char st0_tag = st0_ptr->tag;
   FPU_REG *st1_ptr = &st(1), exponent;
-  char st1_tag = st1_ptr->tag;
-  int e;
+  u_char st1_tag = FPU_gettagi(1);
+  u_char sign;
+  int e, tag;
 
   clear_C1();
-  if ( !((st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
+
+  if ( (st0_tag == TAG_Valid) && (st1_tag == TAG_Valid) )
     {
-      if ( st0_ptr->sign == SIGN_POS )
+    both_valid:
+      /* Both regs are Valid or Denormal */
+      if ( signpositive(st0_ptr) )
 	{
-#ifdef DENORM_OPERAND
-	  if ( ((st0_ptr->exp <= EXP_UNDER) ||
-		(st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()) )
-	    return;
-#endif DENORM_OPERAND
+	  if ( st0_tag == TW_Denormal )
+	    FPU_to_exp16(st0_ptr, st0_ptr);
+	  else
+	    /* Convert st(0) for internal use. */
+	    setexponent16(st0_ptr, exponent(st0_ptr));
 
 	  if ( (st0_ptr->sigh == 0x80000000) && (st0_ptr->sigl == 0) )
 	    {
 	      /* Special case. The result can be precise. */
-	      e = st0_ptr->exp - EXP_BIAS;
-	      if ( e > 0 )
+	      u_char esign;
+	      e = exponent16(st0_ptr);
+	      if ( e >= 0 )
 		{
 		  exponent.sigh = e;
-		  exponent.sign = SIGN_POS;
+		  esign = SIGN_POS;
 		}
 	      else
 		{
 		  exponent.sigh = -e;
-		  exponent.sign = SIGN_NEG;
+		  esign = SIGN_NEG;
 		}
 	      exponent.sigl = 0;
-	      exponent.exp = EXP_BIAS + 31;
-	      exponent.tag = TW_Valid;
-	      normalize_nuo(&exponent);
-	      reg_mul(&exponent, st1_ptr, st1_ptr, FULL_PRECISION);
+	      setexponent16(&exponent, 31);
+	      tag = FPU_normalize_nuo(&exponent);
+	      stdexp(&exponent);
+	      setsign(&exponent, esign);
+	      tag = FPU_mul(&exponent, tag, 1, FULL_PRECISION);
+	      if ( tag >= 0 )
+		FPU_settagi(1, tag);
 	    }
 	  else
 	    {
 	      /* The usual case */
-	      poly_l2(st0_ptr, st1_ptr, st1_ptr);
-	      if ( st1_ptr->exp <= EXP_UNDER )
-		{
-		  /* A denormal result has been produced.
-		     Precision must have been lost, this is always
-		     an underflow. */
-		  arith_underflow(st1_ptr);
-		}
+	      sign = getsign(st1_ptr);
+	      if ( st1_tag == TW_Denormal )
+		FPU_to_exp16(st1_ptr, st1_ptr);
 	      else
-		set_precision_flag_up();  /* 80486 appears to always do this */
+		/* Convert st(1) for internal use. */
+		setexponent16(st1_ptr, exponent(st1_ptr));
+	      poly_l2(st0_ptr, st1_ptr, sign);
 	    }
-	  pop();
-	  return;
 	}
       else
 	{
 	  /* negative */
-	  if ( !arith_invalid(st1_ptr) )
-	    pop();
-	  return;
+	  if ( arith_invalid(1) < 0 )
+	    return;
 	}
-    }
-  else if ( (st0_tag == TW_Empty) || (st1_tag == TW_Empty) )
-    {
-      stack_underflow_pop(1);
+
+      FPU_pop();
+
       return;
     }
-  else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) )
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+  if ( st1_tag == TAG_Special )
+    st1_tag = FPU_Special(st1_ptr);
+
+  if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) )
     {
-      if ( !real_2op_NaN(st0_ptr, st1_ptr, st1_ptr) )
-	pop();
+      FPU_stack_underflow_pop(1);
       return;
     }
-  else if ( (st0_tag <= TW_Zero) && (st1_tag <= TW_Zero) )
+  else if ( (st0_tag <= TW_Denormal) && (st1_tag <= TW_Denormal) )
     {
-      /* one of the args is zero, the other valid, or both zero */
-      if ( st0_tag == TW_Zero )
+      if ( st0_tag == TAG_Zero )
 	{
-	  if ( st1_tag == TW_Zero )
+	  if ( st1_tag == TAG_Zero )
 	    {
 	      /* Both args zero is invalid */
-	      if ( !arith_invalid(st1_ptr) )
-		pop();
-	    }
-#ifdef PECULIAR_486
-	  /* This case is not specifically covered in the manual,
-	     but divide-by-zero would seem to be the best response.
-	     However, a real 80486 does it this way... */
-	  else if ( st0_ptr->tag == TW_Infinity )
-	    {
-	      reg_move(&CONST_INF, st1_ptr);
-	      pop();
+	      if ( arith_invalid(1) < 0 )
+		return;
 	    }
-#endif PECULIAR_486
 	  else
 	    {
-	      if ( !divide_by_zero(st1_ptr->sign^SIGN_NEG^SIGN_POS, st1_ptr) )
-		pop();
+	      u_char sign;
+	      sign = getsign(st1_ptr)^SIGN_NEG;
+	      if ( FPU_divide_by_zero(1, sign) < 0 )
+		return;
+
+	      setsign(st1_ptr, sign);
 	    }
-	  return;
 	}
-      else
+      else if ( st1_tag == TAG_Zero )
 	{
 	  /* st(1) contains zero, st(0) valid <> 0 */
 	  /* Zero is the valid answer */
-	  char sign = st1_ptr->sign;
-
-	  if ( st0_ptr->sign == SIGN_NEG )
+	  sign = getsign(st1_ptr);
+	  
+	  if ( signnegative(st0_ptr) )
 	    {
 	      /* log(negative) */
-	      if ( !arith_invalid(st1_ptr) )
-		pop();
-	      return;
+	      if ( arith_invalid(1) < 0 )
+		return;
 	    }
-
-#ifdef DENORM_OPERAND
-	  if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+	  else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
 	    return;
-#endif DENORM_OPERAND
+	  else
+	    {
+	      if ( exponent(st0_ptr) < 0 )
+		sign ^= SIGN_NEG;
 
-	  if ( st0_ptr->exp < EXP_BIAS ) sign ^= SIGN_NEG^SIGN_POS;
-	  pop(); st0_ptr = &st(0);
-	  reg_move(&CONST_Z, st0_ptr);
-	  st0_ptr->sign = sign;
-	  return;
+	      FPU_copy_to_reg1(&CONST_Z, TAG_Zero);
+	      setsign(st1_ptr, sign);
+	    }
+	}
+      else
+	{
+	  /* One or both operands are denormals. */
+	  if ( denormal_operand() < 0 )
+	    return;
+	  goto both_valid;
 	}
     }
+  else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) )
+    {
+      if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
+	return;
+    }
   /* One or both arg must be an infinity */
   else if ( st0_tag == TW_Infinity )
     {
-      if ( (st0_ptr->sign == SIGN_NEG) || (st1_tag == TW_Zero) )
+      if ( (signnegative(st0_ptr)) || (st1_tag == TAG_Zero) )
 	{
 	  /* log(-infinity) or 0*log(infinity) */
-	  if ( !arith_invalid(st1_ptr) )
-	    pop();
-	  return;
+	  if ( arith_invalid(1) < 0 )
+	    return;
 	}
       else
 	{
-	  char sign = st1_ptr->sign;
+	  u_char sign = getsign(st1_ptr);
 
-#ifdef DENORM_OPERAND
-	  if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+	  if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
 	    return;
-#endif DENORM_OPERAND
 
-	  pop(); st0_ptr = &st(0);
-	  reg_move(&CONST_INF, st0_ptr);
-	  st0_ptr->sign = sign;
-	  return;
+	  FPU_copy_to_reg1(&CONST_INF, TAG_Special);
+	  setsign(st1_ptr, sign);
 	}
     }
   /* st(1) must be infinity here */
-  else if ( (st0_tag == TW_Valid) && (st0_ptr->sign == SIGN_POS) )
+  else if ( ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal))
+	    && ( signpositive(st0_ptr) ) )
     {
-      if ( st0_ptr->exp >= EXP_BIAS )
+      if ( exponent(st0_ptr) >= 0 )
 	{
-	  if ( (st0_ptr->exp == EXP_BIAS) &&
+	  if ( (exponent(st0_ptr) == 0) &&
 	      (st0_ptr->sigh == 0x80000000) &&
 	      (st0_ptr->sigl == 0) )
 	    {
 	      /* st(0) holds 1.0 */
 	      /* infinity*log(1) */
-	      if ( !arith_invalid(st1_ptr) )
-		pop();
-	      return;
+	      if ( arith_invalid(1) < 0 )
+		return;
 	    }
-	  /* st(0) is positive and > 1.0 */
-	  pop();
+	  /* else st(0) is positive and > 1.0 */
 	}
       else
 	{
 	  /* st(0) is positive and < 1.0 */
 
-#ifdef DENORM_OPERAND
-	  if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+	  if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
 	    return;
-#endif DENORM_OPERAND
 
-	  st1_ptr->sign ^= SIGN_NEG;
-	  pop();
+	  changesign(st1_ptr);
 	}
-      return;
     }
   else
     {
       /* st(0) must be zero or negative */
-      if ( st0_ptr->tag == TW_Zero )
+      if ( st0_tag == TAG_Zero )
 	{
 	  /* This should be invalid, but a real 80486 is happy with it. */
+
 #ifndef PECULIAR_486
-	  if ( !divide_by_zero(st1_ptr->sign, st1_ptr) )
-#endif PECULIAR_486
-	    {
-	      st1_ptr->sign ^= SIGN_NEG^SIGN_POS;
-	      pop();
-	    }
-	}
-      else
-	{
-	  /* log(negative) */
-	  if ( !arith_invalid(st1_ptr) )
-	    pop();
+	  sign = getsign(st1_ptr);
+	  if ( FPU_divide_by_zero(1, sign) < 0 )
+	    return;
+#endif /* PECULIAR_486 */
+
+	  changesign(st1_ptr);
 	}
-      return;
+      else if ( arith_invalid(1) < 0 )	  /* log(negative) */
+	return;
     }
+
+  FPU_pop();
 }
 
 
-static void fpatan(FPU_REG *st0_ptr)
+static void fpatan(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  char st0_tag = st0_ptr->tag;
   FPU_REG *st1_ptr = &st(1);
-  char st1_tag = st1_ptr->tag;
+  u_char st1_tag = FPU_gettagi(1);
+  int tag;
 
   clear_C1();
-  if ( !((st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
+  if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
     {
-#ifdef DENORM_OPERAND
-      if ( ((st0_ptr->exp <= EXP_UNDER) ||
-	    (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()) )
-	return;
-#endif DENORM_OPERAND
+    valid_atan:
 
-      poly_atan(st0_ptr, st1_ptr, st1_ptr);
+      poly_atan(st0_ptr, st0_tag, st1_ptr, st1_tag);
 
-      if ( st1_ptr->exp <= EXP_UNDER )
-	{
-	  /* A denormal result has been produced.
-	     Precision must have been lost.
-	     This is by definition an underflow. */
-	  arith_underflow(st1_ptr);
-	  pop();
-	  return;
-	}
+      FPU_pop();
+
+      return;
+    }
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+  if ( st1_tag == TAG_Special )
+    st1_tag = FPU_Special(st1_ptr);
+
+  if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
+	    || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
+	    || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )
+    {
+      if ( denormal_operand() < 0 )
+	return;
+
+      goto valid_atan;
     }
-  else if ( (st0_tag == TW_Empty) || (st1_tag == TW_Empty) )
+  else if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) )
     {
-      stack_underflow_pop(1);
+      FPU_stack_underflow_pop(1);
       return;
     }
   else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) )
     {
-      if ( !real_2op_NaN(st0_ptr, st1_ptr, st1_ptr) )
-	  pop();
+      if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) >= 0 )
+	  FPU_pop();
       return;
     }
   else if ( (st0_tag == TW_Infinity) || (st1_tag == TW_Infinity) )
     {
-      char sign = st1_ptr->sign;
+      u_char sign = getsign(st1_ptr);
       if ( st0_tag == TW_Infinity )
 	{
 	  if ( st1_tag == TW_Infinity )
 	    {
-	      if ( st0_ptr->sign == SIGN_POS )
-		{ reg_move(&CONST_PI4, st1_ptr); }
+	      if ( signpositive(st0_ptr) )
+		{
+		  FPU_copy_to_reg1(&CONST_PI4, TAG_Valid);
+		}
 	      else
-		reg_add(&CONST_PI4, &CONST_PI2, st1_ptr, FULL_PRECISION);
+		{
+		  setpositive(st1_ptr);
+		  tag = FPU_u_add(&CONST_PI4, &CONST_PI2, st1_ptr,
+				  FULL_PRECISION, SIGN_POS,
+				  exponent(&CONST_PI4), exponent(&CONST_PI2));
+		  if ( tag >= 0 )
+		    FPU_settagi(1, tag);
+		}
 	    }
 	  else
 	    {
-#ifdef DENORM_OPERAND
-	      if ( st1_tag != TW_Zero )
-		{
-		  if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
-		    return;
-		}
-#endif DENORM_OPERAND
+	      if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
+		return;
 
-	      if ( st0_ptr->sign == SIGN_POS )
+	      if ( signpositive(st0_ptr) )
 		{
-		  reg_move(&CONST_Z, st1_ptr);
-		  st1_ptr->sign = sign;   /* An 80486 preserves the sign */
-		  pop();
+		  FPU_copy_to_reg1(&CONST_Z, TAG_Zero);
+		  setsign(st1_ptr, sign);   /* An 80486 preserves the sign */
+		  FPU_pop();
 		  return;
 		}
 	      else
-		reg_move(&CONST_PI, st1_ptr);
+		{
+		  FPU_copy_to_reg1(&CONST_PI, TAG_Valid);
+		}
 	    }
 	}
       else
 	{
 	  /* st(1) is infinity, st(0) not infinity */
-#ifdef DENORM_OPERAND
-	  if ( st0_tag != TW_Zero )
-	    {
-	      if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
-		return;
-	    }
-#endif DENORM_OPERAND
+	  if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
+	    return;
 
-	  reg_move(&CONST_PI2, st1_ptr);
+	  FPU_copy_to_reg1(&CONST_PI2, TAG_Valid);
 	}
-      st1_ptr->sign = sign;
+      setsign(st1_ptr, sign);
     }
-  else if ( st1_tag == TW_Zero )
+  else if ( st1_tag == TAG_Zero )
     {
       /* st(0) must be valid or zero */
-      char sign = st1_ptr->sign;
+      u_char sign = getsign(st1_ptr);
+
+      if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
+	return;
 
-#ifdef DENORM_OPERAND
-      if ( st0_tag != TW_Zero )
+      if ( signpositive(st0_ptr) )
 	{
-	  if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
-	    return;
+	  /* An 80486 preserves the sign */
+	  FPU_pop();
+	  return;
 	}
-#endif DENORM_OPERAND
 
-      if ( st0_ptr->sign == SIGN_POS )
-	{ /* An 80486 preserves the sign */ pop(); return; }
-      else
-	reg_move(&CONST_PI, st1_ptr);
-      st1_ptr->sign = sign;
+      FPU_copy_to_reg1(&CONST_PI, TAG_Valid);
+      setsign(st1_ptr, sign);
     }
-  else if ( st0_tag == TW_Zero )
+  else if ( st0_tag == TAG_Zero )
     {
-      /* st(1) must be TW_Valid here */
-      char sign = st1_ptr->sign;
+      /* st(1) must be TAG_Valid here */
+      u_char sign = getsign(st1_ptr);
 
-#ifdef DENORM_OPERAND
-      if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+      if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
 	return;
-#endif DENORM_OPERAND
 
-      reg_move(&CONST_PI2, st1_ptr);
-      st1_ptr->sign = sign;
+      FPU_copy_to_reg1(&CONST_PI2, TAG_Valid);
+      setsign(st1_ptr, sign);
     }
 #ifdef PARANOID
   else
     EXCEPTION(EX_INTERNAL | 0x125);
-#endif PARANOID
+#endif /* PARANOID */
 
-  pop();
+  FPU_pop();
   set_precision_flag_up();  /* We do not really know if up or down */
 }
 
 
-static void fprem(FPU_REG *st0_ptr)
+static void fprem(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  do_fprem(st0_ptr, RC_CHOP);
+  do_fprem(st0_ptr, st0_tag, RC_CHOP);
 }
 
 
-static void fprem1(FPU_REG *st0_ptr)
+static void fprem1(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  do_fprem(st0_ptr, RC_RND);
+  do_fprem(st0_ptr, st0_tag, RC_RND);
 }
 
 
-static void fyl2xp1(FPU_REG *st0_ptr)
+static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  char st0_tag = st0_ptr->tag, sign;
-  FPU_REG *st1_ptr = &st(1);
-  char st1_tag = st1_ptr->tag;
+  u_char sign, sign1;
+  FPU_REG *st1_ptr = &st(1), a, b;
+  u_char st1_tag = FPU_gettagi(1);
 
   clear_C1();
-  if ( !((st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
+  if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
     {
-#ifdef DENORM_OPERAND
-      if ( ((st0_ptr->exp <= EXP_UNDER) ||
-	    (st1_ptr->exp <= EXP_UNDER)) && denormal_operand() )
+    valid_yl2xp1:
+
+      sign = getsign(st0_ptr);
+      sign1 = getsign(st1_ptr);
+
+      FPU_to_exp16(st0_ptr, &a);
+      FPU_to_exp16(st1_ptr, &b);
+
+      if ( poly_l2p1(sign, sign1, &a, &b, st1_ptr) )
 	return;
-#endif DENORM_OPERAND
 
-      if ( poly_l2p1(st0_ptr, st1_ptr, st1_ptr) )
-	{
-#ifdef PECULIAR_486   /* Stupid 80486 doesn't worry about log(negative). */
-	  st1_ptr->sign ^= SIGN_POS^SIGN_NEG;
-#else
-	  if ( arith_invalid(st1_ptr) )  /* poly_l2p1() returned invalid */
-	    return;
-#endif PECULIAR_486
-	}
-      if ( st1_ptr->exp <= EXP_UNDER )
-	{
-	  /* A denormal result has been produced.
-	     Precision must have been lost, this is always
-	     an underflow. */
-	  sign = st1_ptr->sign;
-	  arith_underflow(st1_ptr);
-	  st1_ptr->sign = sign;
-	}
-      else
-	set_precision_flag_up();   /* 80486 appears to always do this */
-      pop();
+      FPU_pop();
       return;
     }
-  else if ( (st0_tag == TW_Empty) | (st1_tag == TW_Empty) )
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+  if ( st1_tag == TAG_Special )
+    st1_tag = FPU_Special(st1_ptr);
+
+  if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
+	    || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
+	    || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )
     {
-      stack_underflow_pop(1);
+      if ( denormal_operand() < 0 )
+	return;
+
+      goto valid_yl2xp1;
+    }
+  else if ( (st0_tag == TAG_Empty) | (st1_tag == TAG_Empty) )
+    {
+      FPU_stack_underflow_pop(1);
       return;
     }
-  else if ( st0_tag == TW_Zero )
+  else if ( st0_tag == TAG_Zero )
     {
-      if ( st1_tag <= TW_Zero )
+      switch ( st1_tag )
 	{
-#ifdef DENORM_OPERAND
-	  if ( (st1_tag == TW_Valid) && (st1_ptr->exp <= EXP_UNDER) &&
-	      (denormal_operand()) )
+	case TW_Denormal:
+	  if ( denormal_operand() < 0 )
 	    return;
-#endif DENORM_OPERAND
-	  
-	  st0_ptr->sign ^= st1_ptr->sign;
-	  reg_move(st0_ptr, st1_ptr);
-	}
-      else if ( st1_tag == TW_Infinity )
-	{
+
+	case TAG_Zero:
+	case TAG_Valid:
+	  setsign(st0_ptr, getsign(st0_ptr) ^ getsign(st1_ptr));
+	  FPU_copy_to_reg1(st0_ptr, st0_tag);
+	  break;
+
+	case TW_Infinity:
 	  /* Infinity*log(1) */
-	  if ( !arith_invalid(st1_ptr) )
-	    pop();
-	  return;
-	}
-      else if ( st1_tag == TW_NaN )
-	{
-	  if ( !real_2op_NaN(st0_ptr, st1_ptr, st1_ptr) )
-	    pop();
-	  return;
-	}
+	  if ( arith_invalid(1) < 0 )
+	    return;
+	  break;
+
+	case TW_NaN:
+	  if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
+	    return;
+	  break;
+
+	default:
 #ifdef PARANOID
-      else
-	{
 	  EXCEPTION(EX_INTERNAL | 0x116);
 	  return;
+#endif /* PARANOID */
+	  break;
 	}
-#endif PARANOID
-      pop(); return;
     }
-  else if ( st0_tag == TW_Valid )
+  else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
     {
-      if ( st1_tag == TW_Zero )
+      switch ( st1_tag )
 	{
-	  if ( st0_ptr->sign == SIGN_NEG )
+	case TAG_Zero:
+	  if ( signnegative(st0_ptr) )
 	    {
-	      if ( st0_ptr->exp >= EXP_BIAS )
+	      if ( exponent(st0_ptr) >= 0 )
 		{
 		  /* st(0) holds <= -1.0 */
 #ifdef PECULIAR_486   /* Stupid 80486 doesn't worry about log(negative). */
-		  st1_ptr->sign ^= SIGN_POS^SIGN_NEG;
+		  changesign(st1_ptr);
 #else
-		  if ( arith_invalid(st1_ptr) ) return;
-#endif PECULIAR_486
-		  pop(); return;
+		  if ( arith_invalid(1) < 0 )
+		    return;
+#endif /* PECULIAR_486 */
 		}
-#ifdef DENORM_OPERAND
-	      if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+	      else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
 		return;
-#endif DENORM_OPERAND
-	      st1_ptr->sign ^= SIGN_POS^SIGN_NEG;
-	      pop(); return;
+	      else
+		changesign(st1_ptr);
 	    }
-#ifdef DENORM_OPERAND
-	  if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+	  else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
 	    return;
-#endif DENORM_OPERAND
-	  pop(); return;
-	}
-      if ( st1_tag == TW_Infinity )
-	{
-	  if ( st0_ptr->sign == SIGN_NEG )
+	  break;
+
+	case TW_Infinity:
+	  if ( signnegative(st0_ptr) )
 	    {
-	      if ( (st0_ptr->exp >= EXP_BIAS) &&
+	      if ( (exponent(st0_ptr) >= 0) &&
 		  !((st0_ptr->sigh == 0x80000000) &&
 		    (st0_ptr->sigl == 0)) )
 		{
 		  /* st(0) holds < -1.0 */
 #ifdef PECULIAR_486   /* Stupid 80486 doesn't worry about log(negative). */
-		  st1_ptr->sign ^= SIGN_POS^SIGN_NEG;
+		  changesign(st1_ptr);
 #else
-		  if ( arith_invalid(st1_ptr) ) return;
-#endif PECULIAR_486
-		  pop(); return;
+		  if ( arith_invalid(1) < 0 ) return;
+#endif /* PECULIAR_486 */
 		}
-#ifdef DENORM_OPERAND
-	      if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+	      else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
 		return;
-#endif DENORM_OPERAND
-	      st1_ptr->sign ^= SIGN_POS^SIGN_NEG;
-	      pop(); return;
+	      else
+		changesign(st1_ptr);
 	    }
-#ifdef DENORM_OPERAND
-	  if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+	  else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
+	    return;
+	  break;
+
+	case TW_NaN:
+	  if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
 	    return;
-#endif DENORM_OPERAND
-	  pop(); return;
-	}
-      if ( st1_tag == TW_NaN )
-	{
-	  if ( !real_2op_NaN(st0_ptr, st1_ptr, st1_ptr) )
-	    pop();
-	  return;
 	}
+
     }
   else if ( st0_tag == TW_NaN )
     {
-      if ( !real_2op_NaN(st0_ptr, st1_ptr, st1_ptr) )
-	pop();
-      return;
+      if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
+	return;
     }
   else if ( st0_tag == TW_Infinity )
     {
       if ( st1_tag == TW_NaN )
 	{
-	  if ( !real_2op_NaN(st0_ptr, st1_ptr, st1_ptr) )
-	    pop();
-	  return;
+	  if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
+	    return;
 	}
-      else if ( st0_ptr->sign == SIGN_NEG )
+      else if ( signnegative(st0_ptr) )
 	{
-	  int exponent = st1_ptr->exp;
 #ifndef PECULIAR_486
 	  /* This should have higher priority than denormals, but... */
-	  if ( arith_invalid(st1_ptr) )  /* log(-infinity) */
+	  if ( arith_invalid(1) < 0 )  /* log(-infinity) */
+	    return;
+#endif /* PECULIAR_486 */
+	  if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
 	    return;
-#endif PECULIAR_486
-#ifdef DENORM_OPERAND
-	  if ( st1_tag != TW_Zero )
-	    {
-	      if ( (exponent <= EXP_UNDER) && (denormal_operand()) )
-		return;
-	    }
-#endif DENORM_OPERAND
 #ifdef PECULIAR_486
 	  /* Denormal operands actually get higher priority */
-	  if ( arith_invalid(st1_ptr) )  /* log(-infinity) */
+	  if ( arith_invalid(1) < 0 )  /* log(-infinity) */
 	    return;
-#endif PECULIAR_486
-	  pop();
-	  return;
+#endif /* PECULIAR_486 */
 	}
-      else if ( st1_tag == TW_Zero )
+      else if ( st1_tag == TAG_Zero )
 	{
 	  /* log(infinity) */
-	  if ( !arith_invalid(st1_ptr) )
-	    pop();
-	  return;
+	  if ( arith_invalid(1) < 0 )
+	    return;
 	}
 	
       /* st(1) must be valid here. */
 
-#ifdef DENORM_OPERAND
-      if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+      else if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
 	return;
-#endif DENORM_OPERAND
 
       /* The Manual says that log(Infinity) is invalid, but a real
 	 80486 sensibly says that it is o.k. */
-      { char sign = st1_ptr->sign;
-	reg_move(&CONST_INF, st1_ptr);
-	st1_ptr->sign = sign;
-      }
-      pop();
-      return;
+      else
+	{
+	  u_char sign = getsign(st1_ptr);
+	  FPU_copy_to_reg1(&CONST_INF, TAG_Special);
+	  setsign(st1_ptr, sign);
+	}
     }
 #ifdef PARANOID
   else
     {
       EXCEPTION(EX_INTERNAL | 0x117);
+      return;
     }
-#endif PARANOID
+#endif /* PARANOID */
+
+  FPU_pop();
+  return;
+
 }
 
 
-static void fscale(FPU_REG *st0_ptr)
+static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
 {
-  char st0_tag = st0_ptr->tag;
   FPU_REG *st1_ptr = &st(1);
-  char st1_tag = st1_ptr->tag;
+  u_char st1_tag = FPU_gettagi(1);
   int old_cw = control_word;
-  char sign = st0_ptr->sign;
+  u_char sign = getsign(st0_ptr);
 
   clear_C1();
-  if ( !((st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
+  if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
     {
       long scale;
       FPU_REG tmp;
 
-#ifdef DENORM_OPERAND
-      if ( ((st0_ptr->exp <= EXP_UNDER) ||
-	    (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()) )
-	return;
-#endif DENORM_OPERAND
+      /* Convert register for internal use. */
+      setexponent16(st0_ptr, exponent(st0_ptr));
+
+    valid_scale:
 
-      if ( st1_ptr->exp > EXP_BIAS + 30 )
+      if ( exponent(st1_ptr) > 18 )
 	{
-	  /* 2^31 is far too large, would require 2^(2^30) or 2^(-2^30) */
-	  char sign;
+	  /* 2^18 is far too large, would require 2^(2^17) or 2^(-2^17) */
 
-	  if ( st1_ptr->sign == SIGN_POS )
+	outrange_scale:
+	  if ( signpositive(st1_ptr) )
 	    {
 	      EXCEPTION(EX_Overflow);
-	      sign = st0_ptr->sign;
-	      reg_move(&CONST_INF, st0_ptr);
-	      st0_ptr->sign = sign;
+	      FPU_copy_to_reg0(&CONST_INF, TAG_Special);
 	    }
 	  else
 	    {
 	      EXCEPTION(EX_Underflow);
-	      sign = st0_ptr->sign;
-	      reg_move(&CONST_Z, st0_ptr);
-	      st0_ptr->sign = sign;
+	      FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
 	    }
+	  setsign(st0_ptr, sign);
 	  return;
 	}
 
       control_word &= ~CW_RC;
       control_word |= RC_CHOP;
-      reg_move(st1_ptr, &tmp);
-      round_to_int(&tmp);               /* This can never overflow here */
+      reg_copy(st1_ptr, &tmp);
+      FPU_round_to_int(&tmp, st1_tag);      /* This can never overflow here */
       control_word = old_cw;
-      scale = st1_ptr->sign ? -tmp.sigl : tmp.sigl;
-      scale += st0_ptr->exp;
-      st0_ptr->exp = scale;
+      scale = signnegative(st1_ptr) ? -tmp.sigl : tmp.sigl;
+      scale += exponent16(st0_ptr);
+      if ( (scale > 0x7000) || (scale < -0x7000) )
+	goto outrange_scale;
 
-      /* Use round_reg() to properly detect under/overflow etc */
-      round_reg(st0_ptr, 0, control_word);
+      setexponent16(st0_ptr, scale);
+
+      /* Use FPU_round() to properly detect remaining cases of
+	 under/overflow etc */
+      FPU_round(st0_ptr, 0, 0, control_word, sign);
 
       return;
     }
-  else if ( st0_tag == TW_Valid )
+
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
+  if ( st1_tag == TAG_Special )
+    st1_tag = FPU_Special(st1_ptr);
+
+  if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
     {
-      if ( st1_tag == TW_Zero )
+      switch ( st1_tag )
 	{
-
-#ifdef DENORM_OPERAND
-	  if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+	case TAG_Valid:
+	  /* st(0) must be a denormal */
+	  if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
 	    return;
-#endif DENORM_OPERAND
 
+	  FPU_to_exp16(st0_ptr, st0_ptr);  /* Will not be left on stack */
+	  goto valid_scale;
+
+	case TAG_Zero:
+	  if ( st0_tag == TW_Denormal )
+	    denormal_operand();
 	  return;
-	}
-      if ( st1_tag == TW_Infinity )
-	{
-#ifdef DENORM_OPERAND
-	  if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
+
+	case TW_Denormal:
+	  denormal_operand();
+	  return;
+
+	case TW_Infinity:
+	  if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
 	    return;
-#endif DENORM_OPERAND
 
-	  if ( st1_ptr->sign == SIGN_POS )
-	    { reg_move(&CONST_INF, st0_ptr); }
+	  if ( signpositive(st1_ptr) )
+	    FPU_copy_to_reg0(&CONST_INF, TAG_Special);
 	  else
-	      reg_move(&CONST_Z, st0_ptr);
-	  st0_ptr->sign = sign;
+	    FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
+	  setsign(st0_ptr, sign);
+	  return;
+
+	case TW_NaN:
+	  real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
 	  return;
 	}
-      if ( st1_tag == TW_NaN )
-	{ real_2op_NaN(st0_ptr, st1_ptr, st0_ptr); return; }
     }
-  else if ( st0_tag == TW_Zero )
+  else if ( st0_tag == TAG_Zero )
     {
-      if ( st1_tag == TW_Valid )
+      switch ( st1_tag )
 	{
+	case TAG_Valid:
+	case TAG_Zero:
+	  return;
 
-#ifdef DENORM_OPERAND
-	  if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
-	    return;
-#endif DENORM_OPERAND
+	case TW_Denormal:
+	  denormal_operand();
+	  return;
 
+	case TW_Infinity:
+	  if ( signpositive(st1_ptr) )
+	    arith_invalid(0); /* Zero scaled by +Infinity */
+	  return;
+
+	case TW_NaN:
+	  real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
 	  return;
 	}
-      else if ( st1_tag == TW_Zero ) { return; }
-      else if ( st1_tag == TW_Infinity )
-	{
-	  if ( st1_ptr->sign == SIGN_NEG )
-	    return;
-	  else
-	    {
-	      arith_invalid(st0_ptr); /* Zero scaled by +Infinity */
-	      return;
-	    }
-	}
-      else if ( st1_tag == TW_NaN )
-	{ real_2op_NaN(st0_ptr, st1_ptr, st0_ptr); return; }
     }
   else if ( st0_tag == TW_Infinity )
     {
-      if ( st1_tag == TW_Valid )
+      switch ( st1_tag )
 	{
+	case TAG_Valid:
+	case TAG_Zero:
+	  return;
 
-#ifdef DENORM_OPERAND
-	  if ( (st1_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
-	    return;
-#endif DENORM_OPERAND
+	case TW_Denormal:
+	  denormal_operand();
+	  return;
 
+	case TW_Infinity:
+	  if ( signnegative(st1_ptr) )
+	    arith_invalid(0); /* Infinity scaled by -Infinity */
 	  return;
-	}
-      if ( ((st1_tag == TW_Infinity) && (st1_ptr->sign == SIGN_POS))
-	  || (st1_tag == TW_Zero) )
-	return;
-      else if ( st1_tag == TW_Infinity )
-	{
-	  arith_invalid(st0_ptr); /* Infinity scaled by -Infinity */
+
+	case TW_NaN:
+	  real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
 	  return;
 	}
-      else if ( st1_tag == TW_NaN )
-	{ real_2op_NaN(st0_ptr, st1_ptr, st0_ptr); return; }
     }
   else if ( st0_tag == TW_NaN )
     {
-      if ( st1_tag != TW_Empty )
-	{ real_2op_NaN(st0_ptr, st1_ptr, st0_ptr); return; }
+      if ( st1_tag != TAG_Empty )
+	{ real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr); return; }
     }
 
 #ifdef PARANOID
-  if ( !((st0_tag == TW_Empty) || (st1_tag == TW_Empty)) )
+  if ( !((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) )
     {
       EXCEPTION(EX_INTERNAL | 0x115);
       return;
@@ -1690,7 +1820,7 @@
 #endif
 
   /* At least one of st(0), st(1) must be empty */
-  stack_underflow();
+  FPU_stack_underflow();
 
 }
 
@@ -1698,21 +1828,22 @@
 /*---------------------------------------------------------------------------*/
 
 static FUNC_ST0 const trig_table_a[] = {
-  f2xm1, fyl2x, fptan, fpatan, fxtract, fprem1, fdecstp, fincstp
+  f2xm1, fyl2x, fptan, fpatan,
+  fxtract, fprem1, (FUNC_ST0)fdecstp, (FUNC_ST0)fincstp
 };
 
-void trig_a(void)
+void FPU_triga(void)
 {
-  (trig_table_a[FPU_rm])(&st(0));
+  (trig_table_a[FPU_rm])(&st(0), FPU_gettag0());
 }
 
 
 static FUNC_ST0 const trig_table_b[] =
   {
-    fprem, fyl2xp1, fsqrt_, fsincos, frndint_, fscale, fsin, fcos
+    fprem, fyl2xp1, fsqrt_, fsincos, frndint_, fscale, (FUNC_ST0)fsin, fcos
   };
 
-void trig_b(void)
+void FPU_trigb(void)
 {
-  (trig_table_b[FPU_rm])(&st(0));
+  (trig_table_b[FPU_rm])(&st(0), FPU_gettag0());
 }
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/get_address.c linux-2.0.40/arch/i386/math-emu/get_address.c
--- linux-2.0.39/arch/i386/math-emu/get_address.c	Fri Aug 19 07:54:01 1994
+++ linux-2.0.40/arch/i386/math-emu/get_address.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  | Get the effective address from an FPU instruction.                        |
  |                                                                           |
- | Copyright (C) 1992,1993,1994                                              |
+ | Copyright (C) 1992,1993,1994,1997                                         |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                       Australia.  E-mail   billm@suburbia.net             |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -19,9 +19,6 @@
 
 
 #include <linux/stddef.h>
-#include <linux/head.h>
-
-#include <asm/segment.h>
 
 #include "fpu_system.h"
 #include "exception.h"
@@ -41,7 +38,7 @@
 	offsetof(struct info,___edi)
 };
 
-#define REG_(x) (*(long *)(reg_offset[(x)]+(char *) FPU_info))
+#define REG_(x) (*(long *)(reg_offset[(x)]+(u_char *) FPU_info))
 
 static int reg_offset_vm86[] = {
 	offsetof(struct info,___cs),
@@ -54,31 +51,35 @@
       };
 
 #define VM86_REG_(x) (*(unsigned short *) \
-		      (reg_offset_vm86[((unsigned)x)]+(char *) FPU_info))
+		      (reg_offset_vm86[((unsigned)x)]+(u_char *) FPU_info))
+
+/* These are dummy, fs and gs are not saved on the stack. */
+#define ___FS ___ds
+#define ___GS ___ds
 
 static int reg_offset_pm[] = {
 	offsetof(struct info,___cs),
 	offsetof(struct info,___ds),
 	offsetof(struct info,___es),
-	offsetof(struct info,___fs),
-	offsetof(struct info,___gs),
+	offsetof(struct info,___FS),
+	offsetof(struct info,___GS),
 	offsetof(struct info,___ss),
 	offsetof(struct info,___ds)
       };
 
 #define PM_REG_(x) (*(unsigned short *) \
-		      (reg_offset_pm[((unsigned)x)]+(char *) FPU_info))
+		      (reg_offset_pm[((unsigned)x)]+(u_char *) FPU_info))
 
 
 /* Decode the SIB byte. This function assumes mod != 0 */
 static int sib(int mod, unsigned long *fpu_eip)
 {
-  unsigned char ss,index,base;
+  u_char ss,index,base;
   long offset;
 
   RE_ENTRANT_CHECK_OFF;
   FPU_code_verify_area(1);
-  base = get_fs_byte((char *) (*fpu_eip));   /* The SIB byte */
+  FPU_get_user(base, (u_char *) (*fpu_eip));   /* The SIB byte */
   RE_ENTRANT_CHECK_ON;
   (*fpu_eip)++;
   ss = base >> 6;
@@ -105,18 +106,22 @@
   if (mod == 1)
     {
       /* 8 bit signed displacement */
+      long displacement;
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(1);
-      offset += (signed char) get_fs_byte((char *) (*fpu_eip));
+      FPU_get_user(displacement, (signed char *) (*fpu_eip));
+      offset += displacement;
       RE_ENTRANT_CHECK_ON;
       (*fpu_eip)++;
     }
   else if (mod == 2 || base == 5) /* The second condition also has mod==0 */
     {
       /* 32 bit displacement */
+      long displacement;
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(4);
-      offset += (signed) get_fs_long((unsigned long *) (*fpu_eip));
+      FPU_get_user(displacement, (long *) (*fpu_eip));
+      offset += displacement;
       RE_ENTRANT_CHECK_ON;
       (*fpu_eip) += 4;
     }
@@ -125,39 +130,61 @@
 }
 
 
-static unsigned long vm86_segment(unsigned char segment,
-				  unsigned short *selector)
-{ 
+static unsigned long vm86_segment(u_char segment,
+				  struct address *addr)
+{
   segment--;
 #ifdef PARANOID
   if ( segment > PREFIX_SS_ )
     {
       EXCEPTION(EX_INTERNAL|0x130);
-      math_abort(FPU_info,SIGSEGV);
+      math_abort(SIGSEGV);
     }
-#endif PARANOID
-  *selector = VM86_REG_(segment);
+#endif /* PARANOID */
+  addr->selector = VM86_REG_(segment);
   return (unsigned long)VM86_REG_(segment) << 4;
 }
 
 
 /* This should work for 16 and 32 bit protected mode. */
-static long pm_address(unsigned char FPU_modrm, unsigned char segment,
-		       unsigned short *selector, long offset)
+static long pm_address(u_char FPU_modrm, u_char segment,
+		       struct address *addr, long offset)
 { 
   struct desc_struct descriptor;
   unsigned long base_address, limit, address, seg_top;
+  unsigned short selector;
 
   segment--;
+
 #ifdef PARANOID
+  /* segment is unsigned, so this also detects if segment was 0: */
   if ( segment > PREFIX_SS_ )
     {
       EXCEPTION(EX_INTERNAL|0x132);
-      math_abort(FPU_info,SIGSEGV);
+      math_abort(SIGSEGV);
     }
-#endif PARANOID
+#endif /* PARANOID */
 
-  *selector = PM_REG_(segment);
+  switch ( segment )
+    {
+      /* fs and gs aren't used by the kernel, so they still have their
+	 user-space values. */
+    case PREFIX_FS_-1:
+      /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register
+	 in the assembler statement. */
+
+      __asm__("mov %%fs,%0":"=r" (selector));
+      addr->selector = selector;
+      break;
+    case PREFIX_GS_-1:
+      /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register
+	 in the assembler statement. */
+      __asm__("mov %%gs,%0":"=r" (selector));
+      addr->selector = selector;
+      break;
+    default:
+      addr->selector = PM_REG_(segment);
+    }
 
   descriptor = LDT_DESCRIPTOR(PM_REG_(segment));
   base_address = SEG_BASE_ADDR(descriptor);
@@ -211,12 +238,11 @@
 
 */
 
-void *get_address(unsigned char FPU_modrm, unsigned long *fpu_eip,
+void *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
 		  struct address *addr,
-/*		  unsigned short *selector, unsigned long *offset, */
 		  fpu_addr_modes addr_modes)
 {
-  unsigned char mod;
+  u_char mod;
   unsigned rm = FPU_modrm & 7;
   long *cpu_reg_ptr;
   int address = 0;     /* Initialized just to stop compiler warnings. */
@@ -226,7 +252,7 @@
   if ( !addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT)
       && (addr_modes.override.segment == PREFIX_CS_) )
     {
-      math_abort(FPU_info,SIGSEGV);
+      math_abort(SIGSEGV);
     }
 
   addr->selector = FPU_DS;   /* Default, for 32 bit non-segmented mode. */
@@ -248,7 +274,7 @@
 	      /* Special case: disp32 */
 	      RE_ENTRANT_CHECK_OFF;
 	      FPU_code_verify_area(4);
-	      address = get_fs_long((unsigned long *) (*fpu_eip));
+	      FPU_get_user(address, (unsigned long *) (*fpu_eip));
 	      (*fpu_eip) += 4;
 	      RE_ENTRANT_CHECK_ON;
 	      addr->offset = address;
@@ -265,7 +291,7 @@
 	  /* 8 bit signed displacement */
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_code_verify_area(1);
-	  address = (signed char) get_fs_byte((char *) (*fpu_eip));
+	  FPU_get_user(address, (signed char *) (*fpu_eip));
 	  RE_ENTRANT_CHECK_ON;
 	  (*fpu_eip)++;
 	  break;
@@ -273,7 +299,7 @@
 	  /* 32 bit displacement */
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_code_verify_area(4);
-	  address = (signed) get_fs_long((unsigned long *) (*fpu_eip));
+	  FPU_get_user(address, (long *) (*fpu_eip));
 	  (*fpu_eip) += 4;
 	  RE_ENTRANT_CHECK_ON;
 	  break;
@@ -291,13 +317,12 @@
     case 0:
       break;
     case VM86:
-      address += vm86_segment(addr_modes.override.segment,
-			      (unsigned short *)&(addr->selector));
+      address += vm86_segment(addr_modes.override.segment, addr);
       break;
     case PM16:
     case SEG32:
       address = pm_address(FPU_modrm, addr_modes.override.segment,
-			   (unsigned short *)&(addr->selector), address);
+			   addr, address);
       break;
     default:
       EXCEPTION(EX_INTERNAL|0x133);
@@ -307,12 +332,11 @@
 }
 
 
-void *get_address_16(unsigned char FPU_modrm, unsigned long *fpu_eip,
+void *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
 		     struct address *addr,
-/*		     unsigned short *selector, unsigned long *offset, */
 		     fpu_addr_modes addr_modes)
 {
-  unsigned char mod;
+  u_char mod;
   unsigned rm = FPU_modrm & 7;
   int address = 0;     /* Default used for mod == 0 */
 
@@ -321,7 +345,7 @@
   if ( !addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT)
       && (addr_modes.override.segment == PREFIX_CS_) )
     {
-      math_abort(FPU_info,SIGSEGV);
+      math_abort(SIGSEGV);
     }
 
   addr->selector = FPU_DS;   /* Default, for 32 bit non-segmented mode. */
@@ -336,7 +360,7 @@
 	  /* Special case: disp16 */
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_code_verify_area(2);
-	  address = (unsigned short)get_fs_word((unsigned short *) (*fpu_eip));
+	  FPU_get_user(address, (unsigned short *) (*fpu_eip));
 	  (*fpu_eip) += 2;
 	  RE_ENTRANT_CHECK_ON;
 	  goto add_segment;
@@ -346,7 +370,7 @@
       /* 8 bit signed displacement */
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(1);
-      address = (signed char) get_fs_byte((signed char *) (*fpu_eip));
+      FPU_get_user(address, (signed char *) (*fpu_eip));
       RE_ENTRANT_CHECK_ON;
       (*fpu_eip)++;
       break;
@@ -354,7 +378,7 @@
       /* 16 bit displacement */
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(2);
-      address = (unsigned) get_fs_word((unsigned short *) (*fpu_eip));
+      FPU_get_user(address, (unsigned short *) (*fpu_eip));
       (*fpu_eip) += 2;
       RE_ENTRANT_CHECK_ON;
       break;
@@ -407,13 +431,12 @@
     case 0:
       break;
     case VM86:
-      address += vm86_segment(addr_modes.override.segment,
-			      (unsigned short *)&(addr->selector));
+      address += vm86_segment(addr_modes.override.segment, addr);
       break;
     case PM16:
     case SEG32:
       address = pm_address(FPU_modrm, addr_modes.override.segment,
-			   (unsigned short *)&(addr->selector), address);
+			   addr, address);
       break;
     default:
       EXCEPTION(EX_INTERNAL|0x131);
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/load_store.c linux-2.0.40/arch/i386/math-emu/load_store.c
--- linux-2.0.39/arch/i386/math-emu/load_store.c	Thu Jun  2 09:28:26 1994
+++ linux-2.0.40/arch/i386/math-emu/load_store.c	Mon Oct  8 23:54:43 2001
@@ -4,9 +4,9 @@
  | This file contains most of the code to interpret the FPU instructions     |
  | which load and store from user memory.                                    |
  |                                                                           |
- | Copyright (C) 1992,1993,1994                                              |
+ | Copyright (C) 1992,1993,1994,1997,2001                                    |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                       Australia.  E-mail   billm@melbpc.org.au            |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -18,8 +18,6 @@
  |    other processes using the emulator while swapping is in progress.      |
  +---------------------------------------------------------------------------*/
 
-#include <asm/segment.h>
-
 #include "fpu_system.h"
 #include "exception.h"
 #include "fpu_emu.h"
@@ -32,10 +30,10 @@
 #define _PUSH_ 3   /* Need to check for space to push onto stack */
 #define _null_ 4   /* Function illegal or not implemented */
 
-#define pop_0()	{ st0_ptr->tag = TW_Empty; top++; }
+#define pop_0()	{ FPU_settag0(TAG_Empty); FPU_top++; }
 
 
-static unsigned char const type_table[32] = {
+static u_char const type_table[32] = {
   _PUSH_, _PUSH_, _PUSH_, _PUSH_,
   _null_, _null_, _null_, _null_,
   _REG0_, _REG0_, _REG0_, _REG0_,
@@ -46,25 +44,27 @@
   _NONE_, _REG0_, _NONE_, _REG0_
   };
 
-unsigned char const data_sizes_16[32] = {
+u_char const data_sizes_16[32] = {
   4,  4,  8,  2,  0,  0,  0,  0,
   4,  4,  8,  2,  4,  4,  8,  2,
   14, 0, 94, 10,  2, 10,  0,  8,  
   14, 0, 94, 10,  2, 10,  2,  8
 };
 
-unsigned char const data_sizes_32[32] = {
+u_char const data_sizes_32[32] = {
   4,  4,  8,  2,  0,  0,  0,  0,
   4,  4,  8,  2,  4,  4,  8,  2,
   28, 0,108, 10,  2, 10,  0,  8,  
   28, 0,108, 10,  2, 10,  2,  8
 };
 
-int load_store_instr(unsigned char type, fpu_addr_modes addr_modes,
+int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
 		     void *data_address)
 {
   FPU_REG loaded_data;
   FPU_REG *st0_ptr;
+  u_char st0_tag = TAG_Empty;  /* This is just to stop a gcc warning. */
+  u_char loaded_tag;
 
   st0_ptr = NULL;    /* Initialized just to stop compiler warnings. */
 
@@ -73,17 +73,17 @@
       if ( addr_modes.default_mode == SEG32 )
 	{
 	  if ( access_limit < data_sizes_32[type] )
-	    math_abort(FPU_info,SIGSEGV);
+	    math_abort(SIGSEGV);
 	}
       else if ( addr_modes.default_mode == PM16 )
 	{
 	  if ( access_limit < data_sizes_16[type] )
-	    math_abort(FPU_info,SIGSEGV);
+	    math_abort(SIGSEGV);
 	}
 #ifdef PARANOID
       else
 	EXCEPTION(EX_INTERNAL|0x140);
-#endif PARANOID
+#endif /* PARANOID */
     }
 
   switch ( type_table[type] )
@@ -93,13 +93,14 @@
     case _REG0_:
       st0_ptr = &st(0);       /* Some of these instructions pop after
 				 storing */
+      st0_tag = FPU_gettag0();
       break;
     case _PUSH_:
       {
-	st0_ptr = &st(-1);
-	if ( st0_ptr->tag != TW_Empty )
-	  { stack_overflow(); return 0; }
-	top--;
+	if ( FPU_gettagi(-1) != TAG_Empty )
+	  { FPU_stack_overflow(); return 0; }
+	FPU_top--;
+	st0_ptr = &st(0);
       }
       break;
     case _null_:
@@ -109,99 +110,104 @@
     default:
       EXCEPTION(EX_INTERNAL|0x141);
       return 0;
-#endif PARANOID
+#endif /* PARANOID */
     }
 
   switch ( type )
     {
     case 000:       /* fld m32real */
       clear_C1();
-      reg_load_single((float *)data_address, &loaded_data);
-      if ( (loaded_data.tag == TW_NaN) &&
-	  real_2op_NaN(&loaded_data, &loaded_data, &loaded_data) )
+      loaded_tag = FPU_load_single((float *)data_address, &loaded_data);
+      if ( (loaded_tag == TAG_Special)
+	   && isNaN(&loaded_data)
+	   && (real_1op_NaN(&loaded_data) < 0) )
 	{
-	  top++;
+	  FPU_top++;
 	  break;
 	}
-      reg_move(&loaded_data, st0_ptr);
+      FPU_copy_to_reg0(&loaded_data, loaded_tag);
       break;
     case 001:      /* fild m32int */
       clear_C1();
-      reg_load_int32((long *)data_address, st0_ptr);
+      loaded_tag = FPU_load_int32((long *)data_address, &loaded_data);
+      FPU_copy_to_reg0(&loaded_data, loaded_tag);
       break;
     case 002:      /* fld m64real */
       clear_C1();
-      reg_load_double((double *)data_address, &loaded_data);
-      if ( (loaded_data.tag == TW_NaN) &&
-	  real_2op_NaN(&loaded_data, &loaded_data, &loaded_data) )
+      loaded_tag = FPU_load_double((double *)data_address, &loaded_data);
+      if ( (loaded_tag == TAG_Special)
+	   && isNaN(&loaded_data)
+	   && (real_1op_NaN(&loaded_data) < 0) )
 	{
-	  top++;
+	  FPU_top++;
 	  break;
 	}
-      reg_move(&loaded_data, st0_ptr);
+      FPU_copy_to_reg0(&loaded_data, loaded_tag);
       break;
     case 003:      /* fild m16int */
       clear_C1();
-      reg_load_int16((short *)data_address, st0_ptr);
+      loaded_tag = FPU_load_int16((short *)data_address, &loaded_data);
+      FPU_copy_to_reg0(&loaded_data, loaded_tag);
       break;
     case 010:      /* fst m32real */
       clear_C1();
-      reg_store_single((float *)data_address, st0_ptr);
+      FPU_store_single(st0_ptr, st0_tag, (float *)data_address);
       break;
     case 011:      /* fist m32int */
       clear_C1();
-      reg_store_int32((long *)data_address, st0_ptr);
+      FPU_store_int32(st0_ptr, st0_tag, (long *)data_address);
       break;
     case 012:     /* fst m64real */
       clear_C1();
-      reg_store_double((double *)data_address, st0_ptr);
+      FPU_store_double(st0_ptr, st0_tag, (double *)data_address);
       break;
     case 013:     /* fist m16int */
       clear_C1();
-      reg_store_int16((short *)data_address, st0_ptr);
+      FPU_store_int16(st0_ptr, st0_tag, (short *)data_address);
       break;
     case 014:     /* fstp m32real */
       clear_C1();
-      if ( reg_store_single((float *)data_address, st0_ptr) )
+      if ( FPU_store_single(st0_ptr, st0_tag, (float *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
     case 015:     /* fistp m32int */
       clear_C1();
-      if ( reg_store_int32((long *)data_address, st0_ptr) )
+      if ( FPU_store_int32(st0_ptr, st0_tag, (long *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
     case 016:     /* fstp m64real */
       clear_C1();
-      if ( reg_store_double((double *)data_address, st0_ptr) )
+      if ( FPU_store_double(st0_ptr, st0_tag, (double *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
     case 017:     /* fistp m16int */
       clear_C1();
-      if ( reg_store_int16((short *)data_address, st0_ptr) )
+      if ( FPU_store_int16(st0_ptr, st0_tag, (short *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
     case 020:     /* fldenv  m14/28byte */
-      fldenv(addr_modes, (char *)data_address);
+      fldenv(addr_modes, (u_char *)data_address);
       /* Ensure that the values just loaded are not changed by
 	 fix-up operations. */
       return 1;
     case 022:     /* frstor m94/108byte */
-      frstor(addr_modes, (char *)data_address);
+      frstor(addr_modes, (u_char *)data_address);
       /* Ensure that the values just loaded are not changed by
 	 fix-up operations. */
       return 1;
     case 023:     /* fbld m80dec */
       clear_C1();
-      reg_load_bcd((char *)data_address, st0_ptr);
+      loaded_tag = FPU_load_bcd((u_char *)data_address);
+      FPU_settag0(loaded_tag);
       break;
     case 024:     /* fldcw */
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_READ, data_address, 2);
-      control_word = get_fs_word((unsigned short *) data_address);
+      FPU_get_user(control_word, (unsigned short *) data_address);
       RE_ENTRANT_CHECK_ON;
       if ( partial_status & ~control_word & CW_Exceptions )
 	partial_status |= (SW_Summary | SW_Backward);
@@ -209,49 +215,51 @@
 	partial_status &= ~(SW_Summary | SW_Backward);
 #ifdef PECULIAR_486
       control_word |= 0x40;  /* An 80486 appears to always set this bit */
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
       return 1;
     case 025:      /* fld m80real */
       clear_C1();
-      reg_load_extended((long double *)data_address, st0_ptr);
+      loaded_tag = FPU_load_extended((long double *)data_address, 0);
+      FPU_settag0(loaded_tag);
       break;
     case 027:      /* fild m64int */
       clear_C1();
-      reg_load_int64((long long *)data_address, st0_ptr);
+      loaded_tag = FPU_load_int64((long long *)data_address);
+      FPU_settag0(loaded_tag);
       break;
     case 030:     /* fstenv  m14/28byte */
-      fstenv(addr_modes, (char *)data_address);
+      fstenv(addr_modes, (u_char *)data_address);
       return 1;
     case 032:      /* fsave */
-      fsave(addr_modes, (char *)data_address);
+      fsave(addr_modes, (u_char *)data_address);
       return 1;
     case 033:      /* fbstp m80dec */
       clear_C1();
-      if ( reg_store_bcd((char *)data_address, st0_ptr) )
+      if ( FPU_store_bcd(st0_ptr, st0_tag, (u_char *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
     case 034:      /* fstcw m16int */
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE,data_address,2);
-      put_fs_word(control_word, (short *) data_address);
+      FPU_put_user(control_word, (unsigned short *) data_address);
       RE_ENTRANT_CHECK_ON;
       return 1;
     case 035:      /* fstp m80real */
       clear_C1();
-      if ( reg_store_extended((long double *)data_address, st0_ptr) )
+      if ( FPU_store_extended(st0_ptr, st0_tag, (long double *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
     case 036:      /* fstsw m2byte */
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE,data_address,2);
-      put_fs_word(status_word(),(short *) data_address);
+      FPU_put_user(status_word(),(unsigned short *) data_address);
       RE_ENTRANT_CHECK_ON;
       return 1;
     case 037:      /* fistp m64int */
       clear_C1();
-      if ( reg_store_int64((long long *)data_address, st0_ptr) )
+      if ( FPU_store_int64(st0_ptr, st0_tag, (long long *)data_address) )
 	pop_0();  /* pop only if the number was actually stored
 		     (see the 80486 manual p16-28) */
       break;
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/poly.h linux-2.0.40/arch/i386/math-emu/poly.h
--- linux-2.0.39/arch/i386/math-emu/poly.h	Mon Aug  1 07:19:14 1994
+++ linux-2.0.40/arch/i386/math-emu/poly.h	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  |  Header file for the FPU-emu poly*.c source files.                        |
  |                                                                           |
- | Copyright (C) 1994                                                        |
+ | Copyright (C) 1994,1999                                                   |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                       Australia.  E-mail   billm@melbpc.org.au            |
  |                                                                           |
  | Declarations and definitions for functions operating on Xsig (12-byte     |
  | extended-significand) quantities.                                         |
@@ -55,15 +55,20 @@
    actually be in-line.
    */
 
-/* Multiply two fixed-point 32 bit numbers. */
-extern inline void mul_32_32(const unsigned long arg1,
-			     const unsigned long arg2,
-			     unsigned long *out)
+/* Multiply two fixed-point 32 bit numbers, producing a 32 bit result.
+   The answer is the ms word of the product. */
+/* Some versions of gcc make it difficult to stop eax from being clobbered.
+   Merely specifying that it is used doesn't work...
+ */
+extern inline unsigned long mul_32_32(const unsigned long arg1,
+				      const unsigned long arg2)
 {
-  asm volatile ("movl %1,%%eax; mull %2; movl %%edx,%0" \
-		:"=g" (*out) \
-		:"g" (arg1), "g" (arg2) \
-		:"ax","dx");
+  int retval;
+  asm volatile ("mull %2; movl %%edx,%%eax" \
+		:"=a" (retval) \
+		:"0" (arg1), "g" (arg2) \
+		:"dx");
+  return retval;
 }
 
 
@@ -83,7 +88,7 @@
 /* Note: the constraints in the asm statement didn't always work properly
    with gcc 2.5.8.  Changing from using edi to using ecx got around the
    problem, but keep fingers crossed! */
-extern inline int add_two_Xsig(Xsig *dest, const Xsig *x2, long int *exp)
+extern inline void add_two_Xsig(Xsig *dest, const Xsig *x2, long int *exp)
 {
   asm volatile ("movl %2,%%ecx; movl %3,%%esi;
                  movl (%%esi),%%eax; addl %%eax,(%%ecx);
@@ -113,4 +118,4 @@
                :"=g" (*x):"g" (x):"si","ax","cx");
 }
 
-#endif _POLY_H
+#endif /* _POLY_H */
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/poly_2xm1.c linux-2.0.40/arch/i386/math-emu/poly_2xm1.c
--- linux-2.0.39/arch/i386/math-emu/poly_2xm1.c	Mon Aug  1 07:19:14 1994
+++ linux-2.0.40/arch/i386/math-emu/poly_2xm1.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  | Function to compute 2^x-1 by a polynomial approximation.                  |
  |                                                                           |
- | Copyright (C) 1992,1993,1994                                              |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -13,6 +13,7 @@
 #include "exception.h"
 #include "reg_constant.h"
 #include "fpu_emu.h"
+#include "fpu_system.h"
 #include "control_w.h"
 #include "poly.h"
 
@@ -48,26 +49,25 @@
 
 
 /*--- poly_2xm1() -----------------------------------------------------------+
- | Requires an argument which is TW_Valid and < 1.                           |
+ | Requires st(0) which is TAG_Valid and < 1.                                |
  +---------------------------------------------------------------------------*/
-int	poly_2xm1(FPU_REG const *arg, FPU_REG *result)
+int	poly_2xm1(u_char sign, FPU_REG *arg, FPU_REG *result)
 {
-  long int               exponent, shift;
-  unsigned long long     Xll;
-  Xsig                   accumulator, Denom, argSignif;
+  long int              exponent, shift;
+  unsigned long long    Xll;
+  Xsig                  accumulator, Denom, argSignif;
+  u_char                tag;
 
-
-  exponent = arg->exp - EXP_BIAS;
+  exponent = exponent16(arg);
 
 #ifdef PARANOID
-  if (   (exponent >= 0)    	/* Don't want a |number| >= 1.0 */
-      || (arg->tag != TW_Valid) )
+  if ( exponent >= 0 )    	/* Don't want a |number| >= 1.0 */
     {
       /* Number negative, too large, or not Valid. */
       EXCEPTION(EX_INTERNAL|0x127);
       return 1;
     }
-#endif PARANOID
+#endif /* PARANOID */
 
   argSignif.lsw = 0;
   XSIG_LL(argSignif) = Xll = significand(arg);
@@ -94,7 +94,7 @@
   if ( exponent < -2 )
     {
       /* Shift the argument right by the required places. */
-      if ( shrx(&Xll, -2-exponent) >= 0x80000000U )
+      if ( FPU_shrx(&Xll, -2-exponent) >= 0x80000000U )
 	Xll++;	/* round up */
     }
 
@@ -118,7 +118,7 @@
       exponent = 1;
     }
 
-  if ( arg->sign != SIGN_POS )
+  if ( sign != SIGN_POS )
     {
       /* The argument is negative, use the identity:
 	     f(-x) = -f(x) / (1 + f(x))
@@ -142,10 +142,14 @@
   /* Convert to 64 bit signed-compatible */
   exponent += round_Xsig(&accumulator);
 
+  result = &st(0);
   significand(result) = XSIG_LL(accumulator);
-  result->tag = TW_Valid;
-  result->exp = exponent + EXP_BIAS;
-  result->sign = arg->sign;
+  setexponent16(result, exponent);
+
+  tag = FPU_round(result, 1, 0, FULL_PRECISION, sign);
+
+  setsign(result, sign);
+  FPU_settag0(tag);
 
   return 0;
 
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/poly_atan.c linux-2.0.40/arch/i386/math-emu/poly_atan.c
--- linux-2.0.39/arch/i386/math-emu/poly_atan.c	Mon Aug  1 07:19:14 1994
+++ linux-2.0.40/arch/i386/math-emu/poly_atan.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  | Compute the arctan of a FPU_REG, using a polynomial approximation.        |
  |                                                                           |
- | Copyright (C) 1992,1993,1994                                              |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -13,6 +13,7 @@
 #include "exception.h"
 #include "reg_constant.h"
 #include "fpu_emu.h"
+#include "fpu_system.h"
 #include "status_w.h"
 #include "control_w.h"
 #include "poly.h"
@@ -51,31 +52,57 @@
 /*--- poly_atan() -----------------------------------------------------------+
  |                                                                           |
  +---------------------------------------------------------------------------*/
-void	poly_atan(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *result)
+void	poly_atan(FPU_REG *st0_ptr, u_char st0_tag,
+		  FPU_REG *st1_ptr, u_char st1_tag)
 {
-  char		        transformed, inverted,
-                        sign1 = arg1->sign, sign2 = arg2->sign;
-  long int   		exponent, dummy_exp;
-  Xsig                  accumulator, Numer, Denom, accumulatore, argSignif,
-                        argSq, argSqSq;
+  u_char	transformed, inverted,
+                sign1, sign2;
+  int           exponent;
+  long int   	dummy_exp;
+  Xsig          accumulator, Numer, Denom, accumulatore, argSignif,
+                argSq, argSqSq;
+  u_char        tag;
   
+  sign1 = getsign(st0_ptr);
+  sign2 = getsign(st1_ptr);
+  if ( st0_tag == TAG_Valid )
+    {
+      exponent = exponent(st0_ptr);
+    }
+  else
+    {
+      /* This gives non-compatible stack contents... */
+      FPU_to_exp16(st0_ptr, st0_ptr);
+      exponent = exponent16(st0_ptr);
+    }
+  if ( st1_tag == TAG_Valid )
+    {
+      exponent -= exponent(st1_ptr);
+    }
+  else
+    {
+      /* This gives non-compatible stack contents... */
+      FPU_to_exp16(st1_ptr, st1_ptr);
+      exponent -= exponent16(st1_ptr);
+    }
 
-  arg1->sign = arg2->sign = SIGN_POS;
-  if ( (compare(arg2) & ~COMP_Denormal) == COMP_A_lt_B )
+  if ( (exponent < 0) || ((exponent == 0) &&
+			  ((st0_ptr->sigh < st1_ptr->sigh) ||
+			   ((st0_ptr->sigh == st1_ptr->sigh) &&
+			    (st0_ptr->sigl < st1_ptr->sigl))) ) )
     {
       inverted = 1;
-      exponent = arg1->exp - arg2->exp;
       Numer.lsw = Denom.lsw = 0;
-      XSIG_LL(Numer) = significand(arg1);
-      XSIG_LL(Denom) = significand(arg2);
+      XSIG_LL(Numer) = significand(st0_ptr);
+      XSIG_LL(Denom) = significand(st1_ptr);
     }
   else
     {
       inverted = 0;
-      exponent = arg2->exp - arg1->exp;
+      exponent = -exponent;
       Numer.lsw = Denom.lsw = 0;
-      XSIG_LL(Numer) = significand(arg2);
-      XSIG_LL(Denom) = significand(arg1);
+      XSIG_LL(Numer) = significand(st1_ptr);
+      XSIG_LL(Denom) = significand(st0_ptr);
      }
   div_Xsig(&Numer, &Denom, &argSignif);
   exponent += norm_Xsig(&argSignif);
@@ -97,7 +124,7 @@
 	      EXCEPTION(EX_INTERNAL|0x104);  /* There must be a logic error */
 	      return;
 	    }
-#endif PARANOID
+#endif /* PARANOID */
 	  argSignif.msw = 0;   /* Make the transformed arg -> 0.0 */
 	}
       else
@@ -189,9 +216,14 @@
     }
 
   exponent += round_Xsig(&accumulator);
-  significand(result) = XSIG_LL(accumulator);
-  result->exp = exponent + EXP_BIAS;
-  result->tag = TW_Valid;
-  result->sign = sign2;
+
+  significand(st1_ptr) = XSIG_LL(accumulator);
+  setexponent16(st1_ptr, exponent);
+
+  tag = FPU_round(st1_ptr, 1, 0, FULL_PRECISION, sign2);
+  FPU_settagi(1, tag);
+
+  set_precision_flag_up();  /* We do not really know if up or down,
+			       use this as the default. */
 
 }
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/poly_l2.c linux-2.0.40/arch/i386/math-emu/poly_l2.c
--- linux-2.0.39/arch/i386/math-emu/poly_l2.c	Mon Aug  1 07:19:14 1994
+++ linux-2.0.40/arch/i386/math-emu/poly_l2.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  | Compute the base 2 log of a FPU_REG, using a polynomial approximation.    |
  |                                                                           |
- | Copyright (C) 1992,1993,1994                                              |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -14,96 +14,101 @@
 #include "exception.h"
 #include "reg_constant.h"
 #include "fpu_emu.h"
+#include "fpu_system.h"
 #include "control_w.h"
 #include "poly.h"
 
 
-
-static void log2_kernel(FPU_REG const *arg,
+static void log2_kernel(FPU_REG const *arg, u_char argsign,
 			Xsig *accum_result, long int *expon);
 
 
 /*--- poly_l2() -------------------------------------------------------------+
  |   Base 2 logarithm by a polynomial approximation.                         |
  +---------------------------------------------------------------------------*/
-void	poly_l2(FPU_REG const *arg, FPU_REG const *y, FPU_REG *result)
+void	poly_l2(FPU_REG *st0_ptr, FPU_REG *st1_ptr, u_char st1_sign)
 {
   long int	       exponent, expon, expon_expon;
   Xsig                 accumulator, expon_accum, yaccum;
-  char		       sign;
+  u_char		       sign, argsign;
   FPU_REG              x;
+  int                  tag;
 
+  exponent = exponent16(st0_ptr);
 
-  exponent = arg->exp - EXP_BIAS;
-
-  /* From arg, make a number > sqrt(2)/2 and < sqrt(2) */
-  if ( arg->sigh > (unsigned)0xb504f334 )
+  /* From st0_ptr, make a number > sqrt(2)/2 and < sqrt(2) */
+  if ( st0_ptr->sigh > (unsigned)0xb504f334 )
     {
-      /* Treat as  sqrt(2)/2 < arg < 1 */
-      significand(&x) = - significand(arg);
-      x.sign = SIGN_NEG;
-      x.tag = TW_Valid;
-      x.exp = EXP_BIAS-1;
+      /* Treat as  sqrt(2)/2 < st0_ptr < 1 */
+      significand(&x) = - significand(st0_ptr);
+      setexponent16(&x, -1);
       exponent++;
-      normalize(&x);
+      argsign = SIGN_NEG;
     }
   else
     {
-      /* Treat as  1 <= arg < sqrt(2) */
-      x.sigh = arg->sigh - 0x80000000;
-      x.sigl = arg->sigl;
-      x.sign = SIGN_POS;
-      x.tag = TW_Valid;
-      x.exp = EXP_BIAS;
-      normalize(&x);
+      /* Treat as  1 <= st0_ptr < sqrt(2) */
+      x.sigh = st0_ptr->sigh - 0x80000000;
+      x.sigl = st0_ptr->sigl;
+      setexponent16(&x, 0);
+      argsign = SIGN_POS;
     }
+  tag = FPU_normalize_nuo(&x);
 
-  if ( x.tag == TW_Zero )
+  if ( tag == TAG_Zero )
     {
       expon = 0;
       accumulator.msw = accumulator.midw = accumulator.lsw = 0;
     }
   else
     {
-      log2_kernel(&x, &accumulator, &expon);
+      log2_kernel(&x, argsign, &accumulator, &expon);
     }
 
-  sign = exponent < 0;
-  if ( sign ) exponent = -exponent;
+  if ( exponent < 0 )
+    {
+      sign = SIGN_NEG;
+      exponent = -exponent;
+    }
+  else
+    sign = SIGN_POS;
   expon_accum.msw = exponent; expon_accum.midw = expon_accum.lsw = 0;
   if ( exponent )
     {
       expon_expon = 31 + norm_Xsig(&expon_accum);
       shr_Xsig(&accumulator, expon_expon - expon);
 
-      if ( sign ^ (x.sign == SIGN_NEG) )
+      if ( sign ^ argsign )
 	negate_Xsig(&accumulator);
       add_Xsig_Xsig(&accumulator, &expon_accum);
     }
   else
     {
       expon_expon = expon;
-      sign = x.sign;
+      sign = argsign;
     }
 
-  yaccum.lsw = 0; XSIG_LL(yaccum) = significand(y);
+  yaccum.lsw = 0; XSIG_LL(yaccum) = significand(st1_ptr);
   mul_Xsig_Xsig(&accumulator, &yaccum);
 
   expon_expon += round_Xsig(&accumulator);
 
   if ( accumulator.msw == 0 )
     {
-      reg_move(&CONST_Z, y);
-    }
-  else
-    {
-      result->exp = expon_expon + y->exp + 1;
-      significand(result) = XSIG_LL(accumulator);
-      result->tag = TW_Valid; /* set the tags to Valid */
-      result->sign = sign ^ y->sign;
+      FPU_copy_to_reg1(&CONST_Z, TAG_Zero);
+      return;
     }
 
+  significand(st1_ptr) = XSIG_LL(accumulator);
+  setexponent16(st1_ptr, expon_expon + exponent16(st1_ptr) + 1);
+
+  tag = FPU_round(st1_ptr, 1, 0, FULL_PRECISION, sign ^ st1_sign);
+  FPU_settagi(1, tag);
+
+  set_precision_flag_up();  /* 80486 appears to always do this */
+
   return;
+
 }
 
 
@@ -111,47 +116,62 @@
  |   Base 2 logarithm by a polynomial approximation.                         |
  |   log2(x+1)                                                               |
  +---------------------------------------------------------------------------*/
-int	poly_l2p1(FPU_REG const *arg, FPU_REG const *y, FPU_REG *result)
+int	poly_l2p1(u_char sign0, u_char sign1,
+		  FPU_REG *st0_ptr, FPU_REG *st1_ptr, FPU_REG *dest)
 {
-  char                 sign;
-  long int             exponent;
-  Xsig                 accumulator, yaccum;
+  u_char             	tag;
+  long int        	exponent;
+  Xsig              	accumulator, yaccum;
 
-
-  sign = arg->sign;
-
-  if ( arg->exp < EXP_BIAS )
+  if ( exponent16(st0_ptr) < 0 )
     {
-      log2_kernel(arg, &accumulator, &exponent);
+      log2_kernel(st0_ptr, sign0, &accumulator, &exponent);
 
       yaccum.lsw = 0;
-      XSIG_LL(yaccum) = significand(y);
+      XSIG_LL(yaccum) = significand(st1_ptr);
       mul_Xsig_Xsig(&accumulator, &yaccum);
 
       exponent += round_Xsig(&accumulator);
 
-      result->exp = exponent + y->exp + 1;
-      significand(result) = XSIG_LL(accumulator);
-      result->tag = TW_Valid; /* set the tags to Valid */
-      result->sign = sign ^ y->sign;
+      exponent += exponent16(st1_ptr) + 1;
+      if ( exponent < EXP_WAY_UNDER ) exponent = EXP_WAY_UNDER;
+
+      significand(dest) = XSIG_LL(accumulator);
+      setexponent16(dest, exponent);
 
-      return 0;
+      tag = FPU_round(dest, 1, 0, FULL_PRECISION, sign0 ^ sign1);
+      FPU_settagi(1, tag);
+
+      if ( tag == TAG_Valid )
+	set_precision_flag_up();   /* 80486 appears to always do this */
     }
   else
     {
-      /* The magnitude of arg is far too large. */
-      reg_move(y, result);
-      if ( sign != SIGN_POS )
+      /* The magnitude of st0_ptr is far too large. */
+
+      if ( sign0 != SIGN_POS )
 	{
 	  /* Trying to get the log of a negative number. */
-	  return 1;
+#ifdef PECULIAR_486   /* Stupid 80486 doesn't worry about log(negative). */
+	  changesign(st1_ptr);
+#else
+	  if ( arith_invalid(1) < 0 )
+	    return 1;
+#endif /* PECULIAR_486 */
 	}
+
+      /* 80486 appears to do this */
+      if ( sign0 == SIGN_NEG )
+	set_precision_flag_down();
       else
-	{
-	  return 0;
-	}
+	set_precision_flag_up();
     }
 
+  if ( exponent(dest) <= EXP_UNDER )
+    EXCEPTION(EX_Underflow);
+
+  return 0;
+
 }
 
 
@@ -180,20 +200,17 @@
  |   Base 2 logarithm by a polynomial approximation.                         |
  |   log2(x+1)                                                               |
  +---------------------------------------------------------------------------*/
-static void log2_kernel(FPU_REG const *arg, Xsig *accum_result,
+static void log2_kernel(FPU_REG const *arg, u_char argsign, Xsig *accum_result,
 			long int *expon)
 {
-  char                 sign;
   long int             exponent, adj;
   unsigned long long   Xsq;
   Xsig                 accumulator, Numer, Denom, argSignif, arg_signif;
 
-  sign = arg->sign;
-
-  exponent = arg->exp - EXP_BIAS;
+  exponent = exponent16(arg);
   Numer.lsw = Denom.lsw = 0;
   XSIG_LL(Numer) = XSIG_LL(Denom) = significand(arg);
-  if ( sign == SIGN_POS )
+  if ( argsign == SIGN_POS )
     {
       shr_Xsig(&Denom, 2 - (1 + exponent));
       Denom.msw |= 0x80000000;
@@ -226,7 +243,7 @@
 	  /* The argument is too large */
 	}
     }
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 
   arg_signif.lsw = argSignif.lsw; XSIG_LL(arg_signif) = XSIG_LL(argSignif);
   adj = norm_Xsig(&argSignif);
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/poly_sin.c linux-2.0.40/arch/i386/math-emu/poly_sin.c
--- linux-2.0.39/arch/i386/math-emu/poly_sin.c	Mon Aug  1 07:19:15 1994
+++ linux-2.0.40/arch/i386/math-emu/poly_sin.c	Mon Oct  8 23:54:43 2001
@@ -4,9 +4,9 @@
  |  Computation of an approximation of the sin function and the cosine       |
  |  function by a polynomial.                                                |
  |                                                                           |
- | Copyright (C) 1992,1993,1994                                              |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ | Copyright (C) 1992,1993,1994,1997,1999                                    |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@melbpc.org.au                             |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -15,6 +15,7 @@
 #include "exception.h"
 #include "reg_constant.h"
 #include "fpu_emu.h"
+#include "fpu_system.h"
 #include "control_w.h"
 #include "poly.h"
 
@@ -62,35 +63,26 @@
 /*--- poly_sine() -----------------------------------------------------------+
  |                                                                           |
  +---------------------------------------------------------------------------*/
-void	poly_sine(FPU_REG const *arg, FPU_REG *result)
+void	poly_sine(FPU_REG *st0_ptr)
 {
   int                 exponent, echange;
   Xsig                accumulator, argSqrd, argTo4;
   unsigned long       fix_up, adj;
   unsigned long long  fixed_arg;
+  FPU_REG	      result;
 
-
-#ifdef PARANOID
-  if ( arg->tag == TW_Zero )
-    {
-      /* Return 0.0 */
-      reg_move(&CONST_Z, result);
-      return;
-    }
-#endif PARANOID
-
-  exponent = arg->exp - EXP_BIAS;
+  exponent = exponent(st0_ptr);
 
   accumulator.lsw = accumulator.midw = accumulator.msw = 0;
 
   /* Split into two ranges, for arguments below and above 1.0 */
   /* The boundary between upper and lower is approx 0.88309101259 */
-  if ( (exponent < -1) || ((exponent == -1) && (arg->sigh <= 0xe21240aa)) )
+  if ( (exponent < -1) || ((exponent == -1) && (st0_ptr->sigh <= 0xe21240aa)) )
     {
       /* The argument is <= 0.88309101259 */
 
-      argSqrd.msw = arg->sigh; argSqrd.midw = arg->sigl; argSqrd.lsw = 0;
-      mul64_Xsig(&argSqrd, &significand(arg));
+      argSqrd.msw = st0_ptr->sigh; argSqrd.midw = st0_ptr->sigl; argSqrd.lsw = 0;
+      mul64_Xsig(&argSqrd, &significand(st0_ptr));
       shr_Xsig(&argSqrd, 2*(-1-exponent));
       argTo4.msw = argSqrd.msw; argTo4.midw = argSqrd.midw;
       argTo4.lsw = argSqrd.lsw;
@@ -107,29 +99,29 @@
       shr_Xsig(&accumulator, 2);    /* Divide by four */
       accumulator.msw |= 0x80000000;  /* Add 1.0 */
 
-      mul64_Xsig(&accumulator, &significand(arg));
-      mul64_Xsig(&accumulator, &significand(arg));
-      mul64_Xsig(&accumulator, &significand(arg));
+      mul64_Xsig(&accumulator, &significand(st0_ptr));
+      mul64_Xsig(&accumulator, &significand(st0_ptr));
+      mul64_Xsig(&accumulator, &significand(st0_ptr));
 
       /* Divide by four, FPU_REG compatible, etc */
-      exponent = 3*exponent + EXP_BIAS;
+      exponent = 3*exponent;
 
       /* The minimum exponent difference is 3 */
-      shr_Xsig(&accumulator, arg->exp - exponent);
+      shr_Xsig(&accumulator, exponent(st0_ptr) - exponent);
 
       negate_Xsig(&accumulator);
-      XSIG_LL(accumulator) += significand(arg);
+      XSIG_LL(accumulator) += significand(st0_ptr);
 
       echange = round_Xsig(&accumulator);
 
-      result->exp = arg->exp + echange;
+      setexponentpos(&result, exponent(st0_ptr) + echange);
     }
   else
     {
       /* The argument is > 0.88309101259 */
-      /* We use sin(arg) = cos(pi/2-arg) */
+      /* We use sin(st(0)) = cos(pi/2-st(0)) */
 
-      fixed_arg = significand(arg);
+      fixed_arg = significand(st0_ptr);
 
       if ( exponent == 0 )
 	{
@@ -140,6 +132,9 @@
 	}
       /* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */
       fixed_arg = 0x921fb54442d18469LL - fixed_arg;
+      /* There is a special case which arises due to rounding, to fix here. */
+      if ( fixed_arg == 0xffffffffffffffffLL )
+	fixed_arg = 0;
 
       XSIG_LL(argSqrd) = fixed_arg; argSqrd.lsw = 0;
       mul64_Xsig(&argSqrd, &fixed_arg);
@@ -180,10 +175,9 @@
       if ( argSqrd.msw & 0xffc00000 )
 	{
 	  /* Get about 32 bit precision in these: */
-	  mul_32_32(0x898cc517, argSqrd.msw, &adj);
-	  fix_up -= adj/6;
+	  fix_up -= mul_32_32(0x898cc517, argSqrd.msw) / 6;
 	}
-      mul_32_32(fix_up, LL_MSW(fixed_arg), &fix_up);
+      fix_up = mul_32_32(fix_up, LL_MSW(fixed_arg));
 
       adj = accumulator.lsw;    /* temp save */
       accumulator.lsw -= fix_up;
@@ -192,20 +186,20 @@
 
       echange = round_Xsig(&accumulator);
 
-      result->exp = EXP_BIAS - 1 + echange;
+      setexponentpos(&result, echange - 1);
     }
 
-  significand(result) = XSIG_LL(accumulator);
-  result->tag = TW_Valid;
-  result->sign = arg->sign;
+  significand(&result) = XSIG_LL(accumulator);
+  setsign(&result, getsign(st0_ptr));
+  FPU_copy_to_reg0(&result, TAG_Valid);
 
 #ifdef PARANOID
-  if ( (result->exp >= EXP_BIAS)
-      && (significand(result) > 0x8000000000000000LL) )
+  if ( (exponent(&result) >= 0)
+      && (significand(&result) > 0x8000000000000000LL) )
     {
       EXCEPTION(EX_INTERNAL|0x150);
     }
-#endif PARANOID
+#endif /* PARANOID */
 
 }
 
@@ -214,42 +208,35 @@
 /*--- poly_cos() ------------------------------------------------------------+
  |                                                                           |
  +---------------------------------------------------------------------------*/
-void	poly_cos(FPU_REG const *arg, FPU_REG *result)
+void	poly_cos(FPU_REG *st0_ptr)
 {
+  FPU_REG	      result;
   long int            exponent, exp2, echange;
   Xsig                accumulator, argSqrd, fix_up, argTo4;
-  unsigned long       adj;
   unsigned long long  fixed_arg;
 
-
 #ifdef PARANOID
-  if ( arg->tag == TW_Zero )
-    {
-      /* Return 1.0 */
-      reg_move(&CONST_1, result);
-      return;
-    }
-
-  if ( (arg->exp > EXP_BIAS)
-      || ((arg->exp == EXP_BIAS)
-	  && (significand(arg) > 0xc90fdaa22168c234LL)) )
+  if ( (exponent(st0_ptr) > 0)
+      || ((exponent(st0_ptr) == 0)
+	  && (significand(st0_ptr) > 0xc90fdaa22168c234LL)) )
     {
       EXCEPTION(EX_Invalid);
-      reg_move(&CONST_QNaN, result);
+      FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
       return;
     }
-#endif PARANOID
+#endif /* PARANOID */
 
-  exponent = arg->exp - EXP_BIAS;
+  exponent = exponent(st0_ptr);
 
   accumulator.lsw = accumulator.midw = accumulator.msw = 0;
 
-  if ( (exponent < -1) || ((exponent == -1) && (arg->sigh <= 0xb00d6f54)) )
+  if ( (exponent < -1) || ((exponent == -1) && (st0_ptr->sigh <= 0xb00d6f54)) )
     {
       /* arg is < 0.687705 */
 
-      argSqrd.msw = arg->sigh; argSqrd.midw = arg->sigl; argSqrd.lsw = 0;
-      mul64_Xsig(&argSqrd, &significand(arg));
+      argSqrd.msw = st0_ptr->sigh; argSqrd.midw = st0_ptr->sigl;
+      argSqrd.lsw = 0;
+      mul64_Xsig(&argSqrd, &significand(st0_ptr));
 
       if ( exponent < -1 )
 	{
@@ -270,8 +257,8 @@
 		      N_COEFF_PH-1);
       negate_Xsig(&accumulator);
 
-      mul64_Xsig(&accumulator, &significand(arg));
-      mul64_Xsig(&accumulator, &significand(arg));
+      mul64_Xsig(&accumulator, &significand(st0_ptr));
+      mul64_Xsig(&accumulator, &significand(st0_ptr));
       shr_Xsig(&accumulator, -2*(1+exponent));
 
       shr_Xsig(&accumulator, 3);
@@ -290,20 +277,20 @@
       if ( accumulator.msw == 0 )
 	{
 	  /* The result is 1.0 */
-	  reg_move(&CONST_1, result);
+	  FPU_copy_to_reg0(&CONST_1, TAG_Valid);
+	  return;
 	}
       else
 	{
-	  significand(result) = XSIG_LL(accumulator);
+	  significand(&result) = XSIG_LL(accumulator);
       
 	  /* will be a valid positive nr with expon = -1 */
-	  *(short *)&(result->sign) = 0;
-	  result->exp = EXP_BIAS - 1;
+	  setexponentpos(&result, -1);
 	}
     }
   else
     {
-      fixed_arg = significand(arg);
+      fixed_arg = significand(st0_ptr);
 
       if ( exponent == 0 )
 	{
@@ -314,6 +301,9 @@
 	}
       /* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */
       fixed_arg = 0x921fb54442d18469LL - fixed_arg;
+      /* There is a special case which arises due to rounding, to fix here. */
+      if ( fixed_arg == 0xffffffffffffffffLL )
+	fixed_arg = 0;
 
       exponent = -1;
       exp2 = -1;
@@ -377,10 +367,8 @@
       if ( argSqrd.msw & 0xffc00000 )
 	{
 	  /* Get about 32 bit precision in these: */
-	  mul_32_32(0x898cc517, argSqrd.msw, &adj);
-	  fix_up.msw -= adj/2;
-	  mul_32_32(0x898cc517, argTo4.msw, &adj);
-	  fix_up.msw += adj/24;
+	  fix_up.msw -= mul_32_32(0x898cc517, argSqrd.msw) / 2;
+	  fix_up.msw += mul_32_32(0x898cc517, argTo4.msw) / 24;
 	}
 
       exp2 += norm_Xsig(&accumulator);
@@ -392,17 +380,18 @@
 
       echange = round_Xsig(&accumulator);
 
-      result->exp = exp2 + EXP_BIAS + echange;
-      *(short *)&(result->sign) = 0;      /* Is a valid positive nr */
-      significand(result) = XSIG_LL(accumulator);
+      setexponentpos(&result, exp2 + echange);
+      significand(&result) = XSIG_LL(accumulator);
     }
 
+  FPU_copy_to_reg0(&result, TAG_Valid);
+
 #ifdef PARANOID
-  if ( (result->exp >= EXP_BIAS)
-      && (significand(result) > 0x8000000000000000LL) )
+  if ( (exponent(&result) >= 0)
+      && (significand(&result) > 0x8000000000000000LL) )
     {
       EXCEPTION(EX_INTERNAL|0x151);
     }
-#endif PARANOID
+#endif /* PARANOID */
 
 }
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/poly_tan.c linux-2.0.40/arch/i386/math-emu/poly_tan.c
--- linux-2.0.39/arch/i386/math-emu/poly_tan.c	Fri Aug 19 07:54:01 1994
+++ linux-2.0.40/arch/i386/math-emu/poly_tan.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  | Compute the tan of a FPU_REG, using a polynomial approximation.           |
  |                                                                           |
- | Copyright (C) 1992,1993,1994                                              |
+ | Copyright (C) 1992,1993,1994,1997,1999                                    |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                       Australia.  E-mail   billm@melbpc.org.au            |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -13,6 +13,7 @@
 #include "exception.h"
 #include "reg_constant.h"
 #include "fpu_emu.h"
+#include "fpu_system.h"
 #include "control_w.h"
 #include "poly.h"
 
@@ -52,7 +53,7 @@
 /*--- poly_tan() ------------------------------------------------------------+
  |                                                                           |
  +---------------------------------------------------------------------------*/
-void	poly_tan(FPU_REG const *arg, FPU_REG *result)
+void	poly_tan(FPU_REG *st0_ptr)
 {
   long int    		exponent;
   int                   invert;
@@ -60,20 +61,20 @@
                         argSignif, fix_up;
   unsigned long         adj;
 
-  exponent = arg->exp - EXP_BIAS;
+  exponent = exponent(st0_ptr);
 
 #ifdef PARANOID
-  if ( arg->sign != 0 )	/* Can't hack a number < 0.0 */
-    { arith_invalid(result); return; }  /* Need a positive number */
-#endif PARANOID
+  if ( signnegative(st0_ptr) )	/* Can't hack a number < 0.0 */
+    { arith_invalid(0); return; }  /* Need a positive number */
+#endif /* PARANOID */
 
   /* Split the problem into two domains, smaller and larger than pi/4 */
-  if ( (exponent == 0) || ((exponent == -1) && (arg->sigh > 0xc90fdaa2)) )
+  if ( (exponent == 0) || ((exponent == -1) && (st0_ptr->sigh > 0xc90fdaa2)) )
     {
       /* The argument is greater than (approx) pi/4 */
       invert = 1;
       accum.lsw = 0;
-      XSIG_LL(accum) = significand(arg);
+      XSIG_LL(accum) = significand(st0_ptr);
  
       if ( exponent == 0 )
 	{
@@ -83,6 +84,14 @@
 	}
       /* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */
       XSIG_LL(accum) = 0x921fb54442d18469LL - XSIG_LL(accum);
+      /* This is a special case which arises due to rounding. */
+      if ( XSIG_LL(accum) == 0xffffffffffffffffLL )
+	{
+	  FPU_settag0(TAG_Valid);
+	  significand(st0_ptr) = 0x8a51e04daabda360LL;
+	  setexponent16(st0_ptr, (0x41 + EXTENDED_Ebias) | SIGN_Negative);
+	  return;
+	}
 
       argSignif.lsw = accum.lsw;
       XSIG_LL(argSignif) = XSIG_LL(accum);
@@ -92,12 +101,12 @@
     {
       invert = 0;
       argSignif.lsw = 0;
-      XSIG_LL(accum) = XSIG_LL(argSignif) = significand(arg);
+      XSIG_LL(accum) = XSIG_LL(argSignif) = significand(st0_ptr);
  
       if ( exponent < -1 )
 	{
 	  /* shift the argument right by the required places */
-	  if ( shrx(&XSIG_LL(accum), -1-exponent) >= 0x80000000U )
+	  if ( FPU_shrx(&XSIG_LL(accum), -1-exponent) >= 0x80000000U )
 	    XSIG_LL(accum) ++;	/* round up */
 	}
     }
@@ -176,11 +185,11 @@
       else if ( exponent > -30 )
 	{
 	  adj = accum.msw >> -(exponent+1);      /* tan */
-	  mul_32_32(adj, adj, &adj);           /* tan^2 */
+	  adj = mul_32_32(adj, adj);             /* tan^2 */
 	}
       else
 	adj = 0;
-      mul_32_32(0x898cc517, adj, &adj);        /* delta * tan^2 */
+      adj = mul_32_32(0x898cc517, adj);          /* delta * tan^2 */
 
       fix_up.msw += adj;
       if ( !(fix_up.msw & 0x80000000) )   /* did fix_up overflow ? */
@@ -206,8 +215,8 @@
 
   /* Transfer the result */
   round_Xsig(&accum);
-  *(short *)&(result->sign) = 0;
-  significand(result) = XSIG_LL(accum);
-  result->exp = EXP_BIAS + exponent;
+  FPU_settag0(TAG_Valid);
+  significand(st0_ptr) = XSIG_LL(accum);
+  setexponent16(st0_ptr, exponent + EXTENDED_Ebias);  /* Result is positive. */
 
 }
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_add_sub.c linux-2.0.40/arch/i386/math-emu/reg_add_sub.c
--- linux-2.0.39/arch/i386/math-emu/reg_add_sub.c	Wed Dec  1 13:44:16 1993
+++ linux-2.0.40/arch/i386/math-emu/reg_add_sub.c	Mon Oct  8 23:54:43 2001
@@ -3,16 +3,19 @@
  |                                                                           |
  | Functions to add or subtract two registers and put the result in a third. |
  |                                                                           |
- | Copyright (C) 1992,1993                                                   |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ | Copyright (C) 1992,1993,1997                                              |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
 /*---------------------------------------------------------------------------+
- | For each function, the destination may be any FPU_REG, including one of   |
+ |  For each function, the destination may be any FPU_REG, including one of  |
  | the source FPU_REGs.                                                      |
+ |  Each function returns 0 if the answer is o.k., otherwise a non-zero      |
+ | value is returned, indicating either an exception condition or an         |
+ | internal error.                                                           |
  +---------------------------------------------------------------------------*/
 
 #include "exception.h"
@@ -21,156 +24,164 @@
 #include "control_w.h"
 #include "fpu_system.h"
 
+static
+int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa,
+		     FPU_REG const *b, u_char tagb, u_char signb,
+		     FPU_REG *dest, int deststnr, int control_w);
 
-int reg_add(FPU_REG const *a, FPU_REG const *b, FPU_REG *dest, int control_w)
+/*
+  Operates on st(0) and st(n), or on st(0) and temporary data.
+  The destination must be one of the source st(x).
+  */
+int FPU_add(FPU_REG const *b, u_char tagb, int deststnr, int control_w)
 {
-  char saved_sign = dest->sign;
-  int diff;
+  FPU_REG *a = &st(0);
+  FPU_REG *dest = &st(deststnr);
+  u_char signb = getsign(b);
+  u_char taga = FPU_gettag0();
+  u_char signa = getsign(a);
+  u_char saved_sign = getsign(dest);
+  int diff, tag, expa, expb;
   
-  if ( !(a->tag | b->tag) )
+  if ( !(taga | tagb) )
     {
+      expa = exponent(a);
+      expb = exponent(b);
+
+    valid_add:
       /* Both registers are valid */
-      if (!(a->sign ^ b->sign))
+      if (!(signa ^ signb))
 	{
 	  /* signs are the same */
-	  dest->sign = a->sign;
-	  if ( reg_u_add(a, b, dest, control_w) )
-	    {
-	      dest->sign = saved_sign;
-	      return 1;
-	    }
-	  return 0;
+	  tag = FPU_u_add(a, b, dest, control_w, signa, expa, expb);
 	}
-      
-      /* The signs are different, so do a subtraction */
-      diff = a->exp - b->exp;
-      if (!diff)
+      else
 	{
-	  diff = a->sigh - b->sigh;  /* Works only if ms bits are identical */
+	  /* The signs are different, so do a subtraction */
+	  diff = expa - expb;
 	  if (!diff)
 	    {
-	      diff = a->sigl > b->sigl;
+	      diff = a->sigh - b->sigh;  /* This works only if the ms bits
+					    are identical. */
 	      if (!diff)
-		diff = -(a->sigl < b->sigl);
-	    }
-	}
-      
-      if (diff > 0)
-	{
-	  dest->sign = a->sign;
-	  if ( reg_u_sub(a, b, dest, control_w) )
-	    {
-	      dest->sign = saved_sign;
-	      return 1;
-	    }
-	}
-      else if ( diff == 0 )
-	{
-#ifdef DENORM_OPERAND
-	  if ( (b->tag == TW_Valid) && (b->exp <= EXP_UNDER) &&
-	      denormal_operand() )
-	    return 1;
-#endif DENORM_OPERAND
-	  reg_move(&CONST_Z, dest);
-	  /* sign depends upon rounding mode */
-	  dest->sign = ((control_w & CW_RC) != RC_DOWN)
-	    ? SIGN_POS : SIGN_NEG;
-	}
-      else
-	{
-	  dest->sign = b->sign;
-	  if ( reg_u_sub(b, a, dest, control_w) )
-	    {
-	      dest->sign = saved_sign;
-	      return 1;
-	    }
-	}
-      return 0;
-    }
-  else
-    {
-      if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) )
-	{ return real_2op_NaN(a, b, dest); }
-      else if (a->tag == TW_Zero)
-	{
-	  if (b->tag == TW_Zero)
-	    {
-	      char different_signs = a->sign ^ b->sign;
-	      /* Both are zero, result will be zero. */
-	      reg_move(a, dest);
-	      if (different_signs)
 		{
-		  /* Signs are different. */
-		  /* Sign of answer depends upon rounding mode. */
-		  dest->sign = ((control_w & CW_RC) != RC_DOWN)
-		    ? SIGN_POS : SIGN_NEG;
+		  diff = a->sigl > b->sigl;
+		  if (!diff)
+		    diff = -(a->sigl < b->sigl);
 		}
 	    }
-	  else
+      
+	  if (diff > 0)
 	    {
-#ifdef DENORM_OPERAND
-	      if ( (b->tag == TW_Valid) && (b->exp <= EXP_UNDER) &&
-		  denormal_operand() )
-		return 1;
-#endif DENORM_OPERAND
-	      reg_move(b, dest);
+	      tag = FPU_u_sub(a, b, dest, control_w, signa, expa, expb);
 	    }
-	  return 0;
-	}
-      else if (b->tag == TW_Zero)
-	{
-#ifdef DENORM_OPERAND
-	  if ( (a->tag == TW_Valid) && (a->exp <= EXP_UNDER) &&
-	      denormal_operand() )
-	    return 1;
-#endif DENORM_OPERAND
-	  reg_move(a, dest); return 0;
-	}
-      else if (a->tag == TW_Infinity)
-	{
-	  if (b->tag != TW_Infinity)
+	  else if ( diff < 0 )
 	    {
-#ifdef DENORM_OPERAND
-	      if ( (b->tag == TW_Valid) && (b->exp <= EXP_UNDER) &&
-		  denormal_operand() )
-		return 1;
-#endif DENORM_OPERAND
-	      reg_move(a, dest); return 0;
+	      tag = FPU_u_sub(b, a, dest, control_w, signb, expb, expa);
 	    }
-	  if (a->sign == b->sign)
+	  else
 	    {
-	      /* They are both + or - infinity */
-	      reg_move(a, dest); return 0;
+	      FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
+	      /* sign depends upon rounding mode */
+	      setsign(dest, ((control_w & CW_RC) != RC_DOWN)
+		      ? SIGN_POS : SIGN_NEG);
+	      return TAG_Zero;
 	    }
-	  return arith_invalid(dest);	/* Infinity-Infinity is undefined. */
 	}
-      else if (b->tag == TW_Infinity)
+
+      if ( tag < 0 )
 	{
-#ifdef DENORM_OPERAND
-	  if ( (a->tag == TW_Valid) && (a->exp <= EXP_UNDER) &&
-	      denormal_operand() )
-	    return 1;
-#endif DENORM_OPERAND
-	  reg_move(b, dest); return 0;
+	  setsign(dest, saved_sign);
+	  return tag;
 	}
+      FPU_settagi(deststnr, tag);
+      return tag;
     }
-#ifdef PARANOID
-  EXCEPTION(EX_INTERNAL|0x101);
-#endif
-  return 1;
+
+  if ( taga == TAG_Special )
+    taga = FPU_Special(a);
+  if ( tagb == TAG_Special )
+    tagb = FPU_Special(b);
+
+  if ( ((taga == TAG_Valid) && (tagb == TW_Denormal))
+	    || ((taga == TW_Denormal) && (tagb == TAG_Valid))
+	    || ((taga == TW_Denormal) && (tagb == TW_Denormal)) )
+    {
+      FPU_REG x, y;
+
+      if ( denormal_operand() < 0 )
+	return FPU_Exception;
+
+      FPU_to_exp16(a, &x);
+      FPU_to_exp16(b, &y);
+      a = &x;
+      b = &y;
+      expa = exponent16(a);
+      expb = exponent16(b);
+      goto valid_add;
+    }
+
+  if ( (taga == TW_NaN) || (tagb == TW_NaN) )
+    {
+      if ( deststnr == 0 )
+	return real_2op_NaN(b, tagb, deststnr, a);
+      else
+	return real_2op_NaN(a, taga, deststnr, a);
+    }
+
+  return add_sub_specials(a, taga, signa, b, tagb, signb,
+			  dest, deststnr, control_w);
 }
 
 
 /* Subtract b from a.  (a-b) -> dest */
-int reg_sub(FPU_REG const *a, FPU_REG const *b, FPU_REG *dest, int control_w)
+int FPU_sub(int flags, int rm, int control_w)
 {
-  char saved_sign = dest->sign;
-  int diff;
+  FPU_REG const *a, *b;
+  FPU_REG *dest;
+  u_char taga, tagb, signa, signb, saved_sign, sign;
+  int diff, tag, expa, expb, deststnr;
+
+  a = &st(0);
+  taga = FPU_gettag0();
+
+  deststnr = 0;
+  if ( flags & LOADED )
+    {
+      b = (FPU_REG *)rm;
+      tagb = flags & 0x0f;
+    }
+  else
+    {
+      b = &st(rm);
+      tagb = FPU_gettagi(rm);
+
+      if ( flags & DEST_RM )
+	deststnr = rm;
+    }
+
+  signa = getsign(a);
+  signb = getsign(b);
+
+  if ( flags & REV )
+    {
+      signa ^= SIGN_NEG;
+      signb ^= SIGN_NEG;
+    }
 
-  if ( !(a->tag | b->tag) )
+  dest = &st(deststnr);
+  saved_sign = getsign(dest);
+
+  if ( !(taga | tagb) )
     {
+      expa = exponent(a);
+      expb = exponent(b);
+
+    valid_subtract:
       /* Both registers are valid */
-      diff = a->exp - b->exp;
+
+      diff = expa - expb;
+
       if (!diff)
 	{
 	  diff = a->sigh - b->sigh;  /* Works only if ms bits are identical */
@@ -182,137 +193,182 @@
 	    }
 	}
 
-      switch (a->sign*2 + b->sign)
+      switch ( (((int)signa)*2 + signb) / SIGN_NEG )
 	{
 	case 0: /* P - P */
 	case 3: /* N - N */
 	  if (diff > 0)
 	    {
 	      /* |a| > |b| */
-	      dest->sign = a->sign;
-	      if ( reg_u_sub(a, b, dest, control_w) )
-		{
-		  dest->sign = saved_sign;
-		  return 1;
-		}
-	      return 0;
+	      tag = FPU_u_sub(a, b, dest, control_w, signa, expa, expb);
 	    }
 	  else if ( diff == 0 )
 	    {
-#ifdef DENORM_OPERAND
-	      if ( (b->tag == TW_Valid) && (b->exp <= EXP_UNDER) &&
-		  denormal_operand() )
-		return 1;
-#endif DENORM_OPERAND
-	      reg_move(&CONST_Z, dest);
+	      FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
+
 	      /* sign depends upon rounding mode */
-	      dest->sign = ((control_w & CW_RC) != RC_DOWN)
-		? SIGN_POS : SIGN_NEG;
+	      setsign(dest, ((control_w & CW_RC) != RC_DOWN)
+		? SIGN_POS : SIGN_NEG);
+	      return TAG_Zero;
 	    }
 	  else
 	    {
-	      dest->sign = a->sign ^ SIGN_POS^SIGN_NEG;
-	      if ( reg_u_sub(b, a, dest, control_w) )
-		{
-		  dest->sign = saved_sign;
-		  return 1;
-		}
+	      sign = signa ^ SIGN_NEG;
+	      tag = FPU_u_sub(b, a, dest, control_w, sign, expb, expa);
 	    }
 	  break;
 	case 1: /* P - N */
-	  dest->sign = SIGN_POS;
-	  if ( reg_u_add(a, b, dest, control_w) )
-	    {
-	      dest->sign = saved_sign;
-	      return 1;
-	    }
+	  tag = FPU_u_add(a, b, dest, control_w, SIGN_POS, expa, expb);
 	  break;
 	case 2: /* N - P */
-	  dest->sign = SIGN_NEG;
-	  if ( reg_u_add(a, b, dest, control_w) )
-	    {
-	      dest->sign = saved_sign;
-	      return 1;
-	    }
+	  tag = FPU_u_add(a, b, dest, control_w, SIGN_NEG, expa, expb);
 	  break;
+#ifdef PARANOID
+	default:
+	  EXCEPTION(EX_INTERNAL|0x111);
+	  return -1;
+#endif
+	}
+      if ( tag < 0 )
+	{
+	  setsign(dest, saved_sign);
+	  return tag;
 	}
-      return 0;
+      FPU_settagi(deststnr, tag);
+      return tag;
     }
-  else
+
+  if ( taga == TAG_Special )
+    taga = FPU_Special(a);
+  if ( tagb == TAG_Special )
+    tagb = FPU_Special(b);
+
+  if ( ((taga == TAG_Valid) && (tagb == TW_Denormal))
+	    || ((taga == TW_Denormal) && (tagb == TAG_Valid))
+	    || ((taga == TW_Denormal) && (tagb == TW_Denormal)) )
     {
-      if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) )
-	{ return real_2op_NaN(b, a, dest); }
-      else if (b->tag == TW_Zero)
-	{ 
-	  if (a->tag == TW_Zero)
-	    {
-	      char same_signs = !(a->sign ^ b->sign);
-	      /* Both are zero, result will be zero. */
-	      reg_move(a, dest); /* Answer for different signs. */
-	      if (same_signs)
-		{
-		  /* Sign depends upon rounding mode */
-		  dest->sign = ((control_w & CW_RC) != RC_DOWN)
-		    ? SIGN_POS : SIGN_NEG;
-		}
-	    }
-	  else
-	    {
-#ifdef DENORM_OPERAND
-	      if ( (a->tag == TW_Valid) && (a->exp <= EXP_UNDER) &&
-		  denormal_operand() )
-		return 1;
-#endif DENORM_OPERAND
-	      reg_move(a, dest);
-	    }
-	  return 0;
+      FPU_REG x, y;
+
+      if ( denormal_operand() < 0 )
+	return FPU_Exception;
+
+      FPU_to_exp16(a, &x);
+      FPU_to_exp16(b, &y);
+      a = &x;
+      b = &y;
+      expa = exponent16(a);
+      expb = exponent16(b);
+
+      goto valid_subtract;
+    }
+
+  if ( (taga == TW_NaN) || (tagb == TW_NaN) )
+    {
+      FPU_REG const *d1, *d2;
+      if ( flags & REV )
+	{
+	  d1 = b;
+	  d2 = a;
 	}
-      else if (a->tag == TW_Zero)
+      else
 	{
-#ifdef DENORM_OPERAND
-	  if ( (b->tag == TW_Valid) && (b->exp <= EXP_UNDER) &&
-	      denormal_operand() )
-	    return 1;
-#endif DENORM_OPERAND
-	  reg_move(b, dest);
-	  dest->sign ^= SIGN_POS^SIGN_NEG;
-	  return 0;
+	  d1 = a;
+	  d2 = b;
 	}
-      else if (a->tag == TW_Infinity)
+      if ( flags & LOADED )
+	return real_2op_NaN(b, tagb, deststnr, d1);
+      if ( flags & DEST_RM )
+	return real_2op_NaN(a, taga, deststnr, d2);
+      else
+	return real_2op_NaN(b, tagb, deststnr, d2);
+    }
+
+    return add_sub_specials(a, taga, signa, b, tagb, signb ^ SIGN_NEG,
+			    dest, deststnr, control_w);
+}
+
+
+static
+int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa,
+		     FPU_REG const *b, u_char tagb, u_char signb,
+		     FPU_REG *dest, int deststnr, int control_w)
+{
+  if ( ((taga == TW_Denormal) || (tagb == TW_Denormal))
+       && (denormal_operand() < 0) )
+    return FPU_Exception;
+
+  if (taga == TAG_Zero)
+    {
+      if (tagb == TAG_Zero)
 	{
-	  if (b->tag != TW_Infinity)
+	  /* Both are zero, result will be zero. */
+	  u_char different_signs = signa ^ signb;
+
+	  FPU_copy_to_regi(a, TAG_Zero, deststnr);
+	  if ( different_signs )
 	    {
-#ifdef DENORM_OPERAND
-	      if ( (b->tag == TW_Valid) && (b->exp <= EXP_UNDER) &&
-		  denormal_operand() )
-		return 1;
-#endif DENORM_OPERAND
-	      reg_move(a, dest); return 0;
+	      /* Signs are different. */
+	      /* Sign of answer depends upon rounding mode. */
+	      setsign(dest, ((control_w & CW_RC) != RC_DOWN)
+		      ? SIGN_POS : SIGN_NEG);
 	    }
-	  /* Both args are Infinity */
-	  if (a->sign == b->sign)
+	  else
+	    setsign(dest, signa);  /* signa may differ from the sign of a. */
+	  return TAG_Zero;
+	}
+      else
+	{
+	  reg_copy(b, dest);
+	  if ( (tagb == TW_Denormal) && (b->sigh & 0x80000000) )
 	    {
-	      /* Infinity-Infinity is undefined. */
-	      return arith_invalid(dest);
-	    }
-	  reg_move(a, dest);
-	  return 0;
+	      /* A pseudoDenormal, convert it. */
+	      addexponent(dest, 1);
+	      tagb = TAG_Valid;
+	    }
+	  else if ( tagb > TAG_Empty )
+	    tagb = TAG_Special;
+	  setsign(dest, signb);  /* signb may differ from the sign of b. */
+	  FPU_settagi(deststnr, tagb);
+	  return tagb;
 	}
-      else if (b->tag == TW_Infinity)
+    }
+  else if (tagb == TAG_Zero)
+    {
+      reg_copy(a, dest);
+      if ( (taga == TW_Denormal) && (a->sigh & 0x80000000) )
 	{
-#ifdef DENORM_OPERAND
-	  if ( (a->tag == TW_Valid) && (a->exp <= EXP_UNDER) &&
-	      denormal_operand() )
-	    return 1;
-#endif DENORM_OPERAND
-	  reg_move(b, dest);
-	  dest->sign ^= SIGN_POS^SIGN_NEG;
-	  return 0;
+	  /* A pseudoDenormal */
+	  addexponent(dest, 1);
+	  taga = TAG_Valid;
+	}
+      else if ( taga > TAG_Empty )
+	taga = TAG_Special;
+      setsign(dest, signa);  /* signa may differ from the sign of a. */
+      FPU_settagi(deststnr, taga);
+      return taga;
+    }
+  else if (taga == TW_Infinity)
+    {
+      if ( (tagb != TW_Infinity) || (signa == signb) )
+	{
+	  FPU_copy_to_regi(a, TAG_Special, deststnr);
+	  setsign(dest, signa);  /* signa may differ from the sign of a. */
+	  return taga;
 	}
+      /* Infinity-Infinity is undefined. */
+      return arith_invalid(deststnr);
+    }
+  else if (tagb == TW_Infinity)
+    {
+      FPU_copy_to_regi(b, TAG_Special, deststnr);
+      setsign(dest, signb);  /* signb may differ from the sign of b. */
+      return tagb;
     }
+
 #ifdef PARANOID
-  EXCEPTION(EX_INTERNAL|0x110);
+  EXCEPTION(EX_INTERNAL|0x101);
 #endif
-  return 1;
+
+  return FPU_Exception;
 }
 
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_compare.c linux-2.0.40/arch/i386/math-emu/reg_compare.c
--- linux-2.0.39/arch/i386/math-emu/reg_compare.c	Thu Jun  2 09:28:27 1994
+++ linux-2.0.40/arch/i386/math-emu/reg_compare.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  | Compare two floating point registers                                      |
  |                                                                           |
- | Copyright (C) 1992,1993,1994                                              |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ | Copyright (C) 1992,1993,1994,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -21,86 +21,94 @@
 #include "status_w.h"
 
 
-int compare(FPU_REG const *b)
+static void setflags(unsigned char flags)
 {
-  int diff;
-  char	       st0_tag;
-  FPU_REG      *st0_ptr;
+  *(unsigned char *)&FPU_EFLAGS &= ~SFLAGS;
+  *(unsigned char *)&FPU_EFLAGS |= (flags & SFLAGS);
+}
+
+
+static int compare(FPU_REG const *b, int tagb)
+{
+  int diff, exp0, expb;
+  u_char	  	st0_tag;
+  FPU_REG  	*st0_ptr;
+  FPU_REG	x, y;
+  u_char		st0_sign, signb = getsign(b);
 
   st0_ptr = &st(0);
-  st0_tag = st0_ptr->tag;
+  st0_tag = FPU_gettag0();
+  st0_sign = getsign(st0_ptr);
+
+  if ( tagb == TAG_Special )
+    tagb = FPU_Special(b);
+  if ( st0_tag == TAG_Special )
+    st0_tag = FPU_Special(st0_ptr);
 
-  if ( st0_tag | b->tag )
+  if ( ((st0_tag != TAG_Valid) && (st0_tag != TW_Denormal))
+       || ((tagb != TAG_Valid) && (tagb != TW_Denormal)) )
     {
-      if ( st0_tag == TW_Zero )
+      if ( st0_tag == TAG_Zero )
 	{
-	  if ( b->tag == TW_Zero ) return COMP_A_eq_B;
-	  if ( b->tag == TW_Valid )
-	    {
-	      return ((b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
-#ifdef DENORM_OPERAND
-		| ((b->exp <= EXP_UNDER) ?
-		   COMP_Denormal : 0)
-#endif DENORM_OPERAND
-		  ;
-	    }
+	  if ( tagb == TAG_Zero ) return COMP_A_eq_B;
+	  if ( tagb == TAG_Valid )
+	    return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B);
+	  if ( tagb == TW_Denormal )
+	    return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
+	    | COMP_Denormal;
 	}
-      else if ( b->tag == TW_Zero )
+      else if ( tagb == TAG_Zero )
 	{
-	  if ( st0_tag == TW_Valid )
-	    {
-	      return ((st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B
-		      : COMP_A_lt_B)
-#ifdef DENORM_OPERAND
-		| ((st0_ptr->exp <= EXP_UNDER )
-		   ? COMP_Denormal : 0 )
-#endif DENORM_OPERAND
-		  ;
-	    }
+	  if ( st0_tag == TAG_Valid )
+	    return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
+	  if ( st0_tag == TW_Denormal )
+	    return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
+	    | COMP_Denormal;
 	}
 
       if ( st0_tag == TW_Infinity )
 	{
-	  if ( (b->tag == TW_Valid) || (b->tag == TW_Zero) )
-	    {
-	      return ((st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B
-		      : COMP_A_lt_B)
-#ifdef DENORM_OPERAND
-	      | (((b->tag == TW_Valid) && (b->exp <= EXP_UNDER)) ?
-		COMP_Denormal : 0 )
-#endif DENORM_OPERAND
-;
-	    }
-	  else if ( b->tag == TW_Infinity )
+	  if ( (tagb == TAG_Valid) || (tagb == TAG_Zero) )
+	    return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
+	  else if ( tagb == TW_Denormal )
+	    return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
+	      | COMP_Denormal;
+	  else if ( tagb == TW_Infinity )
 	    {
 	      /* The 80486 book says that infinities can be equal! */
-	      return (st0_ptr->sign == b->sign) ? COMP_A_eq_B :
-		((st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
+	      return (st0_sign == signb) ? COMP_A_eq_B :
+		((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
 	    }
 	  /* Fall through to the NaN code */
 	}
-      else if ( b->tag == TW_Infinity )
+      else if ( tagb == TW_Infinity )
 	{
-	  if ( (st0_tag == TW_Valid) || (st0_tag == TW_Zero) )
-	    {
-	      return ((b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
-#ifdef DENORM_OPERAND
-		| (((st0_tag == TW_Valid)
-		    && (st0_ptr->exp <= EXP_UNDER)) ?
-		   COMP_Denormal : 0)
-#endif DENORM_OPERAND
-		  ;
-	    }
+	  if ( (st0_tag == TAG_Valid) || (st0_tag == TAG_Zero) )
+	    return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B);
+	  if ( st0_tag == TW_Denormal )
+	    return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
+		| COMP_Denormal;
 	  /* Fall through to the NaN code */
 	}
 
       /* The only possibility now should be that one of the arguments
 	 is a NaN */
-      if ( (st0_tag == TW_NaN) || (b->tag == TW_NaN) )
+      if ( (st0_tag == TW_NaN) || (tagb == TW_NaN) )
 	{
-	  if ( ((st0_tag == TW_NaN) && !(st0_ptr->sigh & 0x40000000))
-	      || ((b->tag == TW_NaN) && !(b->sigh & 0x40000000)) )
-	    /* At least one arg is a signaling NaN */
+	  int signalling = 0, unsupported = 0;
+	  if ( st0_tag == TW_NaN )
+	    {
+	      signalling = (st0_ptr->sigh & 0xc0000000) == 0x80000000;
+	      unsupported = !((exponent(st0_ptr) == EXP_OVER)
+			      && (st0_ptr->sigh & 0x80000000));
+	    }
+	  if ( tagb == TW_NaN )
+	    {
+	      signalling |= (b->sigh & 0xc0000000) == 0x80000000;
+	      unsupported |= !((exponent(b) == EXP_OVER)
+			       && (b->sigh & 0x80000000));
+	    }
+	  if ( signalling || unsupported )
 	    return COMP_No_Comp | COMP_SNaN | COMP_NaN;
 	  else
 	    /* Neither is a signaling NaN */
@@ -110,24 +118,34 @@
       EXCEPTION(EX_Invalid);
     }
   
-#ifdef PARANOID
-  if (!(st0_ptr->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
-  if (!(b->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
-#endif PARANOID
+  if (st0_sign != signb)
+    {
+      return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
+	| ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
+	    COMP_Denormal : 0);
+    }
 
-  
-  if (st0_ptr->sign != b->sign)
+  if ( (st0_tag == TW_Denormal) || (tagb == TW_Denormal) )
+    {
+      FPU_to_exp16(st0_ptr, &x);
+      FPU_to_exp16(b, &y);
+      st0_ptr = &x;
+      b = &y;
+      exp0 = exponent16(st0_ptr);
+      expb = exponent16(b);
+    }
+  else
     {
-      return ((st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
-#ifdef DENORM_OPERAND
-	|
-	  ( ((st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
-	   COMP_Denormal : 0)
-#endif DENORM_OPERAND
-	    ;
+      exp0 = exponent(st0_ptr);
+      expb = exponent(b);
     }
 
-  diff = st0_ptr->exp - b->exp;
+#ifdef PARANOID
+  if (!(st0_ptr->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
+  if (!(b->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
+#endif /* PARANOID */
+
+  diff = exp0 - expb;
   if ( diff == 0 )
     {
       diff = st0_ptr->sigh - b->sigh;  /* Works only if ms bits are
@@ -142,42 +160,30 @@
 
   if ( diff > 0 )
     {
-      return ((st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
-#ifdef DENORM_OPERAND
-	|
-	  ( ((st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
-	   COMP_Denormal : 0)
-#endif DENORM_OPERAND
-	    ;
+      return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
+	| ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
+	    COMP_Denormal : 0);
     }
   if ( diff < 0 )
     {
-      return ((st0_ptr->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
-#ifdef DENORM_OPERAND
-	|
-	  ( ((st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
-	   COMP_Denormal : 0)
-#endif DENORM_OPERAND
-	    ;
+      return ((st0_sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
+	| ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
+	    COMP_Denormal : 0);
     }
 
   return COMP_A_eq_B
-#ifdef DENORM_OPERAND
-    |
-      ( ((st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
-       COMP_Denormal : 0)
-#endif DENORM_OPERAND
-	;
+    | ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
+	COMP_Denormal : 0);
 
 }
 
 
 /* This function requires that st(0) is not empty */
-int compare_st_data(FPU_REG const *loaded_data)
+int FPU_compare_st_data(FPU_REG const *loaded_data, u_char loaded_tag)
 {
   int f, c;
 
-  c = compare(loaded_data);
+  c = compare(loaded_data, loaded_tag);
 
   if (c & COMP_NaN)
     {
@@ -204,33 +210,35 @@
 	EXCEPTION(EX_INTERNAL|0x121);
 	f = SW_C3 | SW_C2 | SW_C0;
 	break;
-#endif PARANOID
+#endif /* PARANOID */
       }
   setcc(f);
   if (c & COMP_Denormal)
     {
-      return denormal_operand();
+      return denormal_operand() < 0;
     }
   return 0;
 }
 
 
-static int compare_st_st(int nr)
+static int compare_st_st(int nr, int ftype)
 {
   int f, c;
+  FPU_REG *st_ptr;
 
   if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) )
     {
-      setcc(SW_C3 | SW_C2 | SW_C0);
+      setccf(ftype, SW_C3 | SW_C2 | SW_C0);
       /* Stack fault */
       EXCEPTION(EX_StackUnder);
       return !(control_word & CW_Invalid);
     }
 
-  c = compare(&st(nr));
+  st_ptr = &st(nr);
+  c = compare(st_ptr, FPU_gettagi(nr));
   if (c & COMP_NaN)
     {
-      setcc(SW_C3 | SW_C2 | SW_C0);
+      setccf(ftype, SW_C3 | SW_C2 | SW_C0);
       EXCEPTION(EX_Invalid);
       return !(control_word & CW_Invalid);
     }
@@ -254,33 +262,35 @@
 	EXCEPTION(EX_INTERNAL|0x122);
 	f = SW_C3 | SW_C2 | SW_C0;
 	break;
-#endif PARANOID
+#endif /* PARANOID */
       }
-  setcc(f);
+  setccf(ftype, f);
   if (c & COMP_Denormal)
     {
-      return denormal_operand();
+      return denormal_operand() < 0;
     }
   return 0;
 }
 
 
-static int compare_u_st_st(int nr)
+static int compare_u_st_st(int nr, int ftype)
 {
   int f, c;
+  FPU_REG *st_ptr;
 
   if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) )
     {
-      setcc(SW_C3 | SW_C2 | SW_C0);
+      setccf(ftype, SW_C3 | SW_C2 | SW_C0);
       /* Stack fault */
       EXCEPTION(EX_StackUnder);
       return !(control_word & CW_Invalid);
     }
 
-  c = compare(&st(nr));
+  st_ptr = &st(nr);
+  c = compare(st_ptr, FPU_gettagi(nr));
   if (c & COMP_NaN)
     {
-      setcc(SW_C3 | SW_C2 | SW_C0);
+      setccf(ftype, SW_C3 | SW_C2 | SW_C0);
       if (c & COMP_SNaN)       /* This is the only difference between
 				  un-ordered and ordinary comparisons */
 	{
@@ -309,12 +319,12 @@
 	EXCEPTION(EX_INTERNAL|0x123);
 	f = SW_C3 | SW_C2 | SW_C0;
 	break;
-#endif PARANOID
+#endif /* PARANOID */ 
       }
-  setcc(f);
+  setccf(ftype, f);
   if (c & COMP_Denormal)
     {
-      return denormal_operand();
+      return denormal_operand() < 0;
     }
   return 0;
 }
@@ -324,15 +334,15 @@
 void fcom_st()
 {
   /* fcom st(i) */
-  compare_st_st(FPU_rm);
+  compare_st_st(FPU_rm, 0);
 }
 
 
 void fcompst()
 {
   /* fcomp st(i) */
-  if ( !compare_st_st(FPU_rm) )
-    pop();
+  if ( !compare_st_st(FPU_rm, 0) )
+    FPU_pop();
 }
 
 
@@ -344,7 +354,7 @@
       FPU_illegal();
       return;
     }
-  if ( !compare_st_st(1) )
+  if ( !compare_st_st(1, 0) )
       poppop();
 }
 
@@ -352,7 +362,7 @@
 void fucom_()
 {
   /* fucom st(i) */
-  compare_u_st_st(FPU_rm);
+  compare_u_st_st(FPU_rm, 0);
 
 }
 
@@ -360,8 +370,8 @@
 void fucomp()
 {
   /* fucomp st(i) */
-  if ( !compare_u_st_st(FPU_rm) )
-    pop();
+  if ( !compare_u_st_st(FPU_rm, 0) )
+    FPU_pop();
 }
 
 
@@ -370,9 +380,27 @@
   /* fucompp */
   if (FPU_rm == 1)
     {
-      if ( !compare_u_st_st(1) )
+      if ( !compare_u_st_st(1, 0) )
 	poppop();
     }
   else
     FPU_illegal();
 }
+
+
+#ifndef ONLY_486_FPU
+void fcomi()
+{
+  /* fcom st(i) */
+  compare_st_st(FPU_rm, 1);
+}
+
+
+void fucomi()
+{
+  /* fucom st(i) */
+  compare_u_st_st(FPU_rm, 1);
+
+}
+#endif /* ONLY_486_FPU */
+
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_constant.c linux-2.0.40/arch/i386/math-emu/reg_constant.c
--- linux-2.0.39/arch/i386/math-emu/reg_constant.c	Tue Mar 19 12:45:01 1996
+++ linux-2.0.40/arch/i386/math-emu/reg_constant.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  | All of the constant FPU_REGs                                              |
  |                                                                           |
- | Copyright (C) 1992,1993,1994,1996                                         |
+ | Copyright (C) 1992,1993,1994,1997                                         |
  |                     W. Metzenthen, 22 Parker St, Ormond, Vic 3163,        |
- |                     Australia.  E-mail   billm@jacobi.maths.monash.edu.au |
+ |                     Australia.  E-mail   billm@suburbia.net               |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -17,59 +17,52 @@
 #include "control_w.h"
 
 
-FPU_REG const CONST_1    = { SIGN_POS, TW_Valid, EXP_BIAS,
-			    0x00000000, 0x80000000 };
-FPU_REG const CONST_2    = { SIGN_POS, TW_Valid, EXP_BIAS+1,
-			    0x00000000, 0x80000000 };
-FPU_REG const CONST_HALF = { SIGN_POS, TW_Valid, EXP_BIAS-1,
-			    0x00000000, 0x80000000 };
-FPU_REG const CONST_L2T  = { SIGN_POS, TW_Valid, EXP_BIAS+1,
-			    0xcd1b8afe, 0xd49a784b };
-FPU_REG const CONST_L2E  = { SIGN_POS, TW_Valid, EXP_BIAS,
-			    0x5c17f0bc, 0xb8aa3b29 };
-FPU_REG const CONST_PI   = { SIGN_POS, TW_Valid, EXP_BIAS+1,
-			    0x2168c235, 0xc90fdaa2 };
-FPU_REG const CONST_PI2  = { SIGN_POS, TW_Valid, EXP_BIAS,
-			    0x2168c235, 0xc90fdaa2 };
-FPU_REG const CONST_PI4  = { SIGN_POS, TW_Valid, EXP_BIAS-1,
-			    0x2168c235, 0xc90fdaa2 };
-FPU_REG const CONST_LG2  = { SIGN_POS, TW_Valid, EXP_BIAS-2,
-			    0xfbcff799, 0x9a209a84 };
-FPU_REG const CONST_LN2  = { SIGN_POS, TW_Valid, EXP_BIAS-1,
-			    0xd1cf79ac, 0xb17217f7 };
+#define MAKE_REG(s,e,l,h) { l, h, \
+                            ((EXTENDED_Ebias+(e)) | ((SIGN_##s != 0)*0x8000)) }
+
+FPU_REG const CONST_1    = MAKE_REG(POS, 0, 0x00000000, 0x80000000);
+FPU_REG const CONST_2    = MAKE_REG(POS, 1, 0x00000000, 0x80000000);
+FPU_REG const CONST_HALF = MAKE_REG(POS, -1, 0x00000000, 0x80000000);
+FPU_REG const CONST_L2T  = MAKE_REG(POS, 1, 0xcd1b8afe, 0xd49a784b);
+FPU_REG const CONST_L2E  = MAKE_REG(POS, 0, 0x5c17f0bc, 0xb8aa3b29);
+FPU_REG const CONST_PI   = MAKE_REG(POS, 1, 0x2168c235, 0xc90fdaa2);
+FPU_REG const CONST_PI2  = MAKE_REG(POS, 0, 0x2168c235, 0xc90fdaa2);
+FPU_REG const CONST_PI4  = MAKE_REG(POS, -1, 0x2168c235, 0xc90fdaa2);
+FPU_REG const CONST_LG2  = MAKE_REG(POS, -2, 0xfbcff799, 0x9a209a84);
+FPU_REG const CONST_LN2  = MAKE_REG(POS, -1, 0xd1cf79ac, 0xb17217f7);
 
 /* Extra bits to take pi/2 to more than 128 bits precision. */
-FPU_REG const CONST_PI2extra = { SIGN_NEG, TW_Valid, EXP_BIAS-66,
-			    0xfc8f8cbb, 0xece675d1 };
+FPU_REG const CONST_PI2extra = MAKE_REG(NEG, -66,
+					 0xfc8f8cbb, 0xece675d1);
 
 /* Only the sign (and tag) is used in internal zeroes */
-FPU_REG const CONST_Z    = { SIGN_POS, TW_Zero, EXP_UNDER, 0x0, 0x0 };
+FPU_REG const CONST_Z    = MAKE_REG(POS, EXP_UNDER, 0x0, 0x0);
 
 /* Only the sign and significand (and tag) are used in internal NaNs */
 /* The 80486 never generates one of these 
-FPU_REG const CONST_SNAN = { SIGN_POS, TW_NaN, EXP_OVER, 0x00000001, 0x80000000 };
+FPU_REG const CONST_SNAN = MAKE_REG(POS, EXP_OVER, 0x00000001, 0x80000000);
  */
 /* This is the real indefinite QNaN */
-FPU_REG const CONST_QNaN = { SIGN_NEG, TW_NaN, EXP_OVER, 0x00000000, 0xC0000000 };
+FPU_REG const CONST_QNaN = MAKE_REG(NEG, EXP_OVER, 0x00000000, 0xC0000000);
 
 /* Only the sign (and tag) is used in internal infinities */
-FPU_REG const CONST_INF  = { SIGN_POS, TW_Infinity, EXP_OVER, 0x00000000, 0x80000000 };
-
+FPU_REG const CONST_INF  = MAKE_REG(POS, EXP_OVER, 0x00000000, 0x80000000);
 
 
-static void fld_const(FPU_REG const *c, int adj)
+static void fld_const(FPU_REG const *c, int adj, u_char tag)
 {
   FPU_REG *st_new_ptr;
 
   if ( STACK_OVERFLOW )
     {
-      stack_overflow();
+      FPU_stack_overflow();
       return;
     }
   push();
-  reg_move(c, st_new_ptr);
+  reg_copy(c, st_new_ptr);
   st_new_ptr->sigl += adj;  /* For all our fldxxx constants, we don't need to
 			       borrow or carry. */
+  FPU_settag0(tag);
   clear_C1();
 }
 
@@ -80,37 +73,37 @@
 
 static void fld1(int rc)
 {
-  fld_const(&CONST_1, 0);
+  fld_const(&CONST_1, 0, TAG_Valid);
 }
 
 static void fldl2t(int rc)
 {
-  fld_const(&CONST_L2T, (rc == RC_UP) ? 1 : 0);
+  fld_const(&CONST_L2T, (rc == RC_UP) ? 1 : 0, TAG_Valid);
 }
 
 static void fldl2e(int rc)
 {
-  fld_const(&CONST_L2E, DOWN_OR_CHOP(rc) ? -1 : 0);
+  fld_const(&CONST_L2E, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid);
 }
 
 static void fldpi(int rc)
 {
-  fld_const(&CONST_PI, DOWN_OR_CHOP(rc) ? -1 : 0);
+  fld_const(&CONST_PI, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid);
 }
 
 static void fldlg2(int rc)
 {
-  fld_const(&CONST_LG2, DOWN_OR_CHOP(rc) ? -1 : 0);
+  fld_const(&CONST_LG2, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid);
 }
 
 static void fldln2(int rc)
 {
-  fld_const(&CONST_LN2, DOWN_OR_CHOP(rc) ? -1 : 0);
+  fld_const(&CONST_LN2, DOWN_OR_CHOP(rc) ? -1 : 0, TAG_Valid);
 }
 
 static void fldz(int rc)
 {
-  fld_const(&CONST_Z, 0);
+  fld_const(&CONST_Z, 0, TAG_Zero);
 }
 
 typedef void (*FUNC_RC)(int);
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_constant.h linux-2.0.40/arch/i386/math-emu/reg_constant.h
--- linux-2.0.39/arch/i386/math-emu/reg_constant.h	Sat Mar 29 01:12:25 1997
+++ linux-2.0.40/arch/i386/math-emu/reg_constant.h	Thu Aug 23 19:09:34 2001
@@ -28,4 +28,4 @@
 extern FPU_REG const CONST_MINF;
 extern FPU_REG const CONST_QNaN;
 
-#endif _REG_CONSTANT_H_
+#endif /* _REG_CONSTANT_H_ */
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_convert.c linux-2.0.40/arch/i386/math-emu/reg_convert.c
--- linux-2.0.39/arch/i386/math-emu/reg_convert.c	Thu Jan  1 01:00:00 1970
+++ linux-2.0.40/arch/i386/math-emu/reg_convert.c	Mon Oct  8 23:54:43 2001
@@ -0,0 +1,53 @@
+/*---------------------------------------------------------------------------+
+ |  reg_convert.c                                                            |
+ |                                                                           |
+ |  Convert register representation.                                         |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1994,1996,1997                                    |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "fpu_emu.h"
+
+
+int FPU_to_exp16(FPU_REG const *a, FPU_REG *x)
+{
+  int sign = getsign(a);
+
+  *(long long *)&(x->sigl) = *(const long long *)&(a->sigl);
+
+  /* Set up the exponent as a 16 bit quantity. */
+  setexponent16(x, exponent(a));
+
+  if ( exponent16(x) == EXP_UNDER )
+    {
+      /* The number is a de-normal or pseudodenormal. */
+      /* We only deal with the significand and exponent. */
+
+      if (x->sigh & 0x80000000)
+	{
+	  /* Is a pseudodenormal. */
+	  /* This is non-80486 behaviour because the number
+	     loses its 'denormal' identity. */
+	  addexponent(x, 1);
+	}
+      else
+	{
+	  /* Is a denormal. */
+	  addexponent(x, 1);
+	  FPU_normalize_nuo(x);
+	}
+    }
+
+  if ( !(x->sigh & 0x80000000) )
+    {
+      EXCEPTION(EX_INTERNAL | 0x180);
+    }
+
+  return sign;
+}
+
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_div.S linux-2.0.40/arch/i386/math-emu/reg_div.S
--- linux-2.0.39/arch/i386/math-emu/reg_div.S	Thu Oct  5 14:30:43 1995
+++ linux-2.0.40/arch/i386/math-emu/reg_div.S	Thu Jan  1 01:00:00 1970
@@ -1,248 +0,0 @@
-	.file	"reg_div.S"
-/*---------------------------------------------------------------------------+
- |  reg_div.S                                                                |
- |                                                                           |
- | Divide one FPU_REG by another and put the result in a destination FPU_REG.|
- |                                                                           |
- | Copyright (C) 1992,1993,1994,1995                                         |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
- |                                                                           |
- | Call from C as:                                                           |
- |   void reg_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest,                     |
- |                                    unsigned int control_word)             |
- |                                                                           |
- +---------------------------------------------------------------------------*/
-
-#include "exception.h"
-#include "fpu_emu.h"
-
-
-.text
-ENTRY(reg_div)
-	pushl	%ebp
-	movl	%esp,%ebp
-#ifndef NON_REENTRANT_FPU
-	subl	$28,%esp	/* Needed by divide_kernel */
-#endif NON_REENTRANT_FPU
-
-	pushl	%esi
-	pushl	%edi
-	pushl	%ebx
-
-	movl	PARAM1,%esi
-	movl	PARAM2,%ebx
-	movl	PARAM3,%edi
-
-	movb	TAG(%esi),%al
-	orb	TAG(%ebx),%al
-
-	jne	L_div_special		/* Not (both numbers TW_Valid) */
-
-#ifdef DENORM_OPERAND
-/* Check for denormals */
-	cmpl	EXP_UNDER,EXP(%esi)
-	jg	xL_arg1_not_denormal
-
-	call	SYMBOL_NAME(denormal_operand)
-	orl	%eax,%eax
-	jnz	fpu_Arith_exit
-
-xL_arg1_not_denormal:
-	cmpl	EXP_UNDER,EXP(%ebx)
-	jg	xL_arg2_not_denormal
-
-	call	SYMBOL_NAME(denormal_operand)
-	orl	%eax,%eax
-	jnz	fpu_Arith_exit
-
-xL_arg2_not_denormal:
-#endif DENORM_OPERAND
-
-/* Both arguments are TW_Valid */
-	movb	TW_Valid,TAG(%edi)
-
-	movb	SIGN(%esi),%cl
-	cmpb	%cl,SIGN(%ebx)
-	setne	(%edi)	      /* Set the sign, requires SIGN_NEG=1, SIGN_POS=0 */
-
-	movl	EXP(%esi),%edx
-	movl	EXP(%ebx),%eax
-	subl	%eax,%edx
-	addl	EXP_BIAS,%edx
-	movl	%edx,EXP(%edi)
-
-	jmp	SYMBOL_NAME(divide_kernel)
-
-
-/*-----------------------------------------------------------------------*/
-L_div_special:
-	cmpb	TW_NaN,TAG(%esi)	/* A NaN with anything to give NaN */
-	je	L_arg1_NaN
-
-	cmpb	TW_NaN,TAG(%ebx)	/* A NaN with anything to give NaN */
-	jne	L_no_NaN_arg
-
-/* Operations on NaNs */
-L_arg1_NaN:
-L_arg2_NaN:
-	pushl	%edi			/* Destination */
-	pushl	%esi
-	pushl	%ebx			/* Ordering is important here */
-	call	SYMBOL_NAME(real_2op_NaN)
-	jmp	LDiv_exit
-
-/* Invalid operations */
-L_zero_zero:
-L_inf_inf:
-	pushl	%edi			/* Destination */
-	call	SYMBOL_NAME(arith_invalid) /* 0/0 or Infinity/Infinity */
-	jmp	LDiv_exit
-
-L_no_NaN_arg:
-	cmpb	TW_Infinity,TAG(%esi)
-	jne	L_arg1_not_inf
-
-	cmpb	TW_Infinity,TAG(%ebx)
-	je	L_inf_inf		/* invalid operation */
-
-	cmpb	TW_Valid,TAG(%ebx)
-	je	L_inf_valid
-
-#ifdef PARANOID
-	/* arg2 must be zero or valid */
-	cmpb	TW_Zero,TAG(%ebx)
-	ja	L_unknown_tags
-#endif PARANOID
-
-	/* Note that p16-9 says that infinity/0 returns infinity */
-	jmp	L_copy_arg1		/* Answer is Inf */
-
-L_inf_valid:
-#ifdef DENORM_OPERAND
-	cmpl	EXP_UNDER,EXP(%ebx)
-	jg	L_copy_arg1		/* Answer is Inf */
-
-	call	SYMBOL_NAME(denormal_operand)
-	orl	%eax,%eax
-	jnz	fpu_Arith_exit
-#endif DENORM_OPERAND
-
-	jmp	L_copy_arg1		/* Answer is Inf */
-
-L_arg1_not_inf:
-	cmpb	TW_Zero,TAG(%ebx)	/* Priority to div-by-zero error */
-	jne	L_arg2_not_zero
-
-	cmpb	TW_Zero,TAG(%esi)
-	je	L_zero_zero		/* invalid operation */
-
-#ifdef PARANOID
-	/* arg1 must be valid */
-	cmpb	TW_Valid,TAG(%esi)
-	ja	L_unknown_tags
-#endif PARANOID
-
-/* Division by zero error */
-	pushl	%edi			/* destination */
-	movb	SIGN(%esi),%al
-	xorb	SIGN(%ebx),%al
-	pushl	%eax			/* lower 8 bits have the sign */
-	call	SYMBOL_NAME(divide_by_zero)
-	jmp	LDiv_exit
-
-L_arg2_not_zero:
-	cmpb	TW_Infinity,TAG(%ebx)
-	jne	L_arg2_not_inf
-
-#ifdef DENORM_OPERAND
-	cmpb	TW_Valid,TAG(%esi)
-	jne	L_return_zero
-
-	cmpl	EXP_UNDER,EXP(%esi)
-	jg	L_return_zero		/* Answer is zero */
-
-	call	SYMBOL_NAME(denormal_operand)
-	orl	%eax,%eax
-	jnz	fpu_Arith_exit
-#endif DENORM_OPERAND
-
-	jmp	L_return_zero		/* Answer is zero */
-
-L_arg2_not_inf:
-
-#ifdef PARANOID
-	cmpb	TW_Zero,TAG(%esi)
-	jne	L_unknown_tags
-#endif PARANOID
-
-	/* arg1 is zero, arg2 is not Infinity or a NaN */
-
-#ifdef DENORM_OPERAND
-	cmpl	EXP_UNDER,EXP(%ebx)
-	jg	L_copy_arg1		/* Answer is zero */
-
-	call	SYMBOL_NAME(denormal_operand)
-	orl	%eax,%eax
-	jnz	fpu_Arith_exit
-#endif DENORM_OPERAND
-
-L_copy_arg1:
-	movb	TAG(%esi),%ax
-	movb	%ax,TAG(%edi)
-	movl	EXP(%esi),%eax
-	movl	%eax,EXP(%edi)
-	movl	SIGL(%esi),%eax
-	movl	%eax,SIGL(%edi)
-	movl	SIGH(%esi),%eax
-	movl	%eax,SIGH(%edi)
-
-LDiv_set_result_sign:
-	movb	SIGN(%esi),%cl
-	cmpb	%cl,SIGN(%ebx)
-	jne	LDiv_negative_result
-
-	movb	SIGN_POS,SIGN(%edi)
-	xorl	%eax,%eax		/* Valid result */
-	jmp	LDiv_exit
-
-LDiv_negative_result:
-	movb	SIGN_NEG,SIGN(%edi)
-	xorl	%eax,%eax		/* Valid result */
-
-LDiv_exit:
-#ifndef NON_REENTRANT_FPU
-	leal	-40(%ebp),%esp
-#else
-	leal	-12(%ebp),%esp
-#endif NON_REENTRANT_FPU
-
-	popl	%ebx
-	popl	%edi
-	popl	%esi
-	leave
-	ret
-
-
-L_return_zero:
-	xorl	%eax,%eax
-	movl	%eax,SIGH(%edi)
-	movl	%eax,SIGL(%edi)
-	movl	EXP_UNDER,EXP(%edi)
-	movb	TW_Zero,TAG(%edi)
-	jmp	LDiv_set_result_sign
-
-#ifdef PARANOID
-L_unknown_tags:
-	pushl	EX_INTERNAL | 0x208
-	call	EXCEPTION
-
-	/* Generate a NaN for unknown tags */
-	movl	SYMBOL_NAME(CONST_QNaN),%eax
-	movl	%eax,(%edi)
-	movl	SYMBOL_NAME(CONST_QNaN)+4,%eax
-	movl	%eax,SIGL(%edi)
-	movl	SYMBOL_NAME(CONST_QNaN)+8,%eax
-	movl	%eax,SIGH(%edi)
-	jmp	LDiv_exit		/* %eax is nz */
-#endif PARANOID
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_divide.c linux-2.0.40/arch/i386/math-emu/reg_divide.c
--- linux-2.0.39/arch/i386/math-emu/reg_divide.c	Thu Jan  1 01:00:00 1970
+++ linux-2.0.40/arch/i386/math-emu/reg_divide.c	Mon Oct  8 23:54:43 2001
@@ -0,0 +1,206 @@
+/*---------------------------------------------------------------------------+
+ |  reg_divide.c                                                             |
+ |                                                                           |
+ | Divide one FPU_REG by another and put the result in a destination FPU_REG.|
+ |                                                                           |
+ | Copyright (C) 1996                                                        |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@jacobi.maths.monash.edu.au                |
+ |                                                                           |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ | The destination may be any FPU_REG, including one of the source FPU_REGs. |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "reg_constant.h"
+#include "fpu_emu.h"
+#include "fpu_system.h"
+
+/*
+  Divide one register by another and put the result into a third register.
+  */
+int FPU_div(int flags, int rm, int control_w)
+{
+  FPU_REG x, y;
+  FPU_REG const *a, *b, *st0_ptr, *st_ptr;
+  FPU_REG *dest;
+  u_char taga, tagb, signa, signb, sign, saved_sign;
+  int tag, deststnr;
+
+  if ( flags & DEST_RM )
+    deststnr = rm;
+  else
+    deststnr = 0;
+
+  if ( flags & REV )
+    {
+      b = &st(0);
+      st0_ptr = b;
+      tagb = FPU_gettag0();
+      if ( flags & LOADED )
+	{
+	  a = (FPU_REG *)rm;
+	  taga = flags & 0x0f;
+	}
+      else
+	{
+	  a = &st(rm);
+	  st_ptr = a;
+	  taga = FPU_gettagi(rm);
+	}
+    }
+  else
+    {
+      a = &st(0);
+      st0_ptr = a;
+      taga = FPU_gettag0();
+      if ( flags & LOADED )
+	{
+	  b = (FPU_REG *)rm;
+	  tagb = flags & 0x0f;
+	}
+      else
+	{
+	  b = &st(rm);
+	  st_ptr = b;
+	  tagb = FPU_gettagi(rm);
+	}
+    }
+
+  signa = getsign(a);
+  signb = getsign(b);
+
+  sign = signa ^ signb;
+
+  dest = &st(deststnr);
+  saved_sign = getsign(dest);
+
+  if ( !(taga | tagb) )
+    {
+      /* Both regs Valid, this should be the most common case. */
+      reg_copy(a, &x);
+      reg_copy(b, &y);
+      setpositive(&x);
+      setpositive(&y);
+      tag = FPU_u_div(&x, &y, dest, control_w, sign);
+
+      if ( tag < 0 )
+	return tag;
+
+      FPU_settagi(deststnr, tag);
+      return tag;
+    }
+
+  if ( taga == TAG_Special )
+    taga = FPU_Special(a);
+  if ( tagb == TAG_Special )
+    tagb = FPU_Special(b);
+
+  if ( ((taga == TAG_Valid) && (tagb == TW_Denormal))
+	    || ((taga == TW_Denormal) && (tagb == TAG_Valid))
+	    || ((taga == TW_Denormal) && (tagb == TW_Denormal)) )
+    {
+      if ( denormal_operand() < 0 )
+	return FPU_Exception;
+
+      FPU_to_exp16(a, &x);
+      FPU_to_exp16(b, &y);
+      tag = FPU_u_div(&x, &y, dest, control_w, sign);
+      if ( tag < 0 )
+	return tag;
+
+      FPU_settagi(deststnr, tag);
+      return tag;
+    }
+  else if ( (taga <= TW_Denormal) && (tagb <= TW_Denormal) )
+    {
+      if ( tagb != TAG_Zero )
+	{
+	  /* Want to find Zero/Valid */
+	  if ( tagb == TW_Denormal )
+	    {
+	      if ( denormal_operand() < 0 )
+		return FPU_Exception;
+	    }
+
+	  /* The result is zero. */
+	  FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
+	  setsign(dest, sign);
+	  return TAG_Zero;
+	}
+      /* We have an exception condition, either 0/0 or Valid/Zero. */
+      if ( taga == TAG_Zero )
+	{
+	  /* 0/0 */
+	  return arith_invalid(deststnr);
+	}
+      /* Valid/Zero */
+      return FPU_divide_by_zero(deststnr, sign);
+    }
+  /* Must have infinities, NaNs, etc */
+  else if ( (taga == TW_NaN) || (tagb == TW_NaN) )
+    {
+      if ( flags & LOADED )
+	return real_2op_NaN((FPU_REG *)rm, flags & 0x0f, 0, st0_ptr);
+
+      if ( flags & DEST_RM )
+	{
+	  int tag;
+	  tag = FPU_gettag0();
+	  if ( tag == TAG_Special )
+	    tag = FPU_Special(st0_ptr);
+	  return real_2op_NaN(st0_ptr, tag, rm, (flags & REV) ? st0_ptr : &st(rm));
+	}
+      else
+	{
+	  int tag;
+	  tag = FPU_gettagi(rm);
+	  if ( tag == TAG_Special )
+	    tag = FPU_Special(&st(rm));
+	  return real_2op_NaN(&st(rm), tag, 0, (flags & REV) ? st0_ptr : &st(rm));
+	}
+    }
+  else if (taga == TW_Infinity)
+    {
+      if (tagb == TW_Infinity)
+	{
+	  /* infinity/infinity */
+	  return arith_invalid(deststnr);
+	}
+      else
+	{
+	  /* tagb must be Valid or Zero */
+	  if ( (tagb == TW_Denormal) && (denormal_operand() < 0) )
+	    return FPU_Exception;
+	  
+	  /* Infinity divided by Zero or Valid does
+	     not raise and exception, but returns Infinity */
+	  FPU_copy_to_regi(a, TAG_Special, deststnr);
+	  setsign(dest, sign);
+	  return taga;
+	}
+    }
+  else if (tagb == TW_Infinity)
+    {
+      if ( (taga == TW_Denormal) && (denormal_operand() < 0) )
+	return FPU_Exception;
+
+      /* The result is zero. */
+      FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
+      setsign(dest, sign);
+      return TAG_Zero;
+    }
+#ifdef PARANOID
+  else
+    {
+      EXCEPTION(EX_INTERNAL|0x102);
+      return FPU_Exception;
+    }
+#endif /* PARANOID */ 
+
+}
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_ld_str.c linux-2.0.40/arch/i386/math-emu/reg_ld_str.c
--- linux-2.0.39/arch/i386/math-emu/reg_ld_str.c	Mon May  6 15:31:17 1996
+++ linux-2.0.40/arch/i386/math-emu/reg_ld_str.c	Mon Oct  8 23:54:43 2001
@@ -3,9 +3,9 @@
  |                                                                           |
  | All of the functions which transfer data between user memory and FPU_REGs.|
  |                                                                           |
- | Copyright (C) 1992,1993,1994,1996                                         |
+ | Copyright (C) 1992,1993,1994,1996,1997,2001                               |
  |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
- |                  E-mail   billm@jacobi.maths.monash.edu.au                |
+ |                  E-mail   billm@melbpc.org.au                             |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -17,19 +17,14 @@
  |    other processes using the emulator while swapping is in progress.      |
  +---------------------------------------------------------------------------*/
 
-#include <asm/segment.h>
-
+#include "fpu_emu.h"
 #include "fpu_system.h"
 #include "exception.h"
 #include "reg_constant.h"
-#include "fpu_emu.h"
 #include "control_w.h"
 #include "status_w.h"
 
 
-#define EXTENDED_Ebias 0x3fff
-#define EXTENDED_Emin (-0x3ffe)  /* smallest valid exponent */
-
 #define DOUBLE_Emax 1023         /* largest valid exponent */
 #define DOUBLE_Ebias 1023
 #define DOUBLE_Emin (-1022)      /* smallest valid exponent */
@@ -38,123 +33,85 @@
 #define SINGLE_Ebias 127
 #define SINGLE_Emin (-126)       /* smallest valid exponent */
 
-static void write_to_extended(FPU_REG *rp, char *d);
 
-
-/* Get a long double from user memory */
-int reg_load_extended(long double *s, FPU_REG *loaded_data)
+static u_char normalize_no_excep(FPU_REG *r, int exp, int sign)
 {
-  unsigned long sigl, sigh, exp;
+  u_char tag;
 
-  RE_ENTRANT_CHECK_OFF;
-  FPU_verify_area(VERIFY_READ, s, 10);
-  sigl = get_fs_long((unsigned long *) s);
-  sigh = get_fs_long(1 + (unsigned long *) s);
-  exp = get_fs_word(4 + (unsigned short *) s);
-  RE_ENTRANT_CHECK_ON;
+  setexponent16(r, exp);
 
-  loaded_data->tag = TW_Valid;   /* Default */
-  loaded_data->sigl = sigl;
-  loaded_data->sigh = sigh;
-  if (exp & 0x8000)
-    loaded_data->sign = SIGN_NEG;
-  else
-    loaded_data->sign = SIGN_POS;
-  exp &= 0x7fff;
-  loaded_data->exp = exp - EXTENDED_Ebias + EXP_BIAS;
+  tag = FPU_normalize_nuo(r);
+  stdexp(r);
+  if ( sign )
+    setnegative(r);
+
+  return tag;
+}
+
+
+int FPU_tagof(FPU_REG *ptr)
+{
+  int exp;
 
+  exp = exponent16(ptr) & 0x7fff;
   if ( exp == 0 )
     {
-      if ( !(sigh | sigl) )
+      if ( !(ptr->sigh | ptr->sigl) )
 	{
-	  loaded_data->tag = TW_Zero;
-	  return 0;
+	  return TAG_Zero;
 	}
       /* The number is a de-normal or pseudodenormal. */
-      if (sigh & 0x80000000)
-	{
-	  /* Is a pseudodenormal. */
-	  /* Convert it for internal use. */
-	  /* This is non-80486 behaviour because the number
-	     loses its 'denormal' identity. */
-	  loaded_data->exp++;
-	  return 1;
-	}
-      else
-	{
-	  /* Is a denormal. */
-	  /* Convert it for internal use. */
-	  loaded_data->exp++;
-	  normalize_nuo(loaded_data);
-	  return 0;
-	}
+      return TAG_Special;
     }
-  else if ( exp == 0x7fff )
-    {
-      if ( !((sigh ^ 0x80000000) | sigl) )
-	{
-	  /* Matches the bit pattern for Infinity. */
-	  loaded_data->exp = EXP_Infinity;
-	  loaded_data->tag = TW_Infinity;
-	  return 0;
-	}
 
-      loaded_data->exp = EXP_NaN;
-      loaded_data->tag = TW_NaN;
-      if ( !(sigh & 0x80000000) )
-	{
-	  /* NaNs have the ms bit set to 1. */
-	  /* This is therefore an Unsupported NaN data type. */
-	  /* This is non 80486 behaviour */
-	  /* This should generate an Invalid Operand exception
-	     later, so we convert it to a SNaN */
-	  loaded_data->sigh = 0x80000000;
-	  loaded_data->sigl = 0x00000001;
-	  loaded_data->sign = SIGN_NEG;
-	  return 1;
-	}
-      return 0;
+  if ( exp == 0x7fff )
+    {
+      /* Is an Infinity, a NaN, or an unsupported data type. */
+      return TAG_Special;
     }
 
-  if ( !(sigh & 0x80000000) )
+  if ( !(ptr->sigh & 0x80000000) )
     {
       /* Unsupported data type. */
       /* Valid numbers have the ms bit set to 1. */
       /* Unnormal. */
-      /* Convert it for internal use. */
-      /* This is non-80486 behaviour */
-      /* This should generate an Invalid Operand exception
-	 later, so we convert it to a SNaN */
-      loaded_data->sigh = 0x80000000;
-      loaded_data->sigl = 0x00000001;
-      loaded_data->sign = SIGN_NEG;
-      loaded_data->exp = EXP_NaN;
-      loaded_data->tag = TW_NaN;
-      return 1;
+      return TAG_Special;
     }
-  return 0;
+
+  return TAG_Valid;
+}
+
+
+/* Get a long double from user memory */
+int FPU_load_extended(long double *s, int stnr)
+{
+  FPU_REG *sti_ptr = &st(stnr);
+
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_READ, s, 10);
+  FPU_copy_from_user(sti_ptr, s, 10);
+  RE_ENTRANT_CHECK_ON;
+
+  return FPU_tagof(sti_ptr);
 }
 
 
 /* Get a double from user memory */
-int reg_load_double(double *dfloat, FPU_REG *loaded_data)
+int FPU_load_double(double *dfloat, FPU_REG *loaded_data)
 {
-  int exp;
+  int exp, tag, negative;
   unsigned m64, l64;
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, dfloat, 8);
-  m64 = get_fs_long(1 + (unsigned long *) dfloat);
-  l64 = get_fs_long((unsigned long *) dfloat);
+  FPU_get_user(m64, 1 + (unsigned long *) dfloat);
+  FPU_get_user(l64, (unsigned long *) dfloat);
   RE_ENTRANT_CHECK_ON;
 
-  if (m64 & 0x80000000)
-    loaded_data->sign = SIGN_NEG;
-  else
-    loaded_data->sign = SIGN_POS;
-  exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias;
+  negative = (m64 & 0x80000000) ? SIGN_Negative : SIGN_Positive;
+  exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias + EXTENDED_Ebias;
   m64 &= 0xfffff;
-  if (exp > DOUBLE_Emax)
+  if ( exp > DOUBLE_Emax + EXTENDED_Ebias )
     {
       /* Infinity or NaN */
       if ((m64 == 0) && (l64 == 0))
@@ -162,93 +119,87 @@
 	  /* +- infinity */
 	  loaded_data->sigh = 0x80000000;
 	  loaded_data->sigl = 0x00000000;
-	  loaded_data->exp = EXP_Infinity;
-	  loaded_data->tag = TW_Infinity;
-	  return 0;
+	  exp = EXP_Infinity + EXTENDED_Ebias;
+	  tag = TAG_Special;
 	}
       else
 	{
 	  /* Must be a signaling or quiet NaN */
-	  loaded_data->exp = EXP_NaN;
-	  loaded_data->tag = TW_NaN;
+	  exp = EXP_NaN + EXTENDED_Ebias;
 	  loaded_data->sigh = (m64 << 11) | 0x80000000;
 	  loaded_data->sigh |= l64 >> 21;
 	  loaded_data->sigl = l64 << 11;
-	  return 0; /* The calling function must look for NaNs */
+	  tag = TAG_Special;    /* The calling function must look for NaNs */
 	}
     }
-  else if ( exp < DOUBLE_Emin )
+  else if ( exp < DOUBLE_Emin + EXTENDED_Ebias )
     {
       /* Zero or de-normal */
       if ((m64 == 0) && (l64 == 0))
 	{
 	  /* Zero */
-	  int c = loaded_data->sign;
-	  reg_move(&CONST_Z, loaded_data);
-	  loaded_data->sign = c;
-	  return 0;
+	  reg_copy(&CONST_Z, loaded_data);
+	  exp = 0;
+	  tag = TAG_Zero;
 	}
       else
 	{
 	  /* De-normal */
-	  loaded_data->exp = DOUBLE_Emin + EXP_BIAS;
-	  loaded_data->tag = TW_Valid;
 	  loaded_data->sigh = m64 << 11;
 	  loaded_data->sigh |= l64 >> 21;
 	  loaded_data->sigl = l64 << 11;
-	  normalize_nuo(loaded_data);
-	  return denormal_operand();
+
+	  return normalize_no_excep(loaded_data, DOUBLE_Emin, negative)
+	    | (denormal_operand() < 0 ? FPU_Exception : 0);
 	}
     }
   else
     {
-      loaded_data->exp = exp + EXP_BIAS;
-      loaded_data->tag = TW_Valid;
       loaded_data->sigh = (m64 << 11) | 0x80000000;
       loaded_data->sigh |= l64 >> 21;
       loaded_data->sigl = l64 << 11;
 
-      return 0;
+      tag = TAG_Valid;
     }
+
+  setexponent16(loaded_data, exp | negative);
+
+  return tag;
 }
 
 
 /* Get a float from user memory */
-int reg_load_single(float *single, FPU_REG *loaded_data)
+int FPU_load_single(float *single, FPU_REG *loaded_data)
 {
   unsigned m32;
-  int exp;
+  int exp, tag, negative;
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, single, 4);
-  m32 = get_fs_long((unsigned long *) single);
+  FPU_get_user(m32, (unsigned long *) single);
   RE_ENTRANT_CHECK_ON;
 
-  if (m32 & 0x80000000)
-    loaded_data->sign = SIGN_NEG;
-  else
-    loaded_data->sign = SIGN_POS;
+  negative = (m32 & 0x80000000) ? SIGN_Negative : SIGN_Positive;
+
   if (!(m32 & 0x7fffffff))
     {
       /* Zero */
-      int c = loaded_data->sign;
-      reg_move(&CONST_Z, loaded_data);
-      loaded_data->sign = c;
-      return 0;
+      reg_copy(&CONST_Z, loaded_data);
+      addexponent(loaded_data, negative);
+      return TAG_Zero;
     }
-  exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias;
+  exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias + EXTENDED_Ebias;
   m32 = (m32 & 0x7fffff) << 8;
-  if ( exp < SINGLE_Emin )
+  if ( exp < SINGLE_Emin + EXTENDED_Ebias )
     {
       /* De-normals */
-      loaded_data->exp = SINGLE_Emin + EXP_BIAS;
-      loaded_data->tag = TW_Valid;
       loaded_data->sigh = m32;
       loaded_data->sigl = 0;
-      normalize_nuo(loaded_data);
-      return denormal_operand();
+
+      return normalize_no_excep(loaded_data, SINGLE_Emin, negative)
+	| (denormal_operand() < 0 ? FPU_Exception : 0);
     }
-  else if ( exp > SINGLE_Emax )
+  else if ( exp > SINGLE_Emax + EXTENDED_Ebias )
     {
     /* Infinity or NaN */
       if ( m32 == 0 )
@@ -256,131 +207,129 @@
 	  /* +- infinity */
 	  loaded_data->sigh = 0x80000000;
 	  loaded_data->sigl = 0x00000000;
-	  loaded_data->exp = EXP_Infinity;
-	  loaded_data->tag = TW_Infinity;
-	  return 0;
+	  exp = EXP_Infinity + EXTENDED_Ebias;
+	  tag = TAG_Special;
 	}
       else
 	{
 	  /* Must be a signaling or quiet NaN */
-	  loaded_data->exp = EXP_NaN;
-	  loaded_data->tag = TW_NaN;
+	  exp = EXP_NaN + EXTENDED_Ebias;
 	  loaded_data->sigh = m32 | 0x80000000;
 	  loaded_data->sigl = 0;
-	  return 0; /* The calling function must look for NaNs */
+	  tag = TAG_Special;  /* The calling function must look for NaNs */
 	}
     }
   else
     {
-      loaded_data->exp = exp + EXP_BIAS;
       loaded_data->sigh = m32 | 0x80000000;
       loaded_data->sigl = 0;
-      loaded_data->tag = TW_Valid;
-      return 0;
+      tag = TAG_Valid;
     }
+
+  setexponent16(loaded_data, exp | negative);  /* Set the sign. */
+
+  return tag;
 }
 
 
 /* Get a long long from user memory */
-void reg_load_int64(long long *_s, FPU_REG *loaded_data)
+int FPU_load_int64(long long *_s)
 {
-  int e;
   long long s;
+  int sign;
+  FPU_REG *st0_ptr = &st(0);
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, _s, 8);
-  ((unsigned long *)&s)[0] = get_fs_long((unsigned long *) _s);
-  ((unsigned long *)&s)[1] = get_fs_long(1 + (unsigned long *) _s);
+  copy_from_user(&s,_s,8);
   RE_ENTRANT_CHECK_ON;
 
   if (s == 0)
-    { reg_move(&CONST_Z, loaded_data); return; }
+    {
+      reg_copy(&CONST_Z, st0_ptr);
+      return TAG_Zero;
+    }
 
   if (s > 0)
-    loaded_data->sign = SIGN_POS;
+    sign = SIGN_Positive;
   else
   {
     s = -s;
-    loaded_data->sign = SIGN_NEG;
+    sign = SIGN_Negative;
   }
 
-  e = EXP_BIAS + 63;
-  significand(loaded_data) = s;
-  loaded_data->exp = e;
-  loaded_data->tag = TW_Valid;
-  normalize_nuo(loaded_data);
+  significand(st0_ptr) = s;
+
+  return normalize_no_excep(st0_ptr, 63, sign);
 }
 
 
 /* Get a long from user memory */
-void reg_load_int32(long *_s, FPU_REG *loaded_data)
+int FPU_load_int32(long *_s, FPU_REG *loaded_data)
 {
   long s;
-  int e;
+  int negative;
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, _s, 4);
-  s = (long)get_fs_long((unsigned long *) _s);
+  FPU_get_user(s, _s);
   RE_ENTRANT_CHECK_ON;
 
   if (s == 0)
-    { reg_move(&CONST_Z, loaded_data); return; }
+    { reg_copy(&CONST_Z, loaded_data); return TAG_Zero; }
 
   if (s > 0)
-    loaded_data->sign = SIGN_POS;
+    negative = SIGN_Positive;
   else
-  {
-    s = -s;
-    loaded_data->sign = SIGN_NEG;
-  }
+    {
+      s = -s;
+      negative = SIGN_Negative;
+    }
 
-  e = EXP_BIAS + 31;
   loaded_data->sigh = s;
   loaded_data->sigl = 0;
-  loaded_data->exp = e;
-  loaded_data->tag = TW_Valid;
-  normalize_nuo(loaded_data);
+
+  return normalize_no_excep(loaded_data, 31, negative);
 }
 
 
 /* Get a short from user memory */
-void reg_load_int16(short *_s, FPU_REG *loaded_data)
+int FPU_load_int16(short *_s, FPU_REG *loaded_data)
 {
-  int s, e;
+  int s, negative;
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, _s, 2);
   /* Cast as short to get the sign extended. */
-  s = (short)get_fs_word((unsigned short *) _s);
+  FPU_get_user(s, _s);
   RE_ENTRANT_CHECK_ON;
 
   if (s == 0)
-    { reg_move(&CONST_Z, loaded_data); return; }
+    { reg_copy(&CONST_Z, loaded_data); return TAG_Zero; }
 
   if (s > 0)
-    loaded_data->sign = SIGN_POS;
+    negative = SIGN_Positive;
   else
-  {
-    s = -s;
-    loaded_data->sign = SIGN_NEG;
-  }
+    {
+      s = -s;
+      negative = SIGN_Negative;
+    }
 
-  e = EXP_BIAS + 15;
   loaded_data->sigh = s << 16;
-
   loaded_data->sigl = 0;
-  loaded_data->exp = e;
-  loaded_data->tag = TW_Valid;
-  normalize_nuo(loaded_data);
+
+  return normalize_no_excep(loaded_data, 15, negative);
 }
 
 
 /* Get a packed bcd array from user memory */
-void reg_load_bcd(char *s, FPU_REG *loaded_data)
+int FPU_load_bcd(u_char *s)
 {
+  FPU_REG *st0_ptr = &st(0);
   int pos;
-  unsigned char bcd;
+  u_char bcd;
   long long l=0;
+  int sign;
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, s, 10);
@@ -389,7 +338,7 @@
     {
       l *= 10;
       RE_ENTRANT_CHECK_OFF;
-      bcd = (unsigned char)get_fs_byte((unsigned char *) s+pos);
+      FPU_get_user(bcd, (u_char *) s+pos);
       RE_ENTRANT_CHECK_ON;
       l += bcd >> 4;
       l *= 10;
@@ -397,30 +346,27 @@
     }
  
   RE_ENTRANT_CHECK_OFF;
-  loaded_data->sign =
-    ((unsigned char)get_fs_byte((unsigned char *) s+9)) & 0x80 ?
-      SIGN_NEG : SIGN_POS;
+  FPU_get_user(sign, (u_char *) s+9);
+  sign = sign & 0x80 ? SIGN_Negative : SIGN_Positive;
   RE_ENTRANT_CHECK_ON;
 
-  if (l == 0)
+  if ( l == 0 )
     {
-      char sign = loaded_data->sign;
-      reg_move(&CONST_Z, loaded_data);
-      loaded_data->sign = sign;
+      reg_copy(&CONST_Z, st0_ptr);
+      addexponent(st0_ptr, sign);   /* Set the sign. */
+      return TAG_Zero;
     }
   else
     {
-      significand(loaded_data) = l;
-      loaded_data->exp = EXP_BIAS + 63;
-      loaded_data->tag = TW_Valid;
-      normalize_nuo(loaded_data);
+      significand(st0_ptr) = l;
+      return normalize_no_excep(st0_ptr, 63, sign);
     }
 }
 
 /*===========================================================================*/
 
 /* Put a long double into user memory */
-int reg_store_extended(long double *d, FPU_REG *st0_ptr)
+int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double *d)
 {
   /*
     The only exception raised by an attempt to store to an
@@ -428,12 +374,16 @@
     attempting to store from an empty register.
    */
 
-  if ( st0_ptr->tag != TW_Empty )
+  if ( st0_tag != TAG_Empty )
     {
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE, d, 10);
+
+      FPU_put_user(st0_ptr->sigl, (unsigned long *) d);
+      FPU_put_user(st0_ptr->sigh, (unsigned long *) ((u_char *)d + 4));
+      FPU_put_user(exponent16(st0_ptr), (unsigned short *) ((u_char *)d + 8));
       RE_ENTRANT_CHECK_ON;
-      write_to_extended(st0_ptr, (char *) d);
+
       return 1;
     }
 
@@ -445,9 +395,9 @@
       /* Put out the QNaN indefinite */
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE,d,10);
-      put_fs_long(0, (unsigned long *) d);
-      put_fs_long(0xc0000000, 1 + (unsigned long *) d);
-      put_fs_word(0xffff, 4 + (short *) d);
+      FPU_put_user(0, (unsigned long *) d);
+      FPU_put_user(0xc0000000, 1 + (unsigned long *) d);
+      FPU_put_user(0xffff, 4 + (short *) d);
       RE_ENTRANT_CHECK_ON;
       return 1;
     }
@@ -458,38 +408,26 @@
 
 
 /* Put a double into user memory */
-int reg_store_double(double *dfloat, FPU_REG *st0_ptr)
+int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double *dfloat)
 {
   unsigned long l[2];
   unsigned long increment = 0;	/* avoid gcc warnings */
-  char st0_tag = st0_ptr->tag;
+  int precision_loss;
+  int exp;
+  FPU_REG tmp;
 
-  if (st0_tag == TW_Valid)
+  if ( st0_tag == TAG_Valid )
     {
-      int precision_loss;
-      int exp;
-      FPU_REG tmp;
-
-      reg_move(st0_ptr, &tmp);
-      exp = tmp.exp - EXP_BIAS;
+      reg_copy(st0_ptr, &tmp);
+      exp = exponent(&tmp);
 
       if ( exp < DOUBLE_Emin )     /* It may be a denormal */
 	{
-	  /* A denormal will always underflow. */
-#ifndef PECULIAR_486
-	  /* An 80486 is supposed to be able to generate
-	     a denormal exception here, but... */
-	  if ( st0_ptr->exp <= EXP_UNDER )
-	    {
-	      /* Underflow has priority. */
-	      if ( control_word & CW_Underflow )
-		denormal_operand();
-	    }
-#endif PECULIAR_486
+	  addexponent(&tmp, -DOUBLE_Emin + 52);  /* largest exp to be 51 */
 
-	  tmp.exp += -DOUBLE_Emin + 52;  /* largest exp to be 51 */
+	denormal_arg:
 
-	  if ( (precision_loss = round_to_int(&tmp)) )
+	  if ( (precision_loss = FPU_round_to_int(&tmp, st0_tag)) )
 	    {
 #ifdef PECULIAR_486
 	      /* Did it round to a non-denormal ? */
@@ -498,7 +436,7 @@
 		 converts to decide underflow. */
 	      if ( !((tmp.sigh == 0x00100000) && (tmp.sigl == 0) &&
 		  (st0_ptr->sigl & 0x000007ff)) )
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 		{
 		  EXCEPTION(EX_Underflow);
 		  /* This is a special case: see sec 16.2.5.1 of
@@ -526,10 +464,10 @@
 		    ((tmp.sigl & 0xc00) == 0xc00);            /* odd -> even */
 		  break;
 		case RC_DOWN:   /* towards -infinity */
-		  increment = (tmp.sign == SIGN_POS) ? 0 : tmp.sigl & 0x7ff;
+		  increment = signpositive(&tmp) ? 0 : tmp.sigl & 0x7ff;
 		  break;
 		case RC_UP:     /* towards +infinity */
-		  increment = (tmp.sign == SIGN_POS) ? tmp.sigl & 0x7ff : 0;
+		  increment = signpositive(&tmp) ? tmp.sigl & 0x7ff : 0;
 		  break;
 		case RC_CHOP:
 		  increment = 0;
@@ -600,33 +538,64 @@
 	    }
 	}
     }
-  else if (st0_tag == TW_Zero)
+  else if (st0_tag == TAG_Zero)
     {
       /* Number is zero */
       l[0] = 0;
       l[1] = 0;
     }
-  else if (st0_tag == TW_Infinity)
-    {
-      l[0] = 0;
-      l[1] = 0x7ff00000;
-    }
-  else if (st0_tag == TW_NaN)
+  else if ( st0_tag == TAG_Special )
     {
-      /* See if we can get a valid NaN from the FPU_REG */
-      l[0] = (st0_ptr->sigl >> 11) | (st0_ptr->sigh << 21);
-      l[1] = ((st0_ptr->sigh >> 11) & 0xfffff);
-      if ( !(st0_ptr->sigh & 0x40000000) )
+      st0_tag = FPU_Special(st0_ptr);
+      if ( st0_tag == TW_Denormal )
 	{
-	  /* It is a signalling NaN */
-	  EXCEPTION(EX_Invalid);
-	  if ( !(control_word & CW_Invalid) )
-	    return 0;
-	  l[1] |= (0x40000000 >> 11);
+	  /* A denormal will always underflow. */
+#ifndef PECULIAR_486
+	  /* An 80486 is supposed to be able to generate
+	     a denormal exception here, but... */
+	  /* Underflow has priority. */
+	  if ( control_word & CW_Underflow )
+	    denormal_operand();
+#endif /* PECULIAR_486 */
+	  reg_copy(st0_ptr, &tmp);
+	  goto denormal_arg;
+	}
+      else if (st0_tag == TW_Infinity)
+	{
+	  l[0] = 0;
+	  l[1] = 0x7ff00000;
+	}
+      else if (st0_tag == TW_NaN)
+	{
+	  /* Is it really a NaN ? */
+	  if ( (exponent(st0_ptr) == EXP_OVER)
+	       && (st0_ptr->sigh & 0x80000000) )
+	    {
+	      /* See if we can get a valid NaN from the FPU_REG */
+	      l[0] = (st0_ptr->sigl >> 11) | (st0_ptr->sigh << 21);
+	      l[1] = ((st0_ptr->sigh >> 11) & 0xfffff);
+	      if ( !(st0_ptr->sigh & 0x40000000) )
+		{
+		  /* It is a signalling NaN */
+		  EXCEPTION(EX_Invalid);
+		  if ( !(control_word & CW_Invalid) )
+		    return 0;
+		  l[1] |= (0x40000000 >> 11);
+		}
+	      l[1] |= 0x7ff00000;
+	    }
+	  else
+	    {
+	      /* It is an unsupported data type */
+	      EXCEPTION(EX_Invalid);
+	      if ( !(control_word & CW_Invalid) )
+		return 0;
+	      l[0] = 0;
+	      l[1] = 0xfff80000;
+	    }
 	}
-      l[1] |= 0x7ff00000;
     }
-  else if ( st0_tag == TW_Empty )
+  else if ( st0_tag == TAG_Empty )
     {
       /* Empty register (stack underflow) */
       EXCEPTION(EX_StackUnder);
@@ -636,21 +605,21 @@
 	  /* Put out the QNaN indefinite */
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_verify_area(VERIFY_WRITE,(void *)dfloat,8);
-	  put_fs_long(0, (unsigned long *) dfloat);
-	  put_fs_long(0xfff80000, 1 + (unsigned long *) dfloat);
+	  FPU_put_user(0, (unsigned long *) dfloat);
+	  FPU_put_user(0xfff80000, 1 + (unsigned long *) dfloat);
 	  RE_ENTRANT_CHECK_ON;
 	  return 1;
 	}
       else
 	return 0;
     }
-  if ( st0_ptr->sign )
+  if ( getsign(st0_ptr) )
     l[1] |= 0x80000000;
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,(void *)dfloat,8);
-  put_fs_long(l[0], (unsigned long *)dfloat);
-  put_fs_long(l[1], 1 + (unsigned long *)dfloat);
+  FPU_put_user(l[0], (unsigned long *)dfloat);
+  FPU_put_user(l[1], 1 + (unsigned long *)dfloat);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -658,38 +627,27 @@
 
 
 /* Put a float into user memory */
-int reg_store_single(float *single, FPU_REG *st0_ptr)
+int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float *single)
 {
   long templ;
   unsigned long increment = 0;     	/* avoid gcc warnings */
-  char st0_tag = st0_ptr->tag;
+  int precision_loss;
+  int exp;
+  FPU_REG tmp;
 
-  if (st0_tag == TW_Valid)
+  if ( st0_tag == TAG_Valid )
     {
-      int precision_loss;
-      int exp;
-      FPU_REG tmp;
 
-      reg_move(st0_ptr, &tmp);
-      exp = tmp.exp - EXP_BIAS;
+      reg_copy(st0_ptr, &tmp);
+      exp = exponent(&tmp);
 
       if ( exp < SINGLE_Emin )
 	{
-	  /* A denormal will always underflow. */
-#ifndef PECULIAR_486
-	  /* An 80486 is supposed to be able to generate
-	     a denormal exception here, but... */
-	  if ( st0_ptr->exp <= EXP_UNDER )
-	    {
-	      /* Underflow has priority. */
-	      if ( control_word & CW_Underflow )
-		denormal_operand();
-	    }
-#endif PECULIAR_486
+	  addexponent(&tmp, -SINGLE_Emin + 23);  /* largest exp to be 22 */
 
-	  tmp.exp += -SINGLE_Emin + 23;  /* largest exp to be 22 */
+	denormal_arg:
 
-	  if ( (precision_loss = round_to_int(&tmp)) )
+	  if ( (precision_loss = FPU_round_to_int(&tmp, st0_tag)) )
 	    {
 #ifdef PECULIAR_486
 	      /* Did it round to a non-denormal ? */
@@ -698,20 +656,20 @@
 		 converts to decide underflow. */
 	      if ( !((tmp.sigl == 0x00800000) &&
 		  ((st0_ptr->sigh & 0x000000ff) || st0_ptr->sigl)) )
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 		{
 		  EXCEPTION(EX_Underflow);
 		  /* This is a special case: see sec 16.2.5.1 of
 		     the 80486 book */
-		  if ( !(control_word & EX_Underflow) )
+		  if ( !(control_word & CW_Underflow) )
 		    return 0;
 		}
 	      EXCEPTION(precision_loss);
-	      if ( !(control_word & EX_Precision) )
+	      if ( !(control_word & CW_Precision) )
 		return 0;
 	    }
 	  templ = tmp.sigl;
-	}
+      }
       else
 	{
 	  if ( tmp.sigl | (tmp.sigh & 0x000000ff) )
@@ -725,15 +683,15 @@
 		case RC_RND:
 		  increment = ((sigh & 0xff) > 0x80)       /* more than half */
 		    || (((sigh & 0xff) == 0x80) && sigl)   /* more than half */
-		      || ((sigh & 0x180) == 0x180);        /* round to even */
+		    || ((sigh & 0x180) == 0x180);        /* round to even */
 		  break;
 		case RC_DOWN:   /* towards -infinity */
-		  increment = (tmp.sign == SIGN_POS)
-		              ? 0 : (sigl | (sigh & 0xff));
+		  increment = signpositive(&tmp)
+		    ? 0 : (sigl | (sigh & 0xff));
 		  break;
 		case RC_UP:     /* towards +infinity */
-		  increment = (tmp.sign == SIGN_POS)
-		              ? (sigl | (sigh & 0xff)) : 0;
+		  increment = signpositive(&tmp)
+		    ? (sigl | (sigh & 0xff)) : 0;
 		  break;
 		case RC_CHOP:
 		  increment = 0;
@@ -766,7 +724,7 @@
 	    }
 	  else
 	    precision_loss = 0;
-
+      
 	  templ = (tmp.sigh >> 8) & 0x007fffff;
 
 	  if ( exp > SINGLE_Emax )
@@ -797,29 +755,66 @@
 	    }
 	}
     }
-  else if (st0_tag == TW_Zero)
+  else if (st0_tag == TAG_Zero)
     {
       templ = 0;
     }
-  else if (st0_tag == TW_Infinity)
-    {
-      templ = 0x7f800000;
-    }
-  else if (st0_tag == TW_NaN)
+  else if ( st0_tag == TAG_Special )
     {
-      /* See if we can get a valid NaN from the FPU_REG */
-      templ = st0_ptr->sigh >> 8;
-      if ( !(st0_ptr->sigh & 0x40000000) )
+      st0_tag = FPU_Special(st0_ptr);
+      if (st0_tag == TW_Denormal)
 	{
-	  /* It is a signalling NaN */
-	  EXCEPTION(EX_Invalid);
-	  if ( !(control_word & CW_Invalid) )
-	    return 0;
-	  templ |= (0x40000000 >> 8);
+	  reg_copy(st0_ptr, &tmp);
+
+	  /* A denormal will always underflow. */
+#ifndef PECULIAR_486
+	  /* An 80486 is supposed to be able to generate
+	     a denormal exception here, but... */
+	  /* Underflow has priority. */
+	  if ( control_word & CW_Underflow )
+	    denormal_operand();
+#endif /* PECULIAR_486 */ 
+	  goto denormal_arg;
+	}
+      else if (st0_tag == TW_Infinity)
+	{
+	  templ = 0x7f800000;
+	}
+      else if (st0_tag == TW_NaN)
+	{
+	  /* Is it really a NaN ? */
+	  if ( (exponent(st0_ptr) == EXP_OVER) && (st0_ptr->sigh & 0x80000000) )
+	    {
+	      /* See if we can get a valid NaN from the FPU_REG */
+	      templ = st0_ptr->sigh >> 8;
+	      if ( !(st0_ptr->sigh & 0x40000000) )
+		{
+		  /* It is a signalling NaN */
+		  EXCEPTION(EX_Invalid);
+		  if ( !(control_word & CW_Invalid) )
+		    return 0;
+		  templ |= (0x40000000 >> 8);
+		}
+	      templ |= 0x7f800000;
+	    }
+	  else
+	    {
+	      /* It is an unsupported data type */
+	      EXCEPTION(EX_Invalid);
+	      if ( !(control_word & CW_Invalid) )
+		return 0;
+	      templ = 0xffc00000;
+	    }
 	}
-      templ |= 0x7f800000;
+#ifdef PARANOID
+      else
+	{
+	  EXCEPTION(EX_INTERNAL|0x164);
+	  return 0;
+	}
+#endif
     }
-  else if ( st0_tag == TW_Empty )
+  else if ( st0_tag == TAG_Empty )
     {
       /* Empty register (stack underflow) */
       EXCEPTION(EX_StackUnder);
@@ -829,7 +824,7 @@
 	  /* Put out the QNaN indefinite */
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_verify_area(VERIFY_WRITE,(void *)single,4);
-	  put_fs_long(0xffc00000, (unsigned long *) single);
+	  FPU_put_user(0xffc00000, (unsigned long *) single);
 	  RE_ENTRANT_CHECK_ON;
 	  return 1;
 	}
@@ -843,12 +838,12 @@
       return 0;
     }
 #endif
-  if (st0_ptr->sign)
+  if ( getsign(st0_ptr) )
     templ |= 0x80000000;
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,(void *)single,4);
-  put_fs_long(templ,(unsigned long *) single);
+  FPU_put_user(templ,(unsigned long *) single);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -856,34 +851,37 @@
 
 
 /* Put a long long into user memory */
-int reg_store_int64(long long *d, FPU_REG *st0_ptr)
+int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long *d)
 {
   FPU_REG t;
   long long tll;
   int precision_loss;
-  char st0_tag = st0_ptr->tag;
 
-  if ( st0_tag == TW_Empty )
+  if ( st0_tag == TAG_Empty )
     {
       /* Empty register (stack underflow) */
       EXCEPTION(EX_StackUnder);
       goto invalid_operand;
     }
-  else if ( (st0_tag == TW_Infinity) ||
-	   (st0_tag == TW_NaN) )
+  else if ( st0_tag == TAG_Special )
     {
-      EXCEPTION(EX_Invalid);
-      goto invalid_operand;
+      st0_tag = FPU_Special(st0_ptr);
+      if ( (st0_tag == TW_Infinity) ||
+	   (st0_tag == TW_NaN) )
+	{
+	  EXCEPTION(EX_Invalid);
+	  goto invalid_operand;
+	}
     }
 
-  reg_move(st0_ptr, &t);
-  precision_loss = round_to_int(&t);
+  reg_copy(st0_ptr, &t);
+  precision_loss = FPU_round_to_int(&t, st0_tag);
   ((long *)&tll)[0] = t.sigl;
   ((long *)&tll)[1] = t.sigh;
   if ( (precision_loss == 1) ||
       ((t.sigh & 0x80000000) &&
        !((t.sigh == 0x80000000) && (t.sigl == 0) &&
-	 (t.sign == SIGN_NEG))) )
+	 signnegative(&t))) )
     {
       EXCEPTION(EX_Invalid);
       /* This is a special case: see sec 16.2.5.1 of the 80486 book */
@@ -900,14 +898,13 @@
     {
       if ( precision_loss )
 	set_precision_flag(precision_loss);
-      if ( t.sign )
+      if ( signnegative(&t) )
 	tll = - tll;
     }
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,(void *)d,8);
-  put_fs_long(((long *)&tll)[0],(unsigned long *) d);
-  put_fs_long(((long *)&tll)[1],1 + (unsigned long *) d);
+  copy_to_user(d, &tll, 8);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -915,30 +912,33 @@
 
 
 /* Put a long into user memory */
-int reg_store_int32(long *d, FPU_REG *st0_ptr)
+int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long *d)
 {
   FPU_REG t;
   int precision_loss;
-  char st0_tag = st0_ptr->tag;
 
-  if ( st0_tag == TW_Empty )
+  if ( st0_tag == TAG_Empty )
     {
       /* Empty register (stack underflow) */
       EXCEPTION(EX_StackUnder);
       goto invalid_operand;
     }
-  else if ( (st0_tag == TW_Infinity) ||
-	   (st0_tag == TW_NaN) )
+  else if ( st0_tag == TAG_Special )
     {
-      EXCEPTION(EX_Invalid);
-      goto invalid_operand;
+      st0_tag = FPU_Special(st0_ptr);
+      if ( (st0_tag == TW_Infinity) ||
+	   (st0_tag == TW_NaN) )
+	{
+	  EXCEPTION(EX_Invalid);
+	  goto invalid_operand;
+	}
     }
 
-  reg_move(st0_ptr, &t);
-  precision_loss = round_to_int(&t);
+  reg_copy(st0_ptr, &t);
+  precision_loss = FPU_round_to_int(&t, st0_tag);
   if (t.sigh ||
       ((t.sigl & 0x80000000) &&
-       !((t.sigl == 0x80000000) && (t.sign == SIGN_NEG))) )
+       !((t.sigl == 0x80000000) && signnegative(&t))) )
     {
       EXCEPTION(EX_Invalid);
       /* This is a special case: see sec 16.2.5.1 of the 80486 book */
@@ -955,13 +955,13 @@
     {
       if ( precision_loss )
 	set_precision_flag(precision_loss);
-      if ( t.sign )
+      if ( signnegative(&t) )
 	t.sigl = -(long)t.sigl;
     }
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,d,4);
-  put_fs_long(t.sigl, (unsigned long *) d);
+  FPU_put_user(t.sigl, (unsigned long *) d);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -969,30 +969,33 @@
 
 
 /* Put a short into user memory */
-int reg_store_int16(short *d, FPU_REG *st0_ptr)
+int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short *d)
 {
   FPU_REG t;
   int precision_loss;
-  char st0_tag = st0_ptr->tag;
 
-  if ( st0_tag == TW_Empty )
+  if ( st0_tag == TAG_Empty )
     {
       /* Empty register (stack underflow) */
       EXCEPTION(EX_StackUnder);
       goto invalid_operand;
     }
-  else if ( (st0_tag == TW_Infinity) ||
-	   (st0_tag == TW_NaN) )
+  else if ( st0_tag == TAG_Special )
     {
-      EXCEPTION(EX_Invalid);
-      goto invalid_operand;
+      st0_tag = FPU_Special(st0_ptr);
+      if ( (st0_tag == TW_Infinity) ||
+	   (st0_tag == TW_NaN) )
+	{
+	  EXCEPTION(EX_Invalid);
+	  goto invalid_operand;
+	}
     }
 
-  reg_move(st0_ptr, &t);
-  precision_loss = round_to_int(&t);
+  reg_copy(st0_ptr, &t);
+  precision_loss = FPU_round_to_int(&t, st0_tag);
   if (t.sigh ||
       ((t.sigl & 0xffff8000) &&
-       !((t.sigl == 0x8000) && (t.sign == SIGN_NEG))) )
+       !((t.sigl == 0x8000) && signnegative(&t))) )
     {
       EXCEPTION(EX_Invalid);
       /* This is a special case: see sec 16.2.5.1 of the 80486 book */
@@ -1009,13 +1012,13 @@
     {
       if ( precision_loss )
 	set_precision_flag(precision_loss);
-      if ( t.sign )
+      if ( signnegative(&t) )
 	t.sigl = -t.sigl;
     }
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,d,2);
-  put_fs_word((short)t.sigl,(short *) d);
+  FPU_put_user((short)t.sigl,(short *) d);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -1023,24 +1026,33 @@
 
 
 /* Put a packed bcd array into user memory */
-int reg_store_bcd(char *d, FPU_REG *st0_ptr)
+int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char *d)
 {
   FPU_REG t;
   unsigned long long ll;
-  unsigned char b;
+  u_char b;
   int i, precision_loss;
-  unsigned char sign = (st0_ptr->sign == SIGN_NEG) ? 0x80 : 0;
-  char st0_tag = st0_ptr->tag;
+  u_char sign = (getsign(st0_ptr) == SIGN_NEG) ? 0x80 : 0;
 
-  if ( st0_tag == TW_Empty )
+  if ( st0_tag == TAG_Empty )
     {
       /* Empty register (stack underflow) */
       EXCEPTION(EX_StackUnder);
       goto invalid_operand;
     }
+  else if ( st0_tag == TAG_Special )
+    {
+      st0_tag = FPU_Special(st0_ptr);
+      if ( (st0_tag == TW_Infinity) ||
+	   (st0_tag == TW_NaN) )
+	{
+	  EXCEPTION(EX_Invalid);
+	  goto invalid_operand;
+	}
+    }
 
-  reg_move(st0_ptr, &t);
-  precision_loss = round_to_int(&t);
+  reg_copy(st0_ptr, &t);
+  precision_loss = FPU_round_to_int(&t, st0_tag);
   ll = significand(&t);
 
   /* Check for overflow, by comparing with 999999999999999999 decimal. */
@@ -1056,10 +1068,10 @@
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_verify_area(VERIFY_WRITE,d,10);
 	  for ( i = 0; i < 7; i++)
-	    put_fs_byte(0, (unsigned char *) d+i); /* These bytes "undefined" */
-	  put_fs_byte(0xc0, (unsigned char *) d+7); /* This byte "undefined" */
-	  put_fs_byte(0xff, (unsigned char *) d+8);
-	  put_fs_byte(0xff, (unsigned char *) d+9);
+	    FPU_put_user(0, (u_char *) d+i); /* These bytes "undefined" */
+	  FPU_put_user(0xc0, (u_char *) d+7); /* This byte "undefined" */
+	  FPU_put_user(0xff, (u_char *) d+8);
+	  FPU_put_user(0xff, (u_char *) d+9);
 	  RE_ENTRANT_CHECK_ON;
 	  return 1;
 	}
@@ -1077,14 +1089,14 @@
   RE_ENTRANT_CHECK_ON;
   for ( i = 0; i < 9; i++)
     {
-      b = div_small(&ll, 10);
-      b |= (div_small(&ll, 10)) << 4;
+      b = FPU_div_small(&ll, 10);
+      b |= (FPU_div_small(&ll, 10)) << 4;
       RE_ENTRANT_CHECK_OFF;
-      put_fs_byte(b,(unsigned char *) d+i);
+      FPU_put_user(b,(u_char *) d+i);
       RE_ENTRANT_CHECK_ON;
     }
   RE_ENTRANT_CHECK_OFF;
-  put_fs_byte(sign,(unsigned char *) d+9);
+  FPU_put_user(sign,(u_char *) d+9);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -1100,25 +1112,25 @@
 /* Overflow is signalled by a non-zero return value (in eax).
    In the case of overflow, the returned significand always has the
    largest possible value */
-int round_to_int(FPU_REG *r)
+int FPU_round_to_int(FPU_REG *r, u_char tag)
 {
-  char     very_big;
+  u_char     very_big;
   unsigned eax;
 
-  if (r->tag == TW_Zero)
+  if (tag == TAG_Zero)
     {
       /* Make sure that zero is returned */
       significand(r) = 0;
       return 0;        /* o.k. */
     }
-  
-  if (r->exp > EXP_BIAS + 63)
+
+  if (exponent(r) > 63)
     {
       r->sigl = r->sigh = ~0;      /* The largest representable number */
       return 1;        /* overflow */
     }
 
-  eax = shrxs(&r->sigl, EXP_BIAS + 63 - r->exp);
+  eax = FPU_shrxs(&r->sigl, 63 - exponent(r));
   very_big = !(~(r->sigh) | ~(r->sigl));  /* test for 0xfff...fff */
 #define	half_or_more	(eax & 0x80000000)
 #define	frac_part	(eax)
@@ -1135,7 +1147,7 @@
 	}
       break;
     case RC_DOWN:
-      if (frac_part && r->sign)
+      if (frac_part && getsign(r))
 	{
 	  if ( very_big ) return 1;        /* overflow */
 	  significand(r) ++;
@@ -1143,7 +1155,7 @@
 	}
       break;
     case RC_UP:
-      if (frac_part && !r->sign)
+      if (frac_part && !getsign(r))
 	{
 	  if ( very_big ) return 1;        /* overflow */
 	  significand(r) ++;
@@ -1160,10 +1172,10 @@
 
 /*===========================================================================*/
 
-char *fldenv(fpu_addr_modes addr_modes, char *s)
+u_char *fldenv(fpu_addr_modes addr_modes, u_char *s)
 {
   unsigned short tag_word = 0;
-  unsigned char tag;
+  u_char tag;
   int i;
 
   if ( (addr_modes.default_mode == VM86) ||
@@ -1172,13 +1184,13 @@
     {
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_READ, s, 0x0e);
-      control_word = get_fs_word((unsigned short *) s);
-      partial_status = get_fs_word((unsigned short *) (s+2));
-      tag_word = get_fs_word((unsigned short *) (s+4));
-      instruction_address.offset = get_fs_word((unsigned short *) (s+6));
-      instruction_address.selector = get_fs_word((unsigned short *) (s+8));
-      operand_address.offset = get_fs_word((unsigned short *) (s+0x0a));
-      operand_address.selector = get_fs_word((unsigned short *) (s+0x0c));
+      FPU_get_user(control_word, (unsigned short *) s);
+      FPU_get_user(partial_status, (unsigned short *) (s+2));
+      FPU_get_user(tag_word, (unsigned short *) (s+4));
+      FPU_get_user(instruction_address.offset, (unsigned short *) (s+6));
+      FPU_get_user(instruction_address.selector, (unsigned short *) (s+8));
+      FPU_get_user(operand_address.offset, (unsigned short *) (s+0x0a));
+      FPU_get_user(operand_address.selector, (unsigned short *) (s+0x0c));
       RE_ENTRANT_CHECK_ON;
       s += 0x0e;
       if ( addr_modes.default_mode == VM86 )
@@ -1192,23 +1204,23 @@
     {
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_READ, s, 0x1c);
-      control_word = get_fs_word((unsigned short *) s);
-      partial_status = get_fs_word((unsigned short *) (s+4));
-      tag_word = get_fs_word((unsigned short *) (s+8));
-      instruction_address.offset = get_fs_long((unsigned long *) (s+0x0c));
-      instruction_address.selector = get_fs_word((unsigned short *) (s+0x10));
-      instruction_address.opcode = get_fs_word((unsigned short *) (s+0x12));
-      operand_address.offset = get_fs_long((unsigned long *) (s+0x14));
-      operand_address.selector = get_fs_long((unsigned long *) (s+0x18));
+      FPU_get_user(control_word, (unsigned short *) s);
+      FPU_get_user(partial_status, (unsigned short *) (s+4));
+      FPU_get_user(tag_word, (unsigned short *) (s+8));
+      FPU_get_user(instruction_address.offset, (unsigned long *) (s+0x0c));
+      FPU_get_user(instruction_address.selector, (unsigned short *) (s+0x10));
+      FPU_get_user(instruction_address.opcode, (unsigned short *) (s+0x12));
+      FPU_get_user(operand_address.offset, (unsigned long *) (s+0x14));
+      FPU_get_user(operand_address.selector, (unsigned long *) (s+0x18));
       RE_ENTRANT_CHECK_ON;
       s += 0x1c;
     }
 
 #ifdef PECULIAR_486
   control_word &= ~0xe080;
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */ 
 
-  top = (partial_status >> SW_Top_Shift) & 7;
+  FPU_top = (partial_status >> SW_Top_Shift) & 7;
 
   if ( partial_status & ~control_word & CW_Exceptions )
     partial_status |= (SW_Summary | SW_Backward);
@@ -1220,29 +1232,28 @@
       tag = tag_word & 3;
       tag_word >>= 2;
 
-      if ( tag == 3 )
+      if ( tag == TAG_Empty )
 	/* New tag is empty.  Accept it */
-	regs[i].tag = TW_Empty;
-      else if ( regs[i].tag == TW_Empty )
+	FPU_settag(i, TAG_Empty);
+      else if ( FPU_gettag(i) == TAG_Empty )
 	{
 	  /* Old tag is empty and new tag is not empty.  New tag is determined
 	     by old reg contents */
-	  if ( regs[i].exp == EXP_BIAS - EXTENDED_Ebias )
+	  if ( exponent(&fpu_register(i)) == - EXTENDED_Ebias )
 	    {
-	      if ( !(regs[i].sigl | regs[i].sigh) )
-		regs[i].tag = TW_Zero;
+	      if ( !(fpu_register(i).sigl | fpu_register(i).sigh) )
+		FPU_settag(i, TAG_Zero);
 	      else
-		regs[i].tag = TW_Valid;
+		FPU_settag(i, TAG_Special);
 	    }
-	  else if ( regs[i].exp == 0x7fff + EXP_BIAS - EXTENDED_Ebias )
+	  else if ( exponent(&fpu_register(i)) == 0x7fff - EXTENDED_Ebias )
 	    {
-	      if ( !((regs[i].sigh & ~0x80000000) | regs[i].sigl) )
-		regs[i].tag = TW_Infinity;
-	      else
-		regs[i].tag = TW_NaN;
+	      FPU_settag(i, TAG_Special);
 	    }
+	  else if ( fpu_register(i).sigh & 0x80000000 )
+	    FPU_settag(i, TAG_Valid);
 	  else
-	    regs[i].tag = TW_Valid;
+	    FPU_settag(i, TAG_Special);   /* An Un-normal */
   	}
       /* Else old tag is not empty and new tag is not empty.  Old tag
 	 remains correct */
@@ -1252,56 +1263,32 @@
 }
 
 
-void frstor(fpu_addr_modes addr_modes, char *data_address)
+void frstor(fpu_addr_modes addr_modes, u_char *data_address)
 {
-  int i, stnr;
-  unsigned char tag;
-  char *s = fldenv(addr_modes, data_address);
+  int i, regnr;
+  u_char *s = fldenv(addr_modes, data_address);
+  int offset = (FPU_top & 7) * 10, other = 80 - offset;
+
+  /* Copy all registers in stack order. */
+  RE_ENTRANT_CHECK_OFF;
+  FPU_verify_area(VERIFY_READ,s,80);
+  FPU_copy_from_user(register_base+offset, s, other);
+  if ( offset )
+    FPU_copy_from_user(register_base, s+other, offset);
+  RE_ENTRANT_CHECK_ON;
 
   for ( i = 0; i < 8; i++ )
     {
-      /* Load each register. */
-      stnr = (i+top) & 7;
-      tag = regs[stnr].tag;   /* Derived from the fldenv() loaded tag word. */
-      reg_load_extended((long double *)(s+i*10), &regs[stnr]);
-      if ( tag == TW_Empty )  /* The loaded data over-rides all other cases. */
-	regs[stnr].tag = tag;
+      regnr = (i+FPU_top) & 7;
+      if ( FPU_gettag(regnr) != TAG_Empty )
+	/* The loaded data over-rides all other cases. */
+	FPU_settag(regnr, FPU_tagof(&st(i)));
     }
 
 }
 
 
-unsigned short tag_word(void)
-{
-  unsigned short word = 0;
-  unsigned char tag;
-  int i;
-
-  for ( i = 7; i >= 0; i-- )
-    {
-      switch ( tag = regs[i].tag )
-	{
-	case TW_Valid:
-	  if ( regs[i].exp <= (EXP_BIAS - EXTENDED_Ebias) )
-	    tag = 2;
-	  break;
-	case TW_Infinity:
-	case TW_NaN:
-	  tag = 2;
-	  break;
-	case TW_Empty:
-	  tag = 3;
-	  break;
-	  /* TW_Zero already has the correct value */
-	}
-      word <<= 2;
-      word |= tag;
-    }
-  return word;
-}
-
-
-char *fstenv(fpu_addr_modes addr_modes, char *d)
+u_char *fstenv(fpu_addr_modes addr_modes, u_char *d)
 {
   if ( (addr_modes.default_mode == VM86) ||
       ((addr_modes.default_mode == PM16)
@@ -1310,25 +1297,25 @@
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE,d,14);
 #ifdef PECULIAR_486
-      put_fs_long(control_word & ~0xe080, (unsigned short *) d);
+      FPU_put_user(control_word & ~0xe080, (unsigned long *) d);
 #else
-      put_fs_word(control_word, (unsigned short *) d);
-#endif PECULIAR_486
-      put_fs_word(status_word(), (unsigned short *) (d+2));
-      put_fs_word(tag_word(), (unsigned short *) (d+4));
-      put_fs_word(instruction_address.offset, (unsigned short *) (d+6));
-      put_fs_word(operand_address.offset, (unsigned short *) (d+0x0a));
+      FPU_put_user(control_word, (unsigned short *) d);
+#endif /* PECULIAR_486 */
+      FPU_put_user(status_word(), (unsigned short *) (d+2));
+      FPU_put_user(fpu_tag_word, (unsigned short *) (d+4));
+      FPU_put_user(instruction_address.offset, (unsigned short *) (d+6));
+      FPU_put_user(operand_address.offset, (unsigned short *) (d+0x0a));
       if ( addr_modes.default_mode == VM86 )
 	{
-	  put_fs_word((instruction_address.offset & 0xf0000) >> 4,
+	  FPU_put_user((instruction_address.offset & 0xf0000) >> 4,
 		      (unsigned short *) (d+8));
-	  put_fs_word((operand_address.offset & 0xf0000) >> 4,
+	  FPU_put_user((operand_address.offset & 0xf0000) >> 4,
 		      (unsigned short *) (d+0x0c));
 	}
       else
 	{
-	  put_fs_word(instruction_address.selector, (unsigned short *) (d+8));
-	  put_fs_word(operand_address.selector, (unsigned short *) (d+0x0c));
+	  FPU_put_user(instruction_address.selector, (unsigned short *) (d+8));
+	  FPU_put_user(operand_address.selector, (unsigned short *) (d+0x0c));
 	}
       RE_ENTRANT_CHECK_ON;
       d += 0x0e;
@@ -1336,28 +1323,17 @@
   else
     {
       RE_ENTRANT_CHECK_OFF;
-      FPU_verify_area(VERIFY_WRITE,d,28);
-#ifdef PECULIAR_486
-      /* An 80486 sets all the reserved bits to 1. */
-      put_fs_long(0xffff0040 | (control_word & ~0xe080), (unsigned long *) d);
-      put_fs_long(0xffff0000 | status_word(), (unsigned long *) (d+4));
-      put_fs_long(0xffff0000 | tag_word(), (unsigned long *) (d+8));
-#else
-      put_fs_word(control_word, (unsigned short *) d);
-      put_fs_word(status_word(), (unsigned short *) (d+4));
-      put_fs_word(tag_word(), (unsigned short *) (d+8));
-#endif PECULIAR_486
-      put_fs_long(instruction_address.offset, (unsigned long *) (d+0x0c));
-      put_fs_word(instruction_address.selector, (unsigned short *) (d+0x10));
-      put_fs_word(instruction_address.opcode, (unsigned short *) (d+0x12));
-      put_fs_long(operand_address.offset, (unsigned long *) (d+0x14));
+      FPU_verify_area(VERIFY_WRITE, d, 7*4);
 #ifdef PECULIAR_486
-      /* An 80486 sets all the reserved bits to 1. */
-      put_fs_word(operand_address.selector, (unsigned short *) (d+0x18));
-      put_fs_word(0xffff, (unsigned short *) (d+0x1a));
-#else
-      put_fs_long(operand_address.selector, (unsigned long *) (d+0x18));
-#endif PECULIAR_486
+      control_word &= ~0xe080;
+      /* An 80486 sets nearly all of the reserved bits to 1. */
+      control_word |= 0xffff0040;
+      partial_status = status_word() | 0xffff0000;
+      fpu_tag_word |= 0xffff0000;
+      I387.soft.fcs &= ~0xf8000000;
+      I387.soft.fos |= 0xffff0000;
+#endif /* PECULIAR_486 */
+      FPU_copy_to_user(d, &control_word, 7*4);
       RE_ENTRANT_CHECK_ON;
       d += 0x1c;
     }
@@ -1369,84 +1345,23 @@
 }
 
 
-void fsave(fpu_addr_modes addr_modes, char *data_address)
+void fsave(fpu_addr_modes addr_modes, u_char *data_address)
 {
-  char *d;
-  int i;
+  u_char *d;
+  int offset = (FPU_top & 7) * 10, other = 80 - offset;
 
   d = fstenv(addr_modes, data_address);
+
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,d,80);
+
+  /* Copy all registers in stack order. */
+  FPU_copy_to_user(d, register_base+offset, other);
+  if ( offset )
+    FPU_copy_to_user(d+other, register_base, offset);
   RE_ENTRANT_CHECK_ON;
-  for ( i = 0; i < 8; i++ )
-    write_to_extended(&regs[(top + i) & 7], d + 10 * i);
 
   finit();
-
 }
 
 /*===========================================================================*/
-
-/*
-  A call to this function must be preceded by a call to
-  FPU_verify_area() to verify access to the 10 bytes at d
-  */
-static void write_to_extended(FPU_REG *rp, char *d)
-{
-  long e;
-  FPU_REG tmp;
-  
-  e = rp->exp - EXP_BIAS + EXTENDED_Ebias;
-
-#ifdef PARANOID
-  switch ( rp->tag )
-    {
-    case TW_Zero:
-      if ( rp->sigh | rp->sigl | e )
-	EXCEPTION(EX_INTERNAL | 0x160);
-      break;
-    case TW_Infinity:
-    case TW_NaN:
-      if ( (e ^ 0x7fff) | !(rp->sigh & 0x80000000) )
-	EXCEPTION(EX_INTERNAL | 0x161);
-      break;
-    default:
-      if (e > 0x7fff || e < -63)
-	EXCEPTION(EX_INTERNAL | 0x162);
-    }
-#endif PARANOID
-
-  /*
-    All numbers except denormals are stored internally in a
-    format which is compatible with the extended real number
-    format.
-   */
-  if ( e > 0 )
-    {
-      /* just copy the reg */
-      RE_ENTRANT_CHECK_OFF;
-      put_fs_long(rp->sigl, (unsigned long *) d);
-      put_fs_long(rp->sigh, (unsigned long *) (d + 4));
-      RE_ENTRANT_CHECK_ON;
-    }
-  else
-    {
-      /*
-	The number is a de-normal stored as a normal using our
-	extra exponent range, or is Zero.
-	Convert it back to a de-normal, or leave it as Zero.
-       */
-      reg_move(rp, &tmp);
-      tmp.exp += -EXTENDED_Emin + 63;  /* largest exp to be 63 */
-      round_to_int(&tmp);
-      e = 0;
-      RE_ENTRANT_CHECK_OFF;
-      put_fs_long(tmp.sigl, (unsigned long *) d);
-      put_fs_long(tmp.sigh, (unsigned long *) (d + 4));
-      RE_ENTRANT_CHECK_ON;
-    }
-  e |= rp->sign == SIGN_POS ? 0 : 0x8000;
-  RE_ENTRANT_CHECK_OFF;
-  put_fs_word(e, (unsigned short *) (d + 8));
-  RE_ENTRANT_CHECK_ON;
-}
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_mul.c linux-2.0.40/arch/i386/math-emu/reg_mul.c
--- linux-2.0.39/arch/i386/math-emu/reg_mul.c	Fri Feb 25 13:42:46 1994
+++ linux-2.0.40/arch/i386/math-emu/reg_mul.c	Mon Oct  8 23:54:43 2001
@@ -3,10 +3,11 @@
  |                                                                           |
  | Multiply one FPU_REG by another, put the result in a destination FPU_REG. |
  |                                                                           |
- | Copyright (C) 1992,1993                                                   |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ | Copyright (C) 1992,1993,1997                                              |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
  |                                                                           |
+ | Returns the tag of the result if no exceptions or errors occurred.        |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
@@ -14,92 +15,117 @@
  | The destination may be any FPU_REG, including one of the source FPU_REGs. |
  +---------------------------------------------------------------------------*/
 
+#include "fpu_emu.h"
 #include "exception.h"
 #include "reg_constant.h"
-#include "fpu_emu.h"
 #include "fpu_system.h"
 
 
+/*
+  Multiply two registers to give a register result.
+  The sources are st(deststnr) and (b,tagb,signb).
+  The destination is st(deststnr).
+  */
 /* This routine must be called with non-empty source registers */
-int reg_mul(FPU_REG const *a, FPU_REG const *b,
-	    FPU_REG *dest, unsigned int control_w)
+int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w)
 {
-  char saved_sign = dest->sign;
-  char sign = (a->sign ^ b->sign);
+  FPU_REG *a = &st(deststnr);
+  FPU_REG *dest = a;
+  u_char taga = FPU_gettagi(deststnr);
+  u_char saved_sign = getsign(dest);
+  u_char sign = (getsign(a) ^ getsign(b));
+  int tag;
 
-  if (!(a->tag | b->tag))
+
+  if ( !(taga | tagb) )
     {
       /* Both regs Valid, this should be the most common case. */
-      dest->sign = sign;
-      if ( reg_u_mul(a, b, dest, control_w) )
+
+      tag = FPU_u_mul(a, b, dest, control_w, sign, exponent(a) + exponent(b));
+      if ( tag < 0 )
 	{
-	  dest->sign = saved_sign;
-	  return 1;
+	  setsign(dest, saved_sign);
+	  return tag;
 	}
-      return 0;
+      FPU_settagi(deststnr, tag);
+      return tag;
     }
-  else if ((a->tag <= TW_Zero) && (b->tag <= TW_Zero))
+
+  if ( taga == TAG_Special )
+    taga = FPU_Special(a);
+  if ( tagb == TAG_Special )
+    tagb = FPU_Special(b);
+
+  if ( ((taga == TAG_Valid) && (tagb == TW_Denormal))
+	    || ((taga == TW_Denormal) && (tagb == TAG_Valid))
+	    || ((taga == TW_Denormal) && (tagb == TW_Denormal)) )
     {
-#ifdef DENORM_OPERAND
-      if ( ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER)) ||
-	  ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER)) )
+      FPU_REG x, y;
+      if ( denormal_operand() < 0 )
+	return FPU_Exception;
+
+      FPU_to_exp16(a, &x);
+      FPU_to_exp16(b, &y);
+      tag = FPU_u_mul(&x, &y, dest, control_w, sign,
+		      exponent16(&x) + exponent16(&y));
+      if ( tag < 0 )
 	{
-	  if ( denormal_operand() ) return 1;
+	  setsign(dest, saved_sign);
+	  return tag;
 	}
-#endif DENORM_OPERAND
+      FPU_settagi(deststnr, tag);
+      return tag;
+    }
+  else if ( (taga <= TW_Denormal) && (tagb <= TW_Denormal) )
+    {
+      if ( ((tagb == TW_Denormal) || (taga == TW_Denormal))
+	   && (denormal_operand() < 0) )
+	return FPU_Exception;
+
       /* Must have either both arguments == zero, or
 	 one valid and the other zero.
 	 The result is therefore zero. */
-      reg_move(&CONST_Z, dest);
+      FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
       /* The 80486 book says that the answer is +0, but a real
 	 80486 behaves this way.
 	 IEEE-754 apparently says it should be this way. */
-      dest->sign = sign;
-      return 0;
+      setsign(dest, sign);
+      return TAG_Zero;
     }
-  else
-    {
       /* Must have infinities, NaNs, etc */
-      if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) )
-	{ return real_2op_NaN(a, b, dest); }
-      else if (a->tag == TW_Infinity)
-	{
-	  if (b->tag == TW_Zero)
-	    { return arith_invalid(dest); }  /* Zero*Infinity is invalid */
-	  else
-	    {
-#ifdef DENORM_OPERAND
-	      if ( (b->tag == TW_Valid) && (b->exp <= EXP_UNDER) &&
-		  denormal_operand() )
-		return 1;
-#endif DENORM_OPERAND
-	      reg_move(a, dest);
-	      dest->sign = sign;
-	    }
-	  return 0;
-	}
-      else if (b->tag == TW_Infinity)
-	{
-	  if (a->tag == TW_Zero)
-	    { return arith_invalid(dest); }  /* Zero*Infinity is invalid */
-	  else
-	    {
-#ifdef DENORM_OPERAND
-	      if ( (a->tag == TW_Valid) && (a->exp <= EXP_UNDER) &&
-		  denormal_operand() )
-		return 1;
-#endif DENORM_OPERAND
-	      reg_move(b, dest);
-	      dest->sign = sign;
-	    }
-	  return 0;
-	}
+  else if ( (taga == TW_NaN) || (tagb == TW_NaN) )
+    {
+      return real_2op_NaN(b, tagb, deststnr, &st(0));
+    }
+  else if ( ((taga == TW_Infinity) && (tagb == TAG_Zero))
+	    || ((tagb == TW_Infinity) && (taga == TAG_Zero)) )
+    {
+      return arith_invalid(deststnr);  /* Zero*Infinity is invalid */
+    }
+  else if ( ((taga == TW_Denormal) || (tagb == TW_Denormal))
+	    && (denormal_operand() < 0) )
+    {
+      return FPU_Exception;
+    }
+  else if (taga == TW_Infinity)
+    {
+      FPU_copy_to_regi(a, TAG_Special, deststnr);
+      setsign(dest, sign);
+      return TAG_Special;
+    }
+  else if (tagb == TW_Infinity)
+    {
+      FPU_copy_to_regi(b, TAG_Special, deststnr);
+      setsign(dest, sign);
+      return TAG_Special;
+    }
+
 #ifdef PARANOID
-      else
-	{
-	  EXCEPTION(EX_INTERNAL|0x102);
-	  return 1;
-	}
-#endif PARANOID
+  else
+    {
+      EXCEPTION(EX_INTERNAL|0x102);
+      return FPU_Exception;
     }
+#endif /* PARANOID */ 
+
 }
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_norm.S linux-2.0.40/arch/i386/math-emu/reg_norm.S
--- linux-2.0.39/arch/i386/math-emu/reg_norm.S	Thu Oct  5 14:30:43 1995
+++ linux-2.0.40/arch/i386/math-emu/reg_norm.S	Mon Oct  8 23:54:43 2001
@@ -1,16 +1,19 @@
 /*---------------------------------------------------------------------------+
  |  reg_norm.S                                                               |
  |                                                                           |
- | Copyright (C) 1992,1993,1994,1995                                         |
+ | Copyright (C) 1992,1993,1994,1995,1997                                    |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                       Australia.  E-mail billm@suburbia.net               |
  |                                                                           |
  | Normalize the value in a FPU_REG.                                         |
  |                                                                           |
  | Call from C as:                                                           |
- |   void normalize(FPU_REG *n)                                              |
+ |    int FPU_normalize(FPU_REG *n)                                          |
  |                                                                           |
- |   void normalize_nuo(FPU_REG *n)                                          |
+ |    int FPU_normalize_nuo(FPU_REG *n)                                      |
+ |                                                                           |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
@@ -18,24 +21,13 @@
 
 
 .text
-ENTRY(normalize)
+ENTRY(FPU_normalize)
 	pushl	%ebp
 	movl	%esp,%ebp
 	pushl	%ebx
 
 	movl	PARAM1,%ebx
 
-#ifdef PARANOID
-	cmpb	TW_Valid,TAG(%ebx)
-	je	L_ok
-
-	pushl	$0x220
-	call	SYMBOL_NAME(exception)
-	addl	$4,%esp
-
-L_ok:
-#endif PARANOID
-
 	movl	SIGH(%ebx),%edx
 	movl	SIGL(%ebx),%eax
 
@@ -48,7 +40,7 @@
 
 	movl	%eax,%edx
 	xorl	%eax,%eax
-	subl	$32,EXP(%ebx)	/* This can cause an underflow */
+	subw	$32,EXP(%ebx)	/* This can cause an underflow */
 
 /* We need to shift left by 1 - 31 bits */
 L_shift_1:
@@ -57,18 +49,25 @@
 	negl	%ecx
 	shld	%cl,%eax,%edx
 	shl	%cl,%eax
-	subl	%ecx,EXP(%ebx)	/* This can cause an underflow */
+	subw	%cx,EXP(%ebx)	/* This can cause an underflow */
 
 	movl	%edx,SIGH(%ebx)
 	movl	%eax,SIGL(%ebx)
 
 L_done:
-	cmpl	EXP_OVER,EXP(%ebx)
+	cmpw	EXP_OVER,EXP(%ebx)
 	jge	L_overflow
 
-	cmpl	EXP_UNDER,EXP(%ebx)
+	cmpw	EXP_UNDER,EXP(%ebx)
 	jle	L_underflow
 
+L_exit_valid:
+	movl	TAG_Valid,%eax
+
+	/* Convert the exponent to 80x87 form. */
+	addw	EXTENDED_Ebias,EXP(%ebx)
+	andw	$0x7fff,EXP(%ebx)
+
 L_exit:
 	popl	%ebx
 	leave
@@ -76,56 +75,57 @@
 
 
 L_zero:
-	movl	EXP_UNDER,EXP(%ebx)
-	movb	TW_Zero,TAG(%ebx)
+	movw	$0,EXP(%ebx)
+	movl	TAG_Zero,%eax
 	jmp	L_exit
 
 L_underflow:
+	/* Convert the exponent to 80x87 form. */
+	addw	EXTENDED_Ebias,EXP(%ebx)
 	push	%ebx
 	call	SYMBOL_NAME(arith_underflow)
 	pop	%ebx
 	jmp	L_exit
 
 L_overflow:
+	/* Convert the exponent to 80x87 form. */
+	addw	EXTENDED_Ebias,EXP(%ebx)
+	cmpb	SIGN_POS,PARAM2
+	jne	L_ovfl_neg
+	push	$0
+	jmp	L_ovfl_signed
+L_ovfl_neg:
+	push	$1
+L_ovfl_signed:
 	push	%ebx
 	call	SYMBOL_NAME(arith_overflow)
 	pop	%ebx
+	addl	$4,%esp
 	jmp	L_exit
 
 
 
 /* Normalise without reporting underflow or overflow */
-ENTRY(normalize_nuo)
+ENTRY(FPU_normalize_nuo)
 	pushl	%ebp
 	movl	%esp,%ebp
 	pushl	%ebx
 
 	movl	PARAM1,%ebx
 
-#ifdef PARANOID
-	cmpb	TW_Valid,TAG(%ebx)
-	je	L_ok_nuo
-
-	pushl	$0x221
-	call	SYMBOL_NAME(exception)
-	addl	$4,%esp
-
-L_ok_nuo:
-#endif PARANOID
-
 	movl	SIGH(%ebx),%edx
 	movl	SIGL(%ebx),%eax
 
 	orl	%edx,%edx	/* ms bits */
-	js	L_exit		/* Already normalized */
+	js	L_exit_nuo_valid	/* Already normalized */
 	jnz	L_nuo_shift_1	/* Shift left 1 - 31 bits */
 
 	orl	%eax,%eax
-	jz	L_zero		/* The contents are zero */
+	jz	L_exit_nuo_zero		/* The contents are zero */
 
 	movl	%eax,%edx
 	xorl	%eax,%eax
-	subl	$32,EXP(%ebx)	/* This can cause an underflow */
+	subw	$32,EXP(%ebx)	/* This can cause an underflow */
 
 /* We need to shift left by 1 - 31 bits */
 L_nuo_shift_1:
@@ -134,10 +134,22 @@
 	negl	%ecx
 	shld	%cl,%eax,%edx
 	shl	%cl,%eax
-	subl	%ecx,EXP(%ebx)	/* This can cause an underflow */
+	subw	%cx,EXP(%ebx)	/* This can cause an underflow */
 
 	movl	%edx,SIGH(%ebx)
 	movl	%eax,SIGL(%ebx)
-	jmp	L_exit
 
+L_exit_nuo_valid:
+	movl	TAG_Valid,%eax
 
+	popl	%ebx
+	leave
+	ret
+
+L_exit_nuo_zero:
+	movl	TAG_Zero,%eax
+	movw	EXP_UNDER,EXP(%ebx)
+
+	popl	%ebx
+	leave
+	ret
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_round.S linux-2.0.40/arch/i386/math-emu/reg_round.S
--- linux-2.0.39/arch/i386/math-emu/reg_round.S	Thu Oct  5 14:30:43 1995
+++ linux-2.0.40/arch/i386/math-emu/reg_round.S	Mon Oct  8 23:55:31 2001
@@ -4,17 +4,20 @@
  |                                                                           |
  | Rounding/truncation/etc for FPU basic arithmetic functions.               |
  |                                                                           |
- | Copyright (C) 1993,1995                                                   |
+ | Copyright (C) 1993,1995,1997                                              |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                       Australia.  E-mail billm@suburbia.net               |
  |                                                                           |
- | This code has four possible entry points.                                 |
+ | This code has three possible entry points.                                |
  | The following must be entered by a jmp instruction:                       |
- |   fpu_reg_round, fpu_reg_round_sqrt, and fpu_Arith_exit.                  |
+ |   fpu_reg_round, and fpu_Arith_exit.                                      |
  |                                                                           |
- | The _round_reg entry point is intended to be used by C code.              |
+ | The FPU_round entry point is intended to be used by C code.               |
  | From C, call as:                                                          |
- | void round_reg(FPU_REG *arg, unsigned int extent, unsigned int control_w) |
+ |  int FPU_round(FPU_REG *arg, unsigned int extent, unsigned int control_w) |
+ |                                                                           |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
  |                                                                           |
  | For correct "up" and "down" rounding, the argument must have the correct  |
  | sign.                                                                     |
@@ -22,18 +25,17 @@
  +---------------------------------------------------------------------------*/
 
 /*---------------------------------------------------------------------------+
- | Four entry points.                                                        |
+ | Three entry points.                                                       |
  |                                                                           |
- | Needed by both the fpu_reg_round and fpu_reg_round_sqrt entry points:     |
+ | Needed by the fpu_reg_round entry point:                                  |
  |  %eax:%ebx  64 bit significand                                            |
  |  %edx       32 bit extension of the significand                           |
  |  %edi       pointer to an FPU_REG for the result to be stored             |
  |  stack      calling function must have set up a C stack frame and         |
  |             pushed %esi, %edi, and %ebx                                   |
  |                                                                           |
- | Needed just for the fpu_reg_round_sqrt entry point:                       |
- |  %cx  A control word in the same format as the FPU control word.          |
- | Otherwise, PARAM4 must give such a value.                                 |
+ | A control word in the same format as the FPU control word must            |
+ | be in PARAM4.                                                             |
  |                                                                           |
  |                                                                           |
  | The significand and its extension are assumed to be exact in the          |
@@ -92,21 +94,20 @@
 /*	Not re-entrant, so we can gain speed by putting
 	local storage in a static area: */
 .data
-	.align 2,0
+	.align 4,0
 FPU_bits_lost:
 	.byte	0
 FPU_denormal:
 	.byte	0
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */
 
 
 .text
 .globl fpu_reg_round
-.globl fpu_reg_round_sqrt
 .globl fpu_Arith_exit
 
 /* Entry point when called from C */
-ENTRY(round_reg)
+ENTRY(FPU_round)
 	pushl	%ebp
 	movl	%esp,%ebp
 	pushl	%esi
@@ -117,30 +118,26 @@
 	movl	SIGH(%edi),%eax
 	movl	SIGL(%edi),%ebx
 	movl	PARAM2,%edx
-	movl	PARAM3,%ecx
-	jmp	fpu_reg_round_sqrt
 
 fpu_reg_round:			/* Normal entry point */
 	movl	PARAM4,%ecx
 
-fpu_reg_round_sqrt:		/* Entry point from wm_sqrt.S */
-
 #ifndef NON_REENTRANT_FPU
 	pushl	%ebx		/* adjust the stack pointer */
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */ 
 
 #ifdef PARANOID
 /* Cannot use this here yet */
 /*	orl	%eax,%eax */
 /*	jns	L_entry_bugged */
-#endif PARANOID
+#endif /* PARANOID */
 
-	cmpl	EXP_UNDER,EXP(%edi)
-	jle	xMake_denorm			/* The number is a de-normal */
+	cmpw	EXP_UNDER,EXP(%edi)
+	jle	L_Make_denorm			/* The number is a de-normal */
 
 	movb	$0,FPU_denormal			/* 0 -> not a de-normal */
 
-xDenorm_done:
+Denorm_done:
 	movb	$0,FPU_bits_lost		/* No bits yet lost in rounding */
 
 	movl	%ecx,%esi
@@ -161,12 +158,12 @@
 	je	LRound_To_64
 #ifdef PARANOID
 	jmp	L_bugged_denorm_486
-#endif PARANOID
+#endif /* PARANOID */ 
 #else
 #ifdef PARANOID
 	jmp	L_bugged_denorm	/* There is no bug, just a bad control word */
-#endif PARANOID
-#endif PECULIAR_486
+#endif /* PARANOID */ 
+#endif /* PECULIAR_486 */
 
 
 /* Round etc to 24 bit precision */
@@ -187,16 +184,16 @@
 
 #ifdef PARANOID
 	jmp	L_bugged_round24
-#endif PARANOID
+#endif /* PARANOID */ 
 
 LUp_24:
-	cmpb	SIGN_POS,SIGN(%edi)
+	cmpb	SIGN_POS,PARAM5
 	jne	LCheck_truncate_24	/* If negative then  up==truncate */
 
 	jmp	LCheck_24_round_up
 
 LDown_24:
-	cmpb	SIGN_POS,SIGN(%edi)
+	cmpb	SIGN_POS,PARAM5
 	je	LCheck_truncate_24	/* If positive then  down==truncate */
 
 LCheck_24_round_up:
@@ -205,7 +202,7 @@
 	orl	%ebx,%ecx
 	orl	%edx,%ecx
 	jnz	LDo_24_round_up
-	jmp	LRe_normalise
+	jmp	L_Re_normalise
 
 LRound_nearest_24:
 	/* Do rounding of the 24th bit if needed (nearest or even) */
@@ -240,13 +237,13 @@
 	andl	$0x000000ff,%ecx
 	orl	%ebx,%ecx
 	orl	%edx,%ecx
-	jz	LRe_normalise		/* No truncation needed */
+	jz	L_Re_normalise		/* No truncation needed */
 
 LDo_truncate_24:
 	andl	$0xffffff00,%eax	/* Truncate to 24 bits */
 	xorl	%ebx,%ebx
 	movb	LOST_DOWN,FPU_bits_lost
-	jmp	LRe_normalise
+	jmp	L_Re_normalise
 
 
 /* Round etc to 53 bit precision */
@@ -267,16 +264,16 @@
 
 #ifdef PARANOID
 	jmp	L_bugged_round53
-#endif PARANOID
+#endif /* PARANOID */ 
 
 LUp_53:
-	cmpb	SIGN_POS,SIGN(%edi)
+	cmpb	SIGN_POS,PARAM5
 	jne	LCheck_truncate_53	/* If negative then  up==truncate */
 
 	jmp	LCheck_53_round_up
 
 LDown_53:
-	cmpb	SIGN_POS,SIGN(%edi)
+	cmpb	SIGN_POS,PARAM5
 	je	LCheck_truncate_53	/* If positive then  down==truncate */
 
 LCheck_53_round_up:
@@ -284,7 +281,7 @@
 	andl	$0x000007ff,%ecx
 	orl	%edx,%ecx
 	jnz	LDo_53_round_up
-	jmp	LRe_normalise
+	jmp	L_Re_normalise
 
 LRound_nearest_53:
 	/* Do rounding of the 53rd bit if needed (nearest or even) */
@@ -315,12 +312,12 @@
 	movl	%ebx,%ecx
 	andl	$0x000007ff,%ecx
 	orl	%edx,%ecx
-	jz	LRe_normalise
+	jz	L_Re_normalise
 
 LTruncate_53:
 	movb	LOST_DOWN,FPU_bits_lost
 	andl	$0xfffff800,%ebx	/* Truncate to 53 bits */
-	jmp	LRe_normalise
+	jmp	L_Re_normalise
 
 
 /* Round etc to 64 bit precision */
@@ -341,23 +338,23 @@
 
 #ifdef PARANOID
 	jmp	L_bugged_round64
-#endif PARANOID
+#endif /* PARANOID */ 
 
 LUp_64:
-	cmpb	SIGN_POS,SIGN(%edi)
+	cmpb	SIGN_POS,PARAM5
 	jne	LCheck_truncate_64	/* If negative then  up==truncate */
 
 	orl	%edx,%edx
 	jnz	LDo_64_round_up
-	jmp	LRe_normalise
+	jmp	L_Re_normalise
 
 LDown_64:
-	cmpb	SIGN_POS,SIGN(%edi)
+	cmpb	SIGN_POS,PARAM5
 	je	LCheck_truncate_64	/* If positive then  down==truncate */
 
 	orl	%edx,%edx
 	jnz	LDo_64_round_up
-	jmp	LRe_normalise
+	jmp	L_Re_normalise
 
 LRound_nearest_64:
 	cmpl	$0x80000000,%edx
@@ -366,7 +363,7 @@
 	jne	LDo_64_round_up
 
 	/* Now test for round-to-even */
-	testb	$1,%ebx
+	testb	$1,%bl
 	jz	LCheck_truncate_64
 
 LDo_64_round_up:
@@ -375,49 +372,63 @@
 	adcl	$0,%eax
 
 LCheck_Round_Overflow:
-	jnc	LRe_normalise
+	jnc	L_Re_normalise
 
 	/* Overflow, adjust the result (significand to 1.0) */
 	rcrl	$1,%eax
 	rcrl	$1,%ebx
-	incl	EXP(%edi)
-	jmp	LRe_normalise
+	incw	EXP(%edi)
+	jmp	L_Re_normalise
 
 LCheck_truncate_64:
 	orl	%edx,%edx
-	jz	LRe_normalise
+	jz	L_Re_normalise
 
 LTruncate_64:
 	movb	LOST_DOWN,FPU_bits_lost
 
-LRe_normalise:
+L_Re_normalise:
 	testb	$0xff,FPU_denormal
-	jnz	xNormalise_result
+	jnz	Normalise_result
 
-xL_Normalised:
+L_Normalised:
+	movl	TAG_Valid,%edx
+
+L_deNormalised:
 	cmpb	LOST_UP,FPU_bits_lost
-	je	xL_precision_lost_up
+	je	L_precision_lost_up
 
 	cmpb	LOST_DOWN,FPU_bits_lost
-	je	xL_precision_lost_down
+	je	L_precision_lost_down
 
-xL_no_precision_loss:
+L_no_precision_loss:
 	/* store the result */
-	movb	TW_Valid,TAG(%edi)
 
-xL_Store_significand:
+L_Store_significand:
 	movl	%eax,SIGH(%edi)
 	movl	%ebx,SIGL(%edi)
 
-	xorl	%eax,%eax	/* No errors detected. */
-
-	cmpl	EXP_OVER,EXP(%edi)
+	cmpw	EXP_OVER,EXP(%edi)
 	jge	L_overflow
 
-fpu_reg_round_exit:
+	movl	%edx,%eax
+
+	/* Convert the exponent to 80x87 form. */
+	addw	EXTENDED_Ebias,EXP(%edi)
+	andw	$0x7fff,EXP(%edi)
+
+fpu_reg_round_signed_special_exit:
+
+	cmpb	SIGN_POS,PARAM5
+	je	fpu_reg_round_special_exit
+
+	orw	$0x8000,EXP(%edi)	/* Negative sign for the result. */
+
+fpu_reg_round_special_exit:
+
 #ifndef NON_REENTRANT_FPU
 	popl	%ebx		/* adjust the stack pointer */
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */ 
 
 fpu_Arith_exit:
 	popl	%ebx
@@ -431,21 +442,25 @@
  * Set the FPU status flags to represent precision loss due to
  * round-up.
  */
-xL_precision_lost_up:
+L_precision_lost_up:
+	push	%edx
 	push	%eax
 	call	SYMBOL_NAME(set_precision_flag_up)
 	popl	%eax
-	jmp	xL_no_precision_loss
+	popl	%edx
+	jmp	L_no_precision_loss
 
 /*
  * Set the FPU status flags to represent precision loss due to
  * truncation.
  */
-xL_precision_lost_down:
+L_precision_lost_down:
+	push	%edx
 	push	%eax
 	call	SYMBOL_NAME(set_precision_flag_down)
 	popl	%eax
-	jmp	xL_no_precision_loss
+	popl	%edx
+	jmp	L_no_precision_loss
 
 
 /*
@@ -453,30 +468,30 @@
  * Shift the number right the required number of bits, which will
  * have to be undone later...
  */
-xMake_denorm:
+L_Make_denorm:
 	/* The action to be taken depends upon whether the underflow
 	   exception is masked */
 	testb	CW_Underflow,%cl		/* Underflow mask. */
-	jz	xUnmasked_underflow		/* Do not make a denormal. */
+	jz	Unmasked_underflow		/* Do not make a denormal. */
 
 	movb	DENORMAL,FPU_denormal
 
 	pushl	%ecx		/* Save */
-	movl	EXP_UNDER+1,%ecx
-	subl	EXP(%edi),%ecx
+	movw	EXP_UNDER+1,%cx
+	subw	EXP(%edi),%cx
 
-	cmpl	$64,%ecx	/* shrd only works for 0..31 bits */
-	jnc	xDenorm_shift_more_than_63
+	cmpw	$64,%cx	/* shrd only works for 0..31 bits */
+	jnc	Denorm_shift_more_than_63
 
-	cmpl	$32,%ecx	/* shrd only works for 0..31 bits */
-	jnc	xDenorm_shift_more_than_32
+	cmpw	$32,%cx	/* shrd only works for 0..31 bits */
+	jnc	Denorm_shift_more_than_32
 
 /*
  * We got here without jumps by assuming that the most common requirement
  *   is for a small de-normalising shift.
  * Shift by [1..31] bits
  */
-	addl	%ecx,EXP(%edi)
+	addw	%cx,EXP(%edi)
 	orl	%edx,%edx	/* extension */
 	setne	%ch		/* Save whether %edx is non-zero */
 	xorl	%edx,%edx
@@ -485,11 +500,11 @@
 	shr	%cl,%eax
 	orb	%ch,%dl
 	popl	%ecx
-	jmp	xDenorm_done
+	jmp	Denorm_done
 
 /* Shift by [32..63] bits */
-xDenorm_shift_more_than_32:
-	addl	%ecx,EXP(%edi)
+Denorm_shift_more_than_32:
+	addw	%cx,EXP(%edi)
 	subb	$32,%cl
 	orl	%edx,%edx
 	setne	%ch
@@ -506,15 +521,15 @@
 	movl	%eax,%ebx
 	xorl	%eax,%eax
 	popl	%ecx
-	jmp	xDenorm_done
+	jmp	Denorm_done
 
 /* Shift by [64..) bits */
-xDenorm_shift_more_than_63:
-	cmpl	$64,%ecx
-	jne	xDenorm_shift_more_than_64
+Denorm_shift_more_than_63:
+	cmpw	$64,%cx
+	jne	Denorm_shift_more_than_64
 
 /* Exactly 64 bit shift */
-	addl	%ecx,EXP(%edi)
+	addw	%cx,EXP(%edi)
 	xorl	%ecx,%ecx
 	orl	%edx,%edx
 	setne	%cl
@@ -526,34 +541,34 @@
 	xorl	%eax,%eax
 	xorl	%ebx,%ebx
 	popl	%ecx
-	jmp	xDenorm_done
+	jmp	Denorm_done
 
-xDenorm_shift_more_than_64:
-	movl	EXP_UNDER+1,EXP(%edi)
+Denorm_shift_more_than_64:
+	movw	EXP_UNDER+1,EXP(%edi)
 /* This is easy, %eax must be non-zero, so.. */
 	movl	$1,%edx
 	xorl	%eax,%eax
 	xorl	%ebx,%ebx
 	popl	%ecx
-	jmp	xDenorm_done
+	jmp	Denorm_done
 
 
-xUnmasked_underflow:
+Unmasked_underflow:
 	movb	UNMASKED_UNDERFLOW,FPU_denormal
-	jmp	xDenorm_done
+	jmp	Denorm_done
 
 
 /* Undo the de-normalisation. */
-xNormalise_result:
+Normalise_result:
 	cmpb	UNMASKED_UNDERFLOW,FPU_denormal
-	je	xSignal_underflow
+	je	Signal_underflow
 
 /* The number must be a denormal if we got here. */
 #ifdef PARANOID
 	/* But check it... just in case. */
-	cmpl	EXP_UNDER+1,EXP(%edi)
+	cmpw	EXP_UNDER+1,EXP(%edi)
 	jne	L_norm_bugged
-#endif PARANOID
+#endif /* PARANOID */
 
 #ifdef PECULIAR_486
 	/*
@@ -565,41 +580,33 @@
 	 * Actual 80486 behaviour differs from this in some circumstances.
 	 */
 	orl	%eax,%eax		/* ms bits */
-	js	LNormalise_shift_done	/* Will be masked underflow */
-#endif PECULIAR_486
-
+	js	LPseudoDenormal		/* Will be masked underflow */
+#else
 	orl	%eax,%eax		/* ms bits */
-	js	xL_Normalised		/* No longer a denormal */
+	js	L_Normalised		/* No longer a denormal */
+#endif /* PECULIAR_486 */ 
 
-	jnz	LNormalise_shift_up_to_31	/* Shift left 0 - 31 bits */
+	jnz	LDenormal_adj_exponent
 
 	orl	%ebx,%ebx
 	jz	L_underflow_to_zero	/* The contents are zero */
 
-/* Shift left 32 - 63 bits */
-	movl	%ebx,%eax
-	xorl	%ebx,%ebx
-	subl	$32,EXP(%edi)
-
-LNormalise_shift_up_to_31:
-	bsrl	%eax,%ecx	/* get the required shift in %ecx */
-	subl	$31,%ecx
-	negl	%ecx
-	shld	%cl,%ebx,%eax
-	shl	%cl,%ebx
-	subl	%ecx,EXP(%edi)
+LDenormal_adj_exponent:
+	decw	EXP(%edi)
 
-LNormalise_shift_done:
+LPseudoDenormal:
 	testb	$0xff,FPU_bits_lost	/* bits lost == underflow */
-	jz	xL_Normalised
+	movl	TAG_Special,%edx
+	jz	L_deNormalised
 
 	/* There must be a masked underflow */
 	push	%eax
 	pushl	EX_Underflow
-	call	SYMBOL_NAME(exception)
+	call	EXCEPTION
 	popl	%eax
 	popl	%eax
-	jmp	xL_Normalised
+	movl	TAG_Special,%edx
+	jmp	L_deNormalised
 
 
 /*
@@ -613,41 +620,50 @@
 
 	push	%eax
 	pushl	EX_Underflow
-	call	SYMBOL_NAME(exception)
+	call	EXCEPTION
 	popl	%eax
 	popl	%eax
 
 /* Reduce the exponent to EXP_UNDER */
-	movl	EXP_UNDER,EXP(%edi)
-	movb	TW_Zero,TAG(%edi)
-	jmp	xL_Store_significand
+	movw	EXP_UNDER,EXP(%edi)
+	movl	TAG_Zero,%edx
+	jmp	L_Store_significand
 
 
 /* The operations resulted in a number too large to represent. */
 L_overflow:
+	addw	EXTENDED_Ebias,EXP(%edi)	/* Set for unmasked response. */
+	cmpb	SIGN_POS,PARAM5
+	jne	L_ovfl_neg
+	push	$0
+	jmp	L_ovfl_signed
+L_ovfl_neg:
+	push	$1
+L_ovfl_signed:
 	push	%edi
 	call	SYMBOL_NAME(arith_overflow)
 	pop	%edi
-	jmp	fpu_reg_round_exit
+	addl	$4,%esp
+	jmp	fpu_reg_round_signed_special_exit
 
 
-xSignal_underflow:
+Signal_underflow:
 	/* The number may have been changed to a non-denormal */
 	/* by the rounding operations. */
-	cmpl	EXP_UNDER,EXP(%edi)
-	jle	xDo_unmasked_underflow
+	cmpw	EXP_UNDER,EXP(%edi)
+	jle	Do_unmasked_underflow
 
-	jmp	xL_Normalised
+	jmp	L_Normalised
 
-xDo_unmasked_underflow:
+Do_unmasked_underflow:
 	/* Increase the exponent by the magic number */
-	addl	$(3*(1<<13)),EXP(%edi)
+	addw	$(3*(1<<13)),EXP(%edi)
 	push	%eax
 	pushl	EX_Underflow
 	call	EXCEPTION
 	popl	%eax
 	popl	%eax
-	jmp	xL_Normalised
+	jmp	L_Normalised
 
 
 #ifdef PARANOID
@@ -663,7 +679,7 @@
 	call	EXCEPTION
 	popl	%ebx
 	jmp	L_exception_exit
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */ 
 
 L_bugged_round24:
 	pushl	EX_INTERNAL|0x231
@@ -694,6 +710,6 @@
 	call	EXCEPTION
 	popl	%ebx
 L_exception_exit:
-	mov	$1,%eax
-	jmp	fpu_reg_round_exit
-#endif PARANOID
+	mov	$-1,%eax
+	jmp	fpu_reg_round_special_exit
+#endif /* PARANOID */ 
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_u_add.S linux-2.0.40/arch/i386/math-emu/reg_u_add.S
--- linux-2.0.39/arch/i386/math-emu/reg_u_add.S	Thu Oct  5 14:30:43 1995
+++ linux-2.0.40/arch/i386/math-emu/reg_u_add.S	Mon Oct  8 23:54:43 2001
@@ -2,24 +2,26 @@
 /*---------------------------------------------------------------------------+
  |  reg_u_add.S                                                              |
  |                                                                           |
- | Add two valid (TW_Valid) FPU_REG numbers, of the same sign, and put the   |
+ | Add two valid (TAG_Valid) FPU_REG numbers, of the same sign, and put the  |
  |   result in a destination FPU_REG.                                        |
  |                                                                           |
- | Copyright (C) 1992,1993,1995                                              |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ | Copyright (C) 1992,1993,1995,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
  |                                                                           |
  | Call from C as:                                                           |
- |   void reg_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,             |
+ |   int  FPU_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,             |
  |                                                int control_w)             |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
 /*
- |    Kernel addition routine reg_u_add(reg *arg1, reg *arg2, reg *answ).
- |    Takes two valid reg f.p. numbers (TW_Valid), which are
+ |    Kernel addition routine FPU_u_add(reg *arg1, reg *arg2, reg *answ).
+ |    Takes two valid reg f.p. numbers (TAG_Valid), which are
  |    treated as unsigned numbers,
- |    and returns their sum as a TW_Valid or TW_S f.p. number.
+ |    and returns their sum as a TAG_Valid or TAG_Special f.p. number.
  |    The returned number is normalized.
  |    Basic checks are performed if PARANOID is defined.
  */
@@ -29,7 +31,7 @@
 #include "control_w.h"
 
 .text
-ENTRY(reg_u_add)
+ENTRY(FPU_u_add)
 	pushl	%ebp
 	movl	%esp,%ebp
 	pushl	%esi
@@ -39,27 +41,9 @@
 	movl	PARAM1,%esi		/* source 1 */
 	movl	PARAM2,%edi		/* source 2 */
 
-#ifdef DENORM_OPERAND
-	cmpl	EXP_UNDER,EXP(%esi)
-	jg	xOp1_not_denorm
-
-	call	SYMBOL_NAME(denormal_operand)
-	orl	%eax,%eax
-	jnz	fpu_Arith_exit
-
-xOp1_not_denorm:
-	cmpl	EXP_UNDER,EXP(%edi)
-	jg	xOp2_not_denorm
-
-	call	SYMBOL_NAME(denormal_operand)
-	orl	%eax,%eax
-	jnz	fpu_Arith_exit
-
-xOp2_not_denorm:
-#endif DENORM_OPERAND
-
-	movl	EXP(%esi),%ecx
-	subl	EXP(%edi),%ecx		/* exp1 - exp2 */
+	movl	PARAM6,%ecx
+	movl	%ecx,%edx
+	subl	PARAM7,%ecx			/* exp1 - exp2 */
 	jge	L_arg1_larger
 
 	/* num1 is smaller */
@@ -67,6 +51,7 @@
 	movl	SIGH(%esi),%eax
 
 	movl	%edi,%esi
+	movl	PARAM7,%edx
 	negw	%cx
 	jmp	L_accum_loaded
 
@@ -77,12 +62,7 @@
 
 L_accum_loaded:
 	movl	PARAM3,%edi		/* destination */
-/*	movb	SIGN(%esi),%dl
-	movb	%dl,SIGN(%edi) */	/* Copy the sign from the first arg */
-
-
-	movl	EXP(%esi),%edx
-	movl	%edx,EXP(%edi)		/* Copy exponent to destination */
+	movw	%dx,EXP(%edi)		/* Copy exponent to destination */
 
 	xorl	%edx,%edx		/* clear the extension */
 
@@ -92,7 +72,7 @@
 
 	testl	$0x80000000,SIGH(%esi)
 	je	L_bugged
-#endif PARANOID
+#endif /* PARANOID */
 
 /* The number to be shifted is in %eax:%ebx:%edx */
 	cmpw	$32,%cx		/* shrd only works for 0..31 bits */
@@ -162,7 +142,7 @@
 	orl	$1,%edx
 
 L_no_bit_lost:
-	incl	EXP(%edi)
+	incw	EXP(%edi)
 
 L_round_the_result:
 	jmp	fpu_reg_round	/* Round the result */
@@ -175,9 +155,8 @@
 	pushl	EX_INTERNAL|0x201
 	call	EXCEPTION
 	pop	%ebx
+	movl	$-1,%eax
 	jmp	L_exit
-#endif PARANOID
-
 
 L_exit:
 	popl	%ebx
@@ -185,3 +164,4 @@
 	popl	%esi
 	leave
 	ret
+#endif /* PARANOID */
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_u_div.S linux-2.0.40/arch/i386/math-emu/reg_u_div.S
--- linux-2.0.39/arch/i386/math-emu/reg_u_div.S	Thu Oct  5 14:30:43 1995
+++ linux-2.0.40/arch/i386/math-emu/reg_u_div.S	Mon Oct  8 23:54:43 2001
@@ -2,22 +2,24 @@
 /*---------------------------------------------------------------------------+
  |  reg_u_div.S                                                              |
  |                                                                           |
- | Core division routines                                                    |
+ | Divide one FPU_REG by another and put the result in a destination FPU_REG.|
  |                                                                           |
- | Copyright (C) 1992,1993,1995                                              |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ | Copyright (C) 1992,1993,1995,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
 /*---------------------------------------------------------------------------+
- |  Kernel for the division routines.                                        |
- |                                                                           |
- |  void reg_u_div(FPU_REG *a, FPU_REG *a,                                   |
- |                 FPU_REG *dest, unsigned int control_word)                 |
+ | Call from C as:                                                           |
+ |    int FPU_u_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest,                   |
+ |                unsigned int control_word, char *sign)                     |
  |                                                                           |
  |  Does not compute the destination exponent, but does adjust it.           |
+ |                                                                           |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
  +---------------------------------------------------------------------------*/
 
 #include "exception.h"
@@ -50,7 +52,7 @@
 	Result:		FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0
 	Overflow flag:	ovfl_flag
  */
-	.align 2,0
+	.align 4,0
 FPU_accum_3:
 	.long	0
 FPU_accum_2:
@@ -65,53 +67,50 @@
 	.long	0
 FPU_ovfl_flag:
 	.byte	0
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */
 
+#define REGA	PARAM1
+#define REGB	PARAM2
+#define DEST	PARAM3
 
 .text
-ENTRY(reg_u_div)
+ENTRY(FPU_u_div)
 	pushl	%ebp
 	movl	%esp,%ebp
 #ifndef NON_REENTRANT_FPU
 	subl	$28,%esp
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */
 
 	pushl	%esi
 	pushl	%edi
 	pushl	%ebx
 
-	movl	PARAM1,%esi	/* pointer to num */
-	movl	PARAM2,%ebx	/* pointer to denom */
-	movl	PARAM3,%edi	/* pointer to answer */
-
-#ifdef DENORM_OPERAND
-	movl	EXP(%esi),%eax
-	cmpl	EXP_UNDER,%eax
-	jg	xOp1_not_denorm
-
-	call	SYMBOL_NAME(denormal_operand)
-	orl	%eax,%eax
-	jnz	fpu_Arith_exit
-
-xOp1_not_denorm:
-	movl	EXP(%ebx),%eax
-	cmpl	EXP_UNDER,%eax
-	jg	xOp2_not_denorm
-
-	call	SYMBOL_NAME(denormal_operand)
-	orl	%eax,%eax
-	jnz	fpu_Arith_exit
+	movl	REGA,%esi
+	movl	REGB,%ebx
+	movl	DEST,%edi
+
+	movswl	EXP(%esi),%edx
+	movswl	EXP(%ebx),%eax
+	subl	%eax,%edx
+	addl	EXP_BIAS,%edx
+
+	/* A denormal and a large number can cause an exponent underflow */
+	cmpl	EXP_WAY_UNDER,%edx
+	jg	xExp_not_underflow
+
+	/* Set to a really low value allow correct handling */
+	movl	EXP_WAY_UNDER,%edx
+
+xExp_not_underflow:
 
-xOp2_not_denorm:
-#endif DENORM_OPERAND
+	movw    %dx,EXP(%edi)
 
-ENTRY(divide_kernel)
 #ifdef PARANOID
 /*	testl	$0x80000000, SIGH(%esi)	// Dividend */
 /*	je	L_bugged */
 	testl	$0x80000000, SIGH(%ebx)	/* Divisor */
 	je	L_bugged
-#endif PARANOID
+#endif /* PARANOID */ 
 
 /* Check if the divisor can be treated as having just 32 bits */
 	cmpl	$0,SIGL(%ebx)
@@ -147,7 +146,7 @@
 
 	/* Do the shifting here */
 	/* increase the exponent */
-	incl	EXP(%edi)
+	incw	EXP(%edi)
 
 	/* shift the mantissa right one bit */
 	stc			/* To set the ms bit */
@@ -247,7 +246,7 @@
 
 #ifdef PARANOID
 	jb	L_bugged_1
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	/* need to subtract another once of the denom */
 	incl	FPU_result_2	/* Correct the answer */
@@ -260,7 +259,7 @@
 #ifdef PARANOID
 	sbbl	$0,FPU_accum_3
 	jne	L_bugged_1	/* Must check for non-zero result here */
-#endif PARANOID
+#endif /* PARANOID */ 
 
 /*----------------------------------------------------------------------*/
 /* Half of the main problem is done, there is just a reduced numerator
@@ -290,7 +289,7 @@
 
 #ifdef PARANOID
 	je	L_bugged_2	/* Can't bump the result to 1.0 */
-#endif PARANOID
+#endif /* PARANOID */ 
 
 LDo_2nd_div:
 	cmpl	$0,%ecx		/* augmented denom msw */
@@ -313,7 +312,7 @@
 
 #ifdef PARANOID
 	jc	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	movl	FPU_result_1,%eax	/* Get the result back */
 	mull	SIGL(%ebx)	/* now mul the ls dw of the denom */
@@ -324,14 +323,14 @@
 
 #ifdef PARANOID
 	jc	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	jz	LDo_3rd_32_bits
 
 #ifdef PARANOID
 	cmpl	$1,FPU_accum_2
 	jne	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */
 
 	/* need to subtract another once of the denom */
 	movl	SIGL(%ebx),%eax
@@ -343,14 +342,14 @@
 #ifdef PARANOID
 	jc	L_bugged_2
 	jne	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	addl	$1,FPU_result_1	/* Correct the answer */
 	adcl	$0,FPU_result_2
 
 #ifdef PARANOID
 	jc	L_bugged_2	/* Must check for non-zero result here */
-#endif PARANOID
+#endif /* PARANOID */
 
 /*----------------------------------------------------------------------*/
 /* The division is essentially finished here, we just need to perform
@@ -423,7 +422,7 @@
 	testb	$255,FPU_ovfl_flag	/* was the num > denom ? */
 	je	LRound_precision
 
-	incl	EXP(%edi)
+	incw	EXP(%edi)
 
 	/* shift the mantissa right one bit */
 	stc			/* Will set the ms bit */
@@ -433,7 +432,7 @@
 
 /* Round the result as required */
 LRound_precision:
-	decl	EXP(%edi)	/* binary point between 1st & 2nd bits */
+	decw	EXP(%edi)	/* binary point between 1st & 2nd bits */
 
 	movl	%eax,%edx
 	movl	FPU_result_1,%ebx
@@ -462,10 +461,11 @@
 	jmp	L_exit
 
 L_exit:
+	movl	$-1,%eax
 	popl	%ebx
 	popl	%edi
 	popl	%esi
 
 	leave
 	ret
-#endif PARANOID
+#endif /* PARANOID */ 
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_u_mul.S linux-2.0.40/arch/i386/math-emu/reg_u_mul.S
--- linux-2.0.39/arch/i386/math-emu/reg_u_mul.S	Thu Oct  5 14:30:43 1995
+++ linux-2.0.40/arch/i386/math-emu/reg_u_mul.S	Mon Oct  8 23:54:43 2001
@@ -4,9 +4,9 @@
  |                                                                           |
  | Core multiplication routine                                               |
  |                                                                           |
- | Copyright (C) 1992,1993,1995                                              |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ | Copyright (C) 1992,1993,1995,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
@@ -15,7 +15,7 @@
  |   Basic multiplication routine.                                           |
  |   Does not check the resulting exponent for overflow/underflow            |
  |                                                                           |
- |   reg_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw);         |
+ |   FPU_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw);         |
  |                                                                           |
  |   Internal working is at approx 128 bits.                                 |
  |   Result is rounded to nearest 53 or 64 bits, using "nearest or even".    |
@@ -40,16 +40,16 @@
 	.long	0
 FPU_accum_1:
 	.long	0
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */
 
 
 .text
-ENTRY(reg_u_mul)
+ENTRY(FPU_u_mul)
 	pushl	%ebp
 	movl	%esp,%ebp
 #ifndef NON_REENTRANT_FPU
 	subl	$8,%esp
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */ 
 
 	pushl	%esi
 	pushl	%edi
@@ -63,28 +63,7 @@
 	jz	L_bugged
 	testl	$0x80000000,SIGH(%edi)
 	jz	L_bugged
-#endif PARANOID
-
-#ifdef DENORM_OPERAND
-	movl	EXP(%esi),%eax
-	cmpl	EXP_UNDER,%eax
-	jg	xOp1_not_denorm
-
-	call	SYMBOL_NAME(denormal_operand)
-	orl	%eax,%eax
-	jnz	fpu_Arith_exit
-
-xOp1_not_denorm:
-	movl	EXP(%edi),%eax
-	cmpl	EXP_UNDER,%eax
-	jg	xOp2_not_denorm
-
-	call	SYMBOL_NAME(denormal_operand)
-	orl	%eax,%eax
-	jnz	fpu_Arith_exit
-
-xOp2_not_denorm:
-#endif DENORM_OPERAND
+#endif /* PARANOID */
 
 	xorl	%ecx,%ecx
 	xorl	%ebx,%ebx
@@ -111,13 +90,22 @@
 	addl	%eax,%ebx
 	adcl	%edx,%ecx
 
-	movl	EXP(%esi),%eax	/* Compute the exponent */
-	addl	EXP(%edi),%eax
+	/* Get the sum of the exponents. */
+	movl	PARAM6,%eax
 	subl	EXP_BIAS-1,%eax
 
+	/* Two denormals can cause an exponent underflow */
+	cmpl	EXP_WAY_UNDER,%eax
+	jg	Exp_not_underflow
+
+	/* Set to a really low value allow correct handling */
+	movl	EXP_WAY_UNDER,%eax
+
+Exp_not_underflow:
+
 /*  Have now finished with the sources */
 	movl	PARAM3,%edi	/* Point to the destination */
-	movl	%eax,EXP(%edi)
+	movw	%ax,EXP(%edi)
 
 /*  Now make sure that the result is normalized */
 	testl	$0x80000000,%ecx
@@ -128,7 +116,7 @@
 	rcll	$1,FPU_accum_1
 	rcll	$1,%ebx
 	rcll	$1,%ecx
-	decl	EXP(%edi)
+	decw	EXP(%edi)
 
 LResult_Normalised:
 	movl	FPU_accum_0,%eax
@@ -156,5 +144,5 @@
 	popl	%esi
 	leave
 	ret
-#endif PARANOID
+#endif /* PARANOID */ 
 
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/reg_u_sub.S linux-2.0.40/arch/i386/math-emu/reg_u_sub.S
--- linux-2.0.39/arch/i386/math-emu/reg_u_sub.S	Sun Nov 15 19:32:47 1998
+++ linux-2.0.40/arch/i386/math-emu/reg_u_sub.S	Mon Oct  8 23:54:43 2001
@@ -4,21 +4,23 @@
  |                                                                           |
  | Core floating point subtraction routine.                                  |
  |                                                                           |
- | Copyright (C) 1992,1993,1995                                              |
- |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ | Copyright (C) 1992,1993,1995,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
  |                                                                           |
  | Call from C as:                                                           |
- |   void reg_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,             |
+ |    int FPU_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,             |
  |                                                int control_w)             |
+ |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
+ |    one was raised, or -1 on internal error.                               |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
 /*
- |    Kernel subtraction routine reg_u_sub(reg *arg1, reg *arg2, reg *answ).
- |    Takes two valid reg f.p. numbers (TW_Valid), which are
+ |    Kernel subtraction routine FPU_u_sub(reg *arg1, reg *arg2, reg *answ).
+ |    Takes two valid reg f.p. numbers (TAG_Valid), which are
  |    treated as unsigned numbers,
- |    and returns their difference as a TW_Valid or TW_Zero f.p.
+ |    and returns their difference as a TAG_Valid or TAG_Zero f.p.
  |    number.
  |    The first number (arg1) must be the larger.
  |    The returned number is normalized.
@@ -30,7 +32,7 @@
 #include "control_w.h"
 
 .text
-ENTRY(reg_u_sub)
+ENTRY(FPU_u_sub)
 	pushl	%ebp
 	movl	%esp,%ebp
 	pushl	%esi
@@ -39,39 +41,20 @@
 
 	movl	PARAM1,%esi	/* source 1 */
 	movl	PARAM2,%edi	/* source 2 */
-
-#ifdef DENORM_OPERAND
-	cmpl	EXP_UNDER,EXP(%esi)
-	jg	xOp1_not_denorm
-
-	call	SYMBOL_NAME(denormal_operand)
-	orl	%eax,%eax
-	jnz	fpu_Arith_exit
-
-xOp1_not_denorm:
-	cmpl	EXP_UNDER,EXP(%edi)
-	jg	xOp2_not_denorm
-
-	call	SYMBOL_NAME(denormal_operand)
-	orl	%eax,%eax
-	jnz	fpu_Arith_exit
-
-xOp2_not_denorm:
-#endif DENORM_OPERAND
-
-	movl	EXP(%esi),%ecx
-	subl	EXP(%edi),%ecx	/* exp1 - exp2 */
+	
+	movl	PARAM6,%ecx
+	subl	PARAM7,%ecx	/* exp1 - exp2 */
 
 #ifdef PARANOID
 	/* source 2 is always smaller than source 1 */
 	js	L_bugged_1
 
-	testl	$0x80000000,SIGH(%edi)	/* The args are assumed to be normalized */
+	testl	$0x80000000,SIGH(%edi)	/* The args are assumed to be be normalized */
 	je	L_bugged_2
 
 	testl	$0x80000000,SIGH(%esi)
 	je	L_bugged_2
-#endif PARANOID
+#endif /* PARANOID */
 
 /*--------------------------------------+
  |	Form a register holding the     |
@@ -81,10 +64,8 @@
 	movl	SIGL(%edi),%ebx	/* register ls word */
 
 	movl	PARAM3,%edi	/* destination */
-	movl	EXP(%esi),%edx
-	movl	%edx,EXP(%edi)	/* Copy exponent to destination */
-/*	movb	SIGN(%esi),%dl
-	movb	%dl,SIGN(%edi) */	/* Copy the sign from the first arg */
+	movl	PARAM6,%edx
+	movw	%dx,EXP(%edi)	/* Copy exponent to destination */
 
 	xorl	%edx,%edx	/* register extension */
 
@@ -93,8 +74,8 @@
  |      right the required number of	|
  |	places.				|
  +--------------------------------------*/
-L_shift_r:
-	cmpl	$32,%ecx		/* shrd only works for 0..31 bits */
+
+	cmpw	$32,%cx		/* shrd only works for 0..31 bits */
 	jnc	L_more_than_31
 
 /* less than 32 bits */
@@ -104,7 +85,7 @@
 	jmp	L_shift_done
 
 L_more_than_31:
-	cmpl	$64,%ecx
+	cmpw	$64,%cx
 	jnc	L_more_than_63
 
 	subb	$32,%cl
@@ -184,7 +165,7 @@
 #ifdef PARANOID
 	/* We can never get a borrow */
 	jc	L_bugged
-#endif PARANOID
+#endif /* PARANOID */
 
 /*--------------------------------------+
  |	Normalize the result		|
@@ -210,7 +191,7 @@
 	jnz	L_must_be_zero
 
 	/* Shift left 64 bits */
-	subl	$64,EXP(%edi)
+	subw	$64,EXP(%edi)
 	xchg	%edx,%eax
 	jmp	fpu_reg_round
 
@@ -218,20 +199,20 @@
 #ifdef PARANOID
 	orl	%edx,%edx
 	jnz	L_bugged_3
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	/* The result is zero */
-	movb	TW_Zero,TAG(%edi)
-	movl	$0,EXP(%edi)		/* exponent */
+	movw	$0,EXP(%edi)		/* exponent */
 	movl	$0,SIGL(%edi)
 	movl	$0,SIGH(%edi)
-	jmp	L_exit		/* %eax contains zero */
+	movl	TAG_Zero,%eax
+	jmp	L_exit
 
 L_shift_32:
 	movl	%ebx,%eax
 	movl	%edx,%ebx
 	movl	$0,%edx
-	subl	$32,EXP(%edi)	/* Can get underflow here */
+	subw	$32,EXP(%edi)	/* Can get underflow here */
 
 /* We need to shift left by 1 - 31 bits */
 L_shift_1:
@@ -241,7 +222,7 @@
 	shld	%cl,%ebx,%eax
 	shld	%cl,%edx,%ebx
 	shl	%cl,%edx
-	subl	%ecx,EXP(%edi)	/* Can get underflow here */
+	subw	%cx,EXP(%edi)	/* Can get underflow here */
 
 L_round:
 	jmp	fpu_reg_round	/* Round the result */
@@ -277,11 +258,12 @@
 	call	EXCEPTION
 	pop	%ebx
 	jmp	L_error_exit
-#endif PARANOID
-
 
 L_error_exit:
-	movl	$1,%eax
+	movl	$-1,%eax
+
+#endif /* PARANOID */
+
 L_exit:
 	popl	%ebx
 	popl	%edi
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/status_w.h linux-2.0.40/arch/i386/math-emu/status_w.h
--- linux-2.0.39/arch/i386/math-emu/status_w.h	Sat Mar 29 01:12:25 1997
+++ linux-2.0.40/arch/i386/math-emu/status_w.h	Mon Oct  8 23:54:43 2001
@@ -1,9 +1,9 @@
 /*---------------------------------------------------------------------------+
  |  status_w.h                                                               |
  |                                                                           |
- | Copyright (C) 1992,1993                                                   |
+ | Copyright (C) 1992,1993,2001                                              |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
+ |                       Australia.  E-mail   billm@melbpc.org.au            |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
@@ -18,6 +18,11 @@
 #define	Const__(x)	x
 #endif
 
+#define CFLAG   1
+#define PFLAG   4
+#define ZFLAG   0x40
+#define SFLAGS (CFLAG | PFLAG | ZFLAG)
+
 #define SW_Backward    	Const__(0x8000)	/* backward compatibility */
 #define SW_C3		Const__(0x4000)	/* condition bit 3 */
 #define SW_Top		Const__(0x3800)	/* top of stack */
@@ -47,19 +52,21 @@
 #define COMP_SNaN	0x80
 
 #define status_word() \
-  ((partial_status & ~SW_Top & 0xffff) | ((top << SW_Top_Shift) & SW_Top))
+  ((partial_status & ~SW_Top & 0xffff) | ((FPU_top << SW_Top_Shift) & SW_Top))
 #define setcc(cc) ({ \
   partial_status &= ~(SW_C0|SW_C1|SW_C2|SW_C3); \
   partial_status |= (cc) & (SW_C0|SW_C1|SW_C2|SW_C3); })
 
+#define setccf(ftype,cc) { if ( ftype ) setflags((cc) >> 8); else setcc(cc); }
+
 #ifdef PECULIAR_486
    /* Default, this conveys no information, but an 80486 does it. */
    /* Clear the SW_C1 bit, "other bits undefined". */
 #  define clear_C1()  { partial_status &= ~SW_C1; }
 # else
 #  define clear_C1()
-#endif PECULIAR_486
+#endif /* PECULIAR_486 */
 
-#endif __ASSEMBLY__
+#endif /* __ASSEMBLY__ */
 
-#endif _STATUS_H_
+#endif /* _STATUS_H_ */
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/version.h linux-2.0.40/arch/i386/math-emu/version.h
--- linux-2.0.39/arch/i386/math-emu/version.h	Mon May  6 15:31:17 1996
+++ linux-2.0.40/arch/i386/math-emu/version.h	Mon Oct  8 23:54:43 2001
@@ -2,11 +2,11 @@
  |  version.h                                                                |
  |                                                                           |
  |                                                                           |
- | Copyright (C) 1992,1993,1994,1996                                         |
+ | Copyright (C) 1992,1993,1994,1996,1997,1999,2001                          |
  |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
- |                  E-mail   billm@jacobi.maths.monash.edu.au                |
+ |                  E-mail   billm@melbpc.org.au                             |
  |                                                                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
-#define FPU_VERSION "wm-FPU-emu version 1.22"
+#define FPU_VERSION "wm-FPU-emu version 2.11"
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/wm_shrx.S linux-2.0.40/arch/i386/math-emu/wm_shrx.S
--- linux-2.0.39/arch/i386/math-emu/wm_shrx.S	Thu Oct  5 14:30:43 1995
+++ linux-2.0.40/arch/i386/math-emu/wm_shrx.S	Mon Oct  8 23:54:43 2001
@@ -9,9 +9,9 @@
  |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
  |                                                                           |
  | Call from C as:                                                           |
- |   unsigned shrx(void *arg1, unsigned arg2)                                |
+ |   unsigned FPU_shrx(void *arg1, unsigned arg2)                            |
  | and                                                                       |
- |   unsigned shrxs(void *arg1, unsigned arg2)                               |
+ |   unsigned FPU_shrxs(void *arg1, unsigned arg2)                           |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
@@ -19,7 +19,7 @@
 
 .text
 /*---------------------------------------------------------------------------+
- |   unsigned shrx(void *arg1, unsigned arg2)                                |
+ |   unsigned FPU_shrx(void *arg1, unsigned arg2)                            |
  |                                                                           |
  |   Extended shift right function.                                          |
  |   Fastest for small shifts.                                               |
@@ -32,7 +32,7 @@
  |   Results returned in the 64 bit arg and eax.                             |
  +---------------------------------------------------------------------------*/
 
-ENTRY(shrx)
+ENTRY(FPU_shrx)
 	push	%ebp
 	movl	%esp,%ebp
 	pushl	%esi
@@ -95,7 +95,7 @@
 
 
 /*---------------------------------------------------------------------------+
- |   unsigned shrxs(void *arg1, unsigned arg2)                               |
+ |   unsigned FPU_shrxs(void *arg1, unsigned arg2)                           |
  |                                                                           |
  |   Extended shift right function (optimized for small floating point       |
  |   integers).                                                              |
@@ -110,7 +110,7 @@
  |   part which has been shifted out of the arg.                             |
  |   Results returned in the 64 bit arg and eax.                             |
  +---------------------------------------------------------------------------*/
-ENTRY(shrxs)
+ENTRY(FPU_shrxs)
 	push	%ebp
 	movl	%esp,%ebp
 	pushl	%esi
diff -u --recursive --new-file linux-2.0.39/arch/i386/math-emu/wm_sqrt.S linux-2.0.40/arch/i386/math-emu/wm_sqrt.S
--- linux-2.0.39/arch/i386/math-emu/wm_sqrt.S	Thu Oct  5 14:30:43 1995
+++ linux-2.0.40/arch/i386/math-emu/wm_sqrt.S	Mon Oct  8 23:54:43 2001
@@ -4,12 +4,12 @@
  |                                                                           |
  | Fixed point arithmetic square root evaluation.                            |
  |                                                                           |
- | Copyright (C) 1992,1993,1995                                              |
+ | Copyright (C) 1992,1993,1995,1997                                         |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                       Australia.  E-mail billm@suburbia.net               |
  |                                                                           |
  | Call from C as:                                                           |
- |   void wm_sqrt(FPU_REG *n, unsigned int control_word)                     |
+ |    int wm_sqrt(FPU_REG *n, unsigned int control_word)                     |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
@@ -70,7 +70,7 @@
 	.long	0
 FPU_fsqrt_arg_0:
 	.long	0		/* ls word, at most the ms bit is set */
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */ 
 
 
 .text
@@ -79,7 +79,7 @@
 	movl	%esp,%ebp
 #ifndef NON_REENTRANT_FPU
 	subl	$28,%esp
-#endif NON_REENTRANT_FPU
+#endif /* NON_REENTRANT_FPU */
 	pushl	%esi
 	pushl	%edi
 	pushl	%ebx
@@ -92,7 +92,7 @@
 
 /* We use a rough linear estimate for the first guess.. */
 
-	cmpl	EXP_BIAS,EXP(%esi)
+	cmpw	EXP_BIAS,EXP(%esi)
 	jnz	sqrt_arg_ge_2
 
 	shrl	$1,%eax			/* arg is in the range  [1.0 .. 2.0) */
@@ -210,7 +210,7 @@
 /* It should be possible to get here only if the arg is ffff....ffff */
 	cmp	$0xffffffff,FPU_fsqrt_arg_1
 	jnz	sqrt_stage_2_error
-#endif PARANOID
+#endif /* PARANOID */
 
 /* The best rounded result. */
 	xorl	%eax,%eax
@@ -224,7 +224,7 @@
 sqrt_stage_2_error:
 	pushl	EX_INTERNAL|0x213
 	call	EXCEPTION
-#endif PARANOID
+#endif /* PARANOID */ 
 
 sqrt_stage_2_done:
 
@@ -279,7 +279,7 @@
 	call	EXCEPTION
 
 sqrt_stage_3_no_error:
-#endif PARANOID
+#endif /* PARANOID */
 
 	movl	FPU_accum_2,%edx
 	movl	FPU_accum_1,%eax
@@ -347,9 +347,8 @@
 	movl	%esi,%eax
 	movl	%edi,%ebx
 	movl	PARAM1,%edi
-	movl	EXP_BIAS,EXP(%edi)	/* Result is in  [1.0 .. 2.0) */
-	movl	PARAM2,%ecx
-	jmp	fpu_reg_round_sqrt
+	movw	EXP_BIAS,EXP(%edi)	/* Result is in  [1.0 .. 2.0) */
+	jmp	fpu_reg_round
 
 
 sqrt_near_exact_x:
@@ -386,7 +385,7 @@
 	call	EXCEPTION
 
 sqrt_near_exact_ok:
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	or	%ebx,%ebx
 	js	sqrt_near_exact_small
@@ -446,7 +445,7 @@
 	call	EXCEPTION
 
 sqrt_more_prec_ok:
-#endif PARANOID
+#endif /* PARANOID */ 
 
 	or	%ebx,%ebx
 	js	sqrt_more_prec_small
diff -u --recursive --new-file linux-2.0.39/arch/i386/mm/fault.c linux-2.0.40/arch/i386/mm/fault.c
--- linux-2.0.39/arch/i386/mm/fault.c	Tue Dec  2 22:58:53 1997
+++ linux-2.0.40/arch/i386/mm/fault.c	Mon Sep 10 17:54:45 2001
@@ -49,7 +49,7 @@
 	int write;
 
 	/* get the address */
-	__asm__("movl %%cr2,%0":"=r" (address));
+	__asm__("movl %%cr2,%0" : "=r" (address));
 	down(&mm->mmap_sem);
 	vma = find_vma(mm, address);
 	if (!vma)
diff -u --recursive --new-file linux-2.0.39/arch/i386/mm/init.c linux-2.0.40/arch/i386/mm/init.c
--- linux-2.0.39/arch/i386/mm/init.c	Sun Jun 13 19:21:00 1999
+++ linux-2.0.40/arch/i386/mm/init.c	Mon Sep 10 17:56:43 2001
@@ -57,11 +57,13 @@
 {
 	extern char empty_bad_page_table[PAGE_SIZE];
 
-	__asm__ __volatile__("cld ; rep ; stosl":
-		:"a" (pte_val(BAD_PAGE)),
-		 "D" ((long) empty_bad_page_table),
-		 "c" (PAGE_SIZE/4)
-		:"di","cx");
+	__asm__ __volatile__(
+		"cld ; rep ; stosl"
+		:
+		: "a" (pte_val(BAD_PAGE)),
+		  "D" ((long) empty_bad_page_table),
+		  "c" (PAGE_SIZE/4)
+		: "di","cx");
 	return (pte_t *) empty_bad_page_table;
 }
 
@@ -69,11 +71,13 @@
 {
 	extern char empty_bad_page[PAGE_SIZE];
 
-	__asm__ __volatile__("cld ; rep ; stosl":
-		:"a" (0),
-		 "D" ((long) empty_bad_page),
-		 "c" (PAGE_SIZE/4)
-		:"di","cx");
+	__asm__ __volatile__(
+		"cld ; rep ; stosl"
+		:
+		: "a" (0),
+		  "D" ((long) empty_bad_page),
+		  "c" (PAGE_SIZE/4)
+		: "di","cx");
 	return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED));
 }
 
@@ -183,12 +187,16 @@
 			__asm__("movl %%cr4,%%eax\n\t"
 				"orl $16,%%eax\n\t"
 				"movl %%eax,%%cr4"
-				: : :"ax");
+				:
+				:
+				: "ax");
 #else
 			__asm__(".byte 0x0f,0x20,0xe0\n\t"
 				"orl $16,%%eax\n\t"
 				".byte 0x0f,0x22,0xe0"
-				: : :"ax");
+				:
+				:
+				: "ax");
 #endif
 			wp_works_ok = 1;
 			pgd_val(pg_dir[0]) = _PAGE_TABLE | _PAGE_4M | address;
@@ -292,7 +300,7 @@
 	if (wp_works_ok < 0) {
 		pg0[0] = pte_val(mk_pte(0, PAGE_READONLY));
 		local_flush_tlb();
-		__asm__ __volatile__("movb 0,%%al ; movb %%al,0": : :"ax", "memory");
+		__asm__ __volatile__("movb 0,%%al ; movb %%al,0" : : : "ax", "memory");
 		pg0[0] = 0;
 		local_flush_tlb();
 		if (wp_works_ok < 0)
diff -u --recursive --new-file linux-2.0.39/arch/m68k/config.in linux-2.0.40/arch/m68k/config.in
--- linux-2.0.39/arch/m68k/config.in	Thu Dec 30 01:54:06 1999
+++ linux-2.0.40/arch/m68k/config.in	Mon Oct  8 14:06:31 2001
@@ -178,4 +178,9 @@
 if [ "$CONFIG_PROFILE" = "y" ]; then
    int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
+bool 'Memory flooding' CONFIG_SADISTIC_KMALLOC
+bool 'Socket-buffer consistency checking' CONFIG_SKB_CHECK
+if [ "$CONFIG_SKB_CHECK" = "y" ]; then
+   bool '  Whole-queue checking' CONFIG_SKB_CHECK_WHOLE_QUEUE
+fi
 endmenu
diff -u --recursive --new-file linux-2.0.39/arch/mips/config.in linux-2.0.40/arch/mips/config.in
--- linux-2.0.39/arch/mips/config.in	Thu Dec 30 01:57:14 1999
+++ linux-2.0.40/arch/mips/config.in	Mon Oct  8 14:06:31 2001
@@ -115,4 +115,9 @@
 if [ "$CONFIG_PROFILE" = "y" ]; then
    int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
+bool 'Memory flooding' CONFIG_SADISTIC_KMALLOC
+bool 'Socket-buffer consistency checking' CONFIG_SKB_CHECK
+if [ "$CONFIG_SKB_CHECK" = "y" ]; then
+   bool '  Whole-queue checking' CONFIG_SKB_CHECK_WHOLE_QUEUE
+fi
 endmenu
diff -u --recursive --new-file linux-2.0.39/arch/mips/kernel/sysmips.c linux-2.0.40/arch/mips/kernel/sysmips.c
--- linux-2.0.39/arch/mips/kernel/sysmips.c	Wed Dec 13 11:39:44 1995
+++ linux-2.0.40/arch/mips/kernel/sysmips.c	Mon Aug 20 13:19:24 2001
@@ -52,7 +52,8 @@
 {
 	int	*p;
 	char	*name;
-	int	flags, len, retval = -EINVAL;
+	int	len, retval = -EINVAL;
+	unsigned long flags;
 
 	switch(cmd)
 	{
diff -u --recursive --new-file linux-2.0.39/arch/ppc/config.in linux-2.0.40/arch/ppc/config.in
--- linux-2.0.39/arch/ppc/config.in	Thu Dec 30 01:58:56 1999
+++ linux-2.0.40/arch/ppc/config.in	Mon Oct  8 14:06:31 2001
@@ -104,4 +104,9 @@
 if [ "$CONFIG_PROFILE" = "y" ]; then
    int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
+bool 'Memory flooding' CONFIG_SADISTIC_KMALLOC
+bool 'Socket-buffer consistency checking' CONFIG_SKB_CHECK
+if [ "$CONFIG_SKB_CHECK" = "y" ]; then
+   bool '  Whole-queue checking' CONFIG_SKB_CHECK_WHOLE_QUEUE
+fi
 endmenu
diff -u --recursive --new-file linux-2.0.39/arch/sparc/config.in linux-2.0.40/arch/sparc/config.in
--- linux-2.0.39/arch/sparc/config.in	Thu Dec 30 02:02:58 1999
+++ linux-2.0.40/arch/sparc/config.in	Mon Oct  8 14:06:31 2001
@@ -111,3 +111,8 @@
 if [ "$CONFIG_PROFILE" = "y" ]; then
    int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
+bool 'Memory flooding' CONFIG_SADISTIC_KMALLOC
+bool 'Socket-buffer consistency checking' CONFIG_SKB_CHECK
+if [ "$CONFIG_SKB_CHECK" = "y" ]; then
+   bool '  Whole-queue checking' CONFIG_SKB_CHECK_WHOLE_QUEUE
+fi
diff -u --recursive --new-file linux-2.0.39/arch/sparc/kernel/sparc-stub.c linux-2.0.40/arch/sparc/kernel/sparc-stub.c
--- linux-2.0.39/arch/sparc/kernel/sparc-stub.c	Mon May  6 11:26:03 1996
+++ linux-2.0.40/arch/sparc/kernel/sparc-stub.c	Mon Aug 20 13:21:03 2001
@@ -183,7 +183,8 @@
 /* Initialize the kgdb_savettable so that debugging can commence */
 static void eh_init(void)
 {
-	int i, flags;
+	int i;
+	unsigned long flags;
 
 	save_flags(flags); cli();
 	for(i=0; i < 256; i++)
@@ -195,7 +196,7 @@
 static void exceptionHandler(int tnum, trapfunc_t trap_entry)
 {
 	unsigned long te_addr = (unsigned long) trap_entry;
-	int flags;
+	unsigned long flags;
 
 	/* We are dorking with a live trap table, all irqs off */
 	save_flags(flags); cli();
diff -u --recursive --new-file linux-2.0.39/drivers/block/ide.c linux-2.0.40/drivers/block/ide.c
--- linux-2.0.39/drivers/block/ide.c	Wed Sep  6 23:42:53 2000
+++ linux-2.0.40/drivers/block/ide.c	Mon Nov 26 21:12:45 2001
@@ -2738,6 +2738,10 @@
 	} else
 		hd_status = IDE_ALTSTATUS_REG;	/* use non-intrusive polling */
 
+	/* set features register for atapi identify command */
+	if ((cmd == WIN_PIDENTIFY))
+		OUT_BYTE(0,IDE_FEATURE_REG); /* disable dma & overlap mode */
+
 #if CONFIG_BLK_DEV_PROMISE
 	if (IS_PROMISE_DRIVE) {
 		if (promise_cmd(drive,PROMISE_IDENTIFY)) {
diff -u --recursive --new-file linux-2.0.39/drivers/block/ll_rw_blk.c linux-2.0.40/drivers/block/ll_rw_blk.c
--- linux-2.0.39/drivers/block/ll_rw_blk.c	Wed Jun 28 14:48:19 2000
+++ linux-2.0.40/drivers/block/ll_rw_blk.c	Tue Aug 21 17:42:05 2001
@@ -356,7 +356,7 @@
 	if (buffer_locked(bh)) {
 #if 0
 		printk("make_request(): buffer already locked\n");
-#endif
+#endif /* 0 */
 		return;
 	}
 	/* Maybe the above fixes it, and maybe it doesn't boot. Life is interesting */
@@ -388,7 +388,7 @@
 			if (buffer_uptodate(bh)) {
 #if 0
 				printk ("make_request(): buffer uptodate for READ\n");
-#endif
+#endif /* 0 */
 				unlock_buffer(bh); /* Hmmph! Already have it */
 				return;
 			}
@@ -402,7 +402,7 @@
 			if (!buffer_dirty(bh)) {
 #if 0
 				printk ("make_request(): buffer clean for WRITE\n");
-#endif
+#endif /* 0 */
 				unlock_buffer(bh); /* Hmmph! Nothing to write */
 				return;
 			}
@@ -609,7 +609,7 @@
 				"Bad md_map in ll_rw_block\n");
 		        goto sorry;
 		}
-#endif
+#endif /* CONFIG_BLK_DEV_MD */
 	}
 
 	if ((rw == WRITE || rw == WRITEA) && is_read_only(bh[0]->b_dev)) {
@@ -626,7 +626,7 @@
 				md_make_request(MINOR (bh[i]->b_dev), rw, bh[i]);
 				continue;
 			}
-#endif
+#endif /* CONFIG_BLK_DEV_MD */
 			make_request(MAJOR(bh[i]->b_rdev), rw, bh[i]);
 		}
 	}
@@ -692,8 +692,8 @@
                                         "Bad md_map in ll_rw_swap_file\n");
 				return;
 			}
-#endif
-			
+#endif /* CONFIG_BLK_DEV_MD */
+
 			if (j == 0) {
 				req[j] = get_request_wait(max_req, rdev);
 			} else {
@@ -746,62 +746,64 @@
 	memset(ro_bits,0,sizeof(ro_bits));
 #ifdef CONFIG_BLK_DEV_RAM
 	rd_init();
-#endif
+#endif /* CONFIG_BLK_DEV_RAM */
 #ifdef CONFIG_BLK_DEV_LOOP
 	loop_init();
-#endif
+#endif /* CONFIG_BLK_DEV_LOOP */
 #ifdef CONFIG_CDI_INIT
 	cdi_init();		/* this MUST precede ide_init */
-#endif CONFIG_CDI_INIT
+#endif /* CONFIG_CDI_INIT */
 #ifdef CONFIG_BLK_DEV_IDE
 	ide_init();		/* this MUST precede hd_init */
-#endif
+#endif /* CONFIG_BLK_DEV_IDE */
 #ifdef CONFIG_BLK_DEV_HD
 	hd_init();
-#endif
+#endif /* CONFIG_BLK_DEV_HD */
 #ifdef CONFIG_BLK_DEV_XD
 	xd_init();
-#endif
+#endif /* CONFIG_BLK_DEV_XD */
 #ifdef CONFIG_PARIDE
         { extern void paride_init(void); paride_init(); };
-#endif
+#endif /* CONFIG_PARIDE */
 #ifdef CONFIG_BLK_DEV_FD
 	floppy_init();
-#else
+#else /* CONFIG_BLK_DEV_FD */
+#if defined(__i386__)	/* Do we even need this? */
 	outb_p(0xc, 0x3f2);
-#endif
+#endif /* defined(__i386__) */
+#endif /* !CONFIG_BLK_DEV_FD */
 #ifdef CONFIG_CDU31A
 	cdu31a_init();
-#endif CONFIG_CDU31A
+#endif /* CONFIG_CDU31A */
 #ifdef CONFIG_MCD
 	mcd_init();
-#endif CONFIG_MCD
+#endif /* CONFIG_MCD */
 #ifdef CONFIG_MCDX
 	mcdx_init();
-#endif CONFIG_MCDX
+#endif /* CONFIG_MCDX */
 #ifdef CONFIG_SBPCD
 	sbpcd_init();
-#endif CONFIG_SBPCD
+#endif /* CONFIG_SBPCD */
 #ifdef CONFIG_AZTCD
         aztcd_init();
-#endif CONFIG_AZTCD
+#endif /* CONFIG_AZTCD */
 #ifdef CONFIG_CDU535
 	sony535_init();
-#endif CONFIG_CDU535
+#endif /* CONFIG_CDU535 */
 #ifdef CONFIG_GSCD
 	gscd_init();
-#endif CONFIG_GSCD
+#endif /* CONFIG_GSCD */
 #ifdef CONFIG_CM206
 	cm206_init();
-#endif
+#endif /* CONFIG_CM206 */
 #ifdef CONFIG_OPTCD
 	optcd_init();
-#endif CONFIG_OPTCD
+#endif /* CONFIG_OPTCD */
 #ifdef CONFIG_SJCD
 	sjcd_init();
-#endif CONFIG_SJCD
+#endif /* CONFIG_SJCD */
 #ifdef CONFIG_BLK_DEV_MD
 	md_init();
-#endif CONFIG_BLK_DEV_MD
+#endif /* CONFIG_BLK_DEV_MD */
 	return 0;
 }
diff -u --recursive --new-file linux-2.0.39/drivers/block/promise.h linux-2.0.40/drivers/block/promise.h
--- linux-2.0.39/drivers/block/promise.h	Sat Mar 16 12:52:15 1996
+++ linux-2.0.40/drivers/block/promise.h	Tue Aug 21 17:42:48 2001
@@ -49,4 +49,4 @@
 void setup_dc4030 (ide_hwif_t *);
 int init_dc4030 (void);
 
-#endif IDE_PROMISE_H
+#endif /* !IDE_PROMISE_H */
diff -u --recursive --new-file linux-2.0.39/drivers/cdrom/aztcd.c linux-2.0.40/drivers/cdrom/aztcd.c
--- linux-2.0.39/drivers/cdrom/aztcd.c	Mon May 20 07:38:42 1996
+++ linux-2.0.40/drivers/cdrom/aztcd.c	Thu Aug 23 18:53:14 2001
@@ -334,7 +334,7 @@
 #ifdef MODULE
  int        init_module(void);
  void       cleanup_module(void);
-#endif MODULE
+#endif /* MODULE */
 static struct file_operations azt_fops = {
 	NULL,                   /* lseek - default */
 	block_read,             /* read - general block-dev read */
@@ -1748,7 +1748,7 @@
       release_region(azt_port,4);  /*proprietary interface*/
   printk(KERN_INFO "aztcd module released.\n");
 }   
-#endif MODULE
+#endif /* MODULE */
 
 
 /*##########################################################################
diff -u --recursive --new-file linux-2.0.39/drivers/cdrom/cdi.c linux-2.0.40/drivers/cdrom/cdi.c
--- linux-2.0.39/drivers/cdrom/cdi.c	Tue Feb 13 09:30:25 1996
+++ linux-2.0.40/drivers/cdrom/cdi.c	Thu Aug 23 18:56:04 2001
@@ -30,7 +30,7 @@
 #include <linux/blk.h>  /* where the proto type of cdi_init() is */
 #ifdef CONFIG_ISP16_CDI
 #include <linux/isp16.h>
-#endif CONFIG_ISP16_CDI
+#endif /* CONFIG_ISP16_CDI */
 
 /*
  *  Cdrom interface configuration.
@@ -42,7 +42,7 @@
 
 #ifdef CONFIG_ISP16_CDI
   ret_val &= isp16_init();
-#endif CONFIG_ISP16_CDI
+#endif /* CONFIG_ISP16_CDI */
 
   return(ret_val);
 }
diff -u --recursive --new-file linux-2.0.39/drivers/cdrom/cdu31a.c linux-2.0.40/drivers/cdrom/cdu31a.c
--- linux-2.0.39/drivers/cdrom/cdu31a.c	Tue Apr  8 17:47:45 1997
+++ linux-2.0.40/drivers/cdrom/cdu31a.c	Thu Aug 23 18:53:25 2001
@@ -3243,4 +3243,4 @@
    release_region(cdu31a_port,4);
    printk(KERN_INFO "cdu31a module released.\n");
 }   
-#endif MODULE
+#endif /* MODULE */
diff -u --recursive --new-file linux-2.0.39/drivers/cdrom/mcd.c linux-2.0.40/drivers/cdrom/mcd.c
--- linux-2.0.39/drivers/cdrom/mcd.c	Mon Jul 13 22:47:28 1998
+++ linux-2.0.40/drivers/cdrom/mcd.c	Thu Aug 23 18:53:34 2001
@@ -1644,4 +1644,4 @@
   free_irq(mcd_irq, NULL);
   printk(KERN_INFO "mcd module released.\n");
 }
-#endif MODULE
+#endif /* MODULE */
diff -u --recursive --new-file linux-2.0.39/drivers/cdrom/mcdx.c linux-2.0.40/drivers/cdrom/mcdx.c
--- linux-2.0.39/drivers/cdrom/mcdx.c	Tue Jul 23 09:26:54 1996
+++ linux-2.0.40/drivers/cdrom/mcdx.c	Thu Aug 23 18:53:44 2001
@@ -1154,7 +1154,7 @@
 #endif
 }
 
-#endif MODULE
+#endif /* MODULE */
 
 /* Support functions ************************************************/
 
diff -u --recursive --new-file linux-2.0.39/drivers/cdrom/optcd.c linux-2.0.40/drivers/cdrom/optcd.c
--- linux-2.0.39/drivers/cdrom/optcd.c	Tue Jun  4 09:53:46 1996
+++ linux-2.0.40/drivers/cdrom/optcd.c	Thu Aug 23 18:54:15 2001
@@ -915,7 +915,7 @@
 		return -EIO;
 	return 0;
 }
-#endif MULTISESSION
+#endif /* MULTISESSION */
 
 
 static int update_toc(void)
@@ -953,7 +953,7 @@
 #ifdef MULTISESSION
  	if (disk_info.xa)
 		get_multi_disk_info();	/* Here disk_info.multi is set */
-#endif MULTISESSION
+#endif /* MULTISESSION */
 	if (disk_info.multi)
 		printk(KERN_WARNING "optcd: Multisession support experimental, "
 			"see linux/Documentation/cdrom/optcd\n");
@@ -1704,11 +1704,11 @@
 			disk_info.last_session.minute,
 			disk_info.last_session.second,
 			disk_info.last_session.frame);
-#endif DEBUG_MULTIS
+#endif /* DEBUG_MULTIS */
 
 	return 0;
 }
-#endif MULTISESSION
+#endif /* MULTISESSION */
 
 
 static int cdromreset(void)
@@ -2081,4 +2081,4 @@
 	release_region(optcd_port, 4);
 	printk(KERN_INFO "optcd: module released.\n");
 }
-#endif MODULE
+#endif /* MODULE */
diff -u --recursive --new-file linux-2.0.39/drivers/cdrom/sbpcd.c linux-2.0.40/drivers/cdrom/sbpcd.c
--- linux-2.0.39/drivers/cdrom/sbpcd.c	Sun Jun 13 19:21:00 1999
+++ linux-2.0.40/drivers/cdrom/sbpcd.c	Thu Aug 23 19:38:11 2001
@@ -313,7 +313,7 @@
 
 #ifndef SBPCD_ISSUE
 #define SBPCD_ISSUE 1
-#endif SBPCD_ISSUE
+#endif /* SBPCD_ISSUE */
 
 #include <linux/module.h>
 
@@ -377,7 +377,7 @@
 #else
 #define SBPCD_CLI
 #define SBPCD_STI
-#endif SBPCD_DIS_IRQ
+#endif /* SBPCD_DIS_IRQ */
 /*==========================================================================*/
 /*
  * auto-probing address list
@@ -434,8 +434,8 @@
 	0x370, 0, /* Lasermate, CI-101P */
 	0x290, 1, /* Soundblaster 16 */
 	0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
-#endif MODULE
-#endif DISTRIBUTION
+#endif /* MODULE */
+#endif /* DISTRIBUTION */
 };
 #else
 static int sbpcd[] = {CDROM_PORT, SBPRO}; /* probe with user's setup only */
@@ -523,7 +523,7 @@
 			  (1<<DBG_TOC) |
 			  (1<<DBG_MUL) |
 			  (1<<DBG_UPC));
-#endif DISTRIBUTION
+#endif /* DISTRIBUTION */
 
 static int sbpcd_ioaddr = CDROM_PORT;	/* default I/O base address */
 static int sbpro_type = SBPRO;
@@ -573,7 +573,7 @@
 
 #if FUTURE
 static struct wait_queue *sbp_waitq = NULL;
-#endif FUTURE
+#endif /* FUTURE */
 
 static int teac=SBP_TEAC_SPEED;
 static int buffers=SBP_BUFFER_FRAMES;
@@ -598,7 +598,7 @@
 #if OLD_BUSY
 static volatile u_char busy_data=0;
 static volatile u_char busy_audio=0; /* true semaphores would be safer */
-#endif OLD_BUSY
+#endif /* OLD_BUSY */
 static struct semaphore ioctl_read_sem = MUTEX;
 static u_long timeout;
 static volatile u_char timed_out_delay=0;
@@ -615,7 +615,7 @@
 static u_int maxtim_data= 9000;
 #else
 static u_int maxtim_data= 3000;
-#endif LONG_TIMING
+#endif /* LONG_TIMING */
 #if DISTRIBUTION
 static int n_retries=3;
 #else
@@ -680,7 +680,7 @@
 	u_char vol_ctrl2;
 	char vol_chan3;
 	u_char vol_ctrl3;
-#endif 000
+#endif /* 000 */
 	u_char volume_control; /* TEAC on/off bits */
 	
 	u_char SubQ_ctl_adr;
@@ -709,7 +709,7 @@
 	u_int TocEnt_address;
 #if SAFE_MIXED
 	char has_data;
-#endif SAFE_MIXED
+#endif /* SAFE_MIXED */
 	u_char ored_ctl_adr; /* to detect if CDROM contains data tracks */
 	
 	struct {
@@ -758,7 +758,7 @@
 #define MSG_LEVEL KERN_NOTICE
 #else
 #define MSG_LEVEL KERN_INFO
-#endif DISTRIBUTION
+#endif /* DISTRIBUTION */
 
 	char buf[256];
 	va_list args;
@@ -774,7 +774,7 @@
 	printk(buf);
 #if KLOGD_PAUSE
 	sbp_sleep(KLOGD_PAUSE); /* else messages get lost */
-#endif KLOGD_PAUSE
+#endif /* KLOGD_PAUSE */
 	return;
 }
 /*==========================================================================*/
@@ -1069,7 +1069,7 @@
 	return (0);
 }
 /*==========================================================================*/
-#endif 00000
+#endif /* 00000 */
 /*==========================================================================*/
 static int ResponseInfo(void)
 {
@@ -1099,7 +1099,7 @@
 	}
 	j=i-response_count;
 	if (j>0) msg(DBG_INF,"ResponseInfo: got %d trailing bytes.\n",j);
-#endif 000
+#endif /* 000 */
 	for (j=0;j<i;j++)
 		sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
 	msgbuf[j*3]=0;
@@ -1351,7 +1351,7 @@
 		if (drvcmd[0]==CMDT_READ_VER) sbp_sleep(HZ); /* fixme */
 #if 01
 		OUT(CDo_sel_i_d,1);
-#endif 01
+#endif /* 01 */
 		if (teac==2)
                   {
                     if ((i=CDi_stat_loop_T()) == -1) break;
@@ -1360,7 +1360,7 @@
                   {
 #if 0
                     OUT(CDo_sel_i_d,1);
-#endif 0
+#endif /* 0 */
                     i=inb(CDi_status);
                   }
 		if (!(i&s_not_data_ready)) /* f.e. CMDT_DISKINFO */
@@ -1384,7 +1384,7 @@
                                                         l=1;
                                                         msg(DBG_TEA,"cmd_out_T: do_16bit: false first byte!\n");
                                                 }
-#endif TEST_FALSE_FF
+#endif /* TEST_FALSE_FF */
                                         }
                                         else infobuf[l++]=inb(CDi_data);
                                         i=inb(CDi_status);
@@ -1978,7 +1978,7 @@
 		msg(DBG_TEA, "================CMDT_RESET given=================.\n");
 		sbp_sleep(3*HZ);
 	}
-#endif 1
+#endif /* 1 */
 	flush_status();
 	i=GetStatus();
 	if (i<0) return i;
@@ -1990,7 +1990,7 @@
 static int SetSpeed(void)
 {
 	int i, speed;
-	
+
 	if (!(D_S[d].drv_options&(speed_auto|speed_300|speed_150))) return (0);
 	speed=speed_auto;
 	if (!(D_S[d].drv_options&speed_auto))
@@ -2560,7 +2560,7 @@
 	D_S[d].vol_ctrl2=0xFF;
 	D_S[d].vol_chan3=3;
 	D_S[d].vol_ctrl3=0xFF;
-#endif 000
+#endif /* 000 */
 	D_S[d].diskstate_flags |= volume_bit;
 	return (0);
 }
@@ -2568,7 +2568,7 @@
 static int cc_ReadCapacity(void)
 {
 	int i, j;
-	
+
 	if (fam2_drive) return (0); /* some firmware lacks this command */
 	if (famLV_drive) return (0); /* some firmware lacks this command */
 	if (famT_drive) return (0); /* done with cc_ReadTocDescr() */
@@ -2858,20 +2858,20 @@
 	int i;
 #if TEST_UPC
 	int block, checksum;
-#endif TEST_UPC
-	
+#endif /* TEST_UPC */
+
 	if (fam2_drive) return (0); /* not implemented yet */
 	if (famT_drive)	return (0); /* not implemented yet */
 	if (famV_drive)	return (0); /* not implemented yet */
 #if 1
 	if (fam0_drive) return (0); /* but it should work */
-#endif 1
-	
+#endif /* 1 */
+
 	D_S[d].diskstate_flags &= ~upc_bit;
 #if TEST_UPC
 	for (block=CD_MSF_OFFSET+1;block<CD_MSF_OFFSET+200;block++)
 	{
-#endif TEST_UPC
+#endif /* TEST_UPC */
 		clr_cmdbuf();
 		if (fam1_drive)
 		{
@@ -2880,7 +2880,7 @@
 			drvcmd[1]=(block>>16)&0xFF;
 			drvcmd[2]=(block>>8)&0xFF;
 			drvcmd[3]=block&0xFF;
-#endif TEST_UPC
+#endif /* TEST_UPC */
 			response_count=8;
 			flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
 		}
@@ -2891,7 +2891,7 @@
 			drvcmd[2]=(block>>16)&0xFF;
 			drvcmd[3]=(block>>8)&0xFF;
 			drvcmd[4]=block&0xFF;
-#endif TEST_UPC
+#endif /* TEST_UPC */
 			response_count=0;
 			flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
 		}
@@ -2922,12 +2922,12 @@
 		}
 #if TEST_UPC
 		checksum=0;
-#endif TEST_UPC
+#endif /* TEST_UPC */
 		for (i=0;i<(fam1_drive?8:16);i++)
 		{
 #if TEST_UPC
 			checksum |= infobuf[i];
-#endif TEST_UPC
+#endif /* TEST_UPC */
 			sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
 		}
 		msgbuf[i*3]=0;
@@ -2935,7 +2935,7 @@
 #if TEST_UPC
 		if ((checksum&0x7F)!=0) break;
 	}
-#endif TEST_UPC
+#endif /* TEST_UPC */
 	D_S[d].UPC_ctl_adr=0;
 	if (fam1_drive) i=0;
 	else i=2;
@@ -3047,12 +3047,12 @@
 	i=cmd_out(); /* which buffer to use? */
 	return (i);
 }
-#endif FUTURE
+#endif /* FUTURE */
 /*==========================================================================*/
 static void check_datarate(void)
 {
 	int i=0;
-	
+
 	msg(DBG_IOX,"check_datarate entered.\n");
 	datarate=0;
 #if TEST_STI
@@ -3074,7 +3074,7 @@
 		datarate++;
 #if 1
 		if (datarate>0x6FFFFFFF) break;
-#endif 00000
+#endif /* 00000 */
 	}
 	while (!timed_out_delay);
 	del_timer(&delay_timer);
@@ -3090,7 +3090,7 @@
 	maxtim_data=datarate/100;
 #else
 	maxtim_data=datarate/300;
-#endif LONG_TIMING
+#endif /* LONG_TIMING */
 #if 0
 	msg(DBG_TIM,"maxtim_8 %d, maxtim_data %d.\n", maxtim_8, maxtim_data);
 #endif
@@ -3244,7 +3244,7 @@
 		OUT(CDo_reset,0);
 		sbp_sleep(6*HZ);
 		OUT(CDo_enable,D_S[d].drv_sel);
-#endif 0
+#endif /* 0 */
 		drvcmd[0]=CMD2_READ_VER;
 		response_count=12;
 		flags_cmd_out=f_putcmd;
@@ -3534,7 +3534,7 @@
 	OUT(port+3,save_port3);
 	return (0); /* in any case - no real "function" at time */
 }
-#endif PATH_CHECK
+#endif /* PATH_CHECK */
 /*==========================================================================*/
 /*==========================================================================*/
 /*
@@ -3543,7 +3543,7 @@
 static int check_drives(void)
 {
 	int i, j;
-	
+
 	msg(DBG_INI,"check_drives entered.\n");
 	ndrives=0;
 	for (j=0;j<MAX_DRIVES;j++)
@@ -3641,7 +3641,7 @@
 	if (func2==tell_UPC) return (-1);
 #else
 	return (0);
-#endif 000
+#endif /* 000 */
 }
 /*==========================================================================*/
 static int check_allowed2(u_char func1, u_char func2)
@@ -3659,7 +3659,7 @@
 	}
 #else
 	return (0);
-#endif 000
+#endif /* 000 */
 }
 /*==========================================================================*/
 static int check_allowed3(u_char func1, u_char func2)
@@ -3693,7 +3693,7 @@
 	if (func1==audio_resume) return (-1);
 #else
 	return (0);
-#endif 000
+#endif /* 000 */
 }
 /*==========================================================================*/
 static int seek_pos_audio_end(void)
@@ -3705,7 +3705,7 @@
 	i=cc_Seek(i,0);
 	return (i);
 }
-#endif FUTURE
+#endif /* FUTURE */
 /*==========================================================================*/
 static int ReadToC(void)
 {
@@ -3883,7 +3883,7 @@
     }
 	return (0);
 }
-#endif FUTURE
+#endif /* FUTURE */
 /*==========================================================================*/
 /*==========================================================================*/
 /*
@@ -3892,16 +3892,16 @@
 static int sbp_status(void)
 {
 	int st;
-	
+
 	st=ResponseStatus();
 	if (st<0)
 	{
 		msg(DBG_INF,"sbp_status: timeout.\n");
 		return (0);
 	}
-	
+
 	if (!st_spinning) msg(DBG_SPI,"motor got off - ignoring.\n");
-	
+
 	if (st_check) 
 	{
 		msg(DBG_INF,"st_check detected - retrying.\n");
@@ -4011,12 +4011,12 @@
 		if (i<0) RETURN_UP(-EIO);
 		D_S[d].audio_state=audio_playing;
 		RETURN_UP(0);
-		
+
 	case CDROMPLAYMSF:
 		msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n");
 #if SAFE_MIXED
 		if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
-#endif SAFE_MIXED
+#endif /* SAFE_MIXED */
 		if (D_S[d].audio_state==audio_playing)
 		{
 			i=cc_Pause_Resume(1);
@@ -4048,12 +4048,12 @@
 		}
 		D_S[d].audio_state=audio_playing;
 		RETURN_UP(0);
-		
+
 	case CDROMPLAYTRKIND: /* Play a track.  This currently ignores index. */
 		msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
 #if SAFE_MIXED
 		if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
-#endif SAFE_MIXED
+#endif /* SAFE_MIXED */
 		if (D_S[d].audio_state==audio_playing)
 		{
 			msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
@@ -4121,28 +4121,28 @@
 		else RETURN_UP(-EINVAL);
 		memcpy_tofs((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
 		RETURN_UP(0);
-		
+
 	case CDROMRESET:      /* hard reset the drive */
 		msg(DBG_IOC,"ioctl: CDROMRESET entered.\n");
 		i=DriveReset();
 		D_S[d].audio_state=0;
 		RETURN_UP(i);
-		
+
 	case CDROMSTOP:      /* Spin down the drive */
 		msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n");
 #if SAFE_MIXED
 		if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
-#endif SAFE_MIXED
+#endif /* SAFE_MIXED */
 		i=cc_Pause_Resume(1);
 		D_S[d].audio_state=0;
 		RETURN_UP(i);
-		
+
 	case CDROMSTART:  /* Spin up the drive */
 		msg(DBG_IOC,"ioctl: CDROMSTART entered.\n");
 		cc_SpinUp();
 		D_S[d].audio_state=0;
 		RETURN_UP(0);
-		
+
 	case CDROMEJECT:
 		msg(DBG_IOC,"ioctl: CDROMEJECT entered.\n");
 		if (fam0_drive) return (0);
@@ -4157,7 +4157,7 @@
 		D_S[d].diskstate_flags=0;
 		D_S[d].audio_state=0;
 		RETURN_UP(0);
-		
+
 	case CDROMEJECT_SW:
 		msg(DBG_IOC,"ioctl: CDROMEJECT_SW entered.\n");
 		if (fam0_drive) RETURN_UP(0);
@@ -4235,27 +4235,27 @@
 		    SC.cdsc_trk,SC.cdsc_ind,
 		    SC.cdsc_absaddr,SC.cdsc_reladdr);
 		RETURN_UP(0);
-		
+
 	case CDROMREADMODE1:
 		msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n");
 #if SAFE_MIXED
 		if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
-#endif SAFE_MIXED
+#endif /* SAFE_MIXED */
 		cc_ModeSelect(CD_FRAMESIZE);
 		cc_ModeSense();
 		D_S[d].mode=READ_M1;
 		RETURN_UP(0);
-		
+
 	case CDROMREADMODE2: /* not usable at the moment */
 		msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n");
 #if SAFE_MIXED
 		if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
-#endif SAFE_MIXED
+#endif /* SAFE_MIXED */
 		cc_ModeSelect(CD_FRAMESIZE_RAW1);
 		cc_ModeSense();
 		D_S[d].mode=READ_M2;
 		RETURN_UP(0);
-		
+
 	case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
 		msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
 		if (D_S[d].sbp_audsiz>0) vfree(D_S[d].aud_buf);
@@ -4284,7 +4284,7 @@
 		u_int data_retrying = 0;
 		int status_tries;
 		int error_flag;
-		
+
 		msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n");
 		if (fam0_drive) RETURN_UP(-EINVAL);
 		if (famL_drive) RETURN_UP(-EINVAL);
@@ -4292,7 +4292,7 @@
 		if (famT_drive) RETURN_UP(-EINVAL);
 #if SAFE_MIXED
 		if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
-#endif SAFE_MIXED
+#endif /* SAFE_MIXED */
 		if (D_S[d].aud_buf==NULL) RETURN_UP(-EINVAL);
 		i=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_read_audio));
 		if (i) RETURN_UP(i);
@@ -4301,7 +4301,7 @@
 		i=verify_area(VERIFY_WRITE, read_audio.buf,
 			      read_audio.nframes*CD_FRAMESIZE_RAW);
 		if (i) RETURN_UP(i);
-		
+
 		if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
 			block=msf2lba(&read_audio.addr.msf.minute);
 		else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */
@@ -4317,7 +4317,7 @@
 #if OLD_BUSY
 		while (busy_data) sbp_sleep(HZ/10); /* wait a bit */
 		busy_audio=1;
-#endif OLD_BUSY
+#endif /* OLD_BUSY */
 		error_flag=0;
 		for (data_tries=5; data_tries>0; data_tries--)
 		{
@@ -4427,7 +4427,7 @@
 				i=cc_DriveReset();                /* ugly fix to prevent a hang */
 #else
 				i=cc_ReadError();
-#endif 0000
+#endif /* 0000 */
 				continue;
 			}
 			if (fam0L_drive)
@@ -4482,7 +4482,7 @@
 		D_S[d].mode=READ_M1;
 #if OLD_BUSY
 		busy_audio=0;
-#endif OLD_BUSY
+#endif /* OLD_BUSY */
 		if (data_tries == 0)
 		{
 			msg(DBG_AUD,"read_audio: failed after 5 tries.\n");
@@ -4491,7 +4491,7 @@
 		msg(DBG_AUD,"read_audio: successful return.\n");
 		RETURN_UP(0);
 	} /* end of CDROMREADAUDIO */
-		
+
 	case CDROMMULTISESSION: /* tell start-of-last-session */
 		msg(DBG_IOC,"ioctl: CDROMMULTISESSION entered.\n");
 		st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_multisession));
@@ -4632,19 +4632,19 @@
 #if OLD_BUSY
 	while (busy_audio) sbp_sleep(HZ); /* wait a bit */
 	busy_data=1;
-#endif OLD_BUSY
-	
+#endif /* OLD_BUSY */
+
 	if (D_S[i].audio_state==audio_playing) goto err_done;
 	if (d!=i) switch_drive(i);
-	
+
 	block = req->sector; /* always numbered as 512-byte-pieces */
 	nsect = req->nr_sectors; /* always counted as 512-byte-pieces */
-	
+
 	msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect);
 #if 0
 	msg(DBG_MUL,"read LBA %d\n", block/4);
 #endif
-	
+
 	sbp_transfer(req);
 	/* if we satisfied the request from the buffer, we're done. */
 	if (req->nr_sectors == 0)
@@ -4661,10 +4661,10 @@
 	i=prepare(0,0); /* at moment not really a hassle check, but ... */
 	if (i!=0)
 		msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i);
-#endif FUTURE
-	
+#endif /* FUTURE */
+
 	if (!st_spinning) cc_SpinUp();
-	
+
 	for (data_tries=n_retries; data_tries > 0; data_tries--)
 	{
 		for (status_tries=3; status_tries > 0; status_tries--)
@@ -4680,14 +4680,14 @@
 			msg(DBG_INF,"sbp_status: failed after 3 tries\n");
 			break;
 		}
-		
+
 		sbp_read_cmd(req);
 		sbp_sleep(0);
 		if (sbp_data(req) != 0)
 		{
 #if SAFE_MIXED
 			D_S[d].has_data=2; /* is really a data disk */
-#endif SAFE_MIXED
+#endif /* SAFE_MIXED */
 #ifdef DEBUG_GTL
 			printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n",
 				xnr, req, req->sector, req->nr_sectors, jiffies);
@@ -4700,7 +4700,7 @@
  err_done:
 #if OLD_BUSY
 	busy_data=0;
-#endif OLD_BUSY
+#endif /* OLD_BUSY */
 #ifdef DEBUG_GTL
 	printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n",
 		xnr, req, req->sector, req->nr_sectors, jiffies);
@@ -5056,20 +5056,20 @@
 		}
 		SBPCD_STI;
 	}
-	
+
 #if 0
 	if (!success)
-#endif 0
+#endif /* 0 */
 		do
 		{
 			if (fam0LV_drive) cc_ReadStatus();
 #if 1
 			if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i);
-#endif 1
+#endif /* 1 */
 			i=ResponseStatus();  /* builds status_bits, returns orig. status (old) or faked p_success (new) */
 #if 1
 			if (famT_drive)	msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i);
-#endif 1
+#endif /* 1 */
 			if (i<0)
 			{
 				msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", D_S[d].status_bits);
@@ -5105,7 +5105,7 @@
 static int sbpcd_open(struct inode *ip, struct file *fp)
 {
 	int i;
-	
+
 	i = MINOR(ip->i_rdev);
 	if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
 	{
@@ -5114,10 +5114,10 @@
 	}
 	if (fp->f_mode & 2)
 		return -EROFS;
-	
+
 	down(&ioctl_read_sem);
 	switch_drive(i);
-	
+
 	i=cc_ReadError();
 	flags_cmd_out |= f_respo2;
 	cc_ReadStatus(); /* command: give 1-byte status */
@@ -5128,7 +5128,7 @@
 		i=ResponseStatus();
 #if 0
                 sbp_sleep(HZ);
-#endif 0
+#endif /* 0 */
 		i=ResponseStatus();
 	}
 	if (i<0)
@@ -5182,15 +5182,15 @@
 		i=DiskInfo();
 		if (famT_drive)	msg(DBG_TEA,"sbpcd_open: after i=DiskInfo();.\n");
 		if ((D_S[d].ored_ctl_adr&0x40)==0)
-		{		
+		{
 			msg(DBG_INF,"CD contains no data tracks.\n");
 #if SAFE_MIXED
 			D_S[d].has_data=0;
-#endif SAFE_MIXED
+#endif /* SAFE_MIXED */
 		}
 #if SAFE_MIXED
 		else if (D_S[d].has_data<1) D_S[d].has_data=1;
-#endif SAFE_MIXED
+#endif /* SAFE_MIXED */
 	}
 	if (!st_spinning) cc_SpinUp();
 	RETURN_UP(0);
@@ -5202,7 +5202,7 @@
 static void sbpcd_release(struct inode * ip, struct file * file)
 {
 	int i;
-	
+
 	i = MINOR(ip->i_rdev);
 	if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
 	{
@@ -5231,7 +5231,7 @@
 			D_S[d].open_count=0; 
 #if SAFE_MIXED
 			D_S[d].has_data=0;
-#endif SAFE_MIXED
+#endif /* SAFE_MIXED */
 		}
 	}
 	up(&ioctl_read_sem);
@@ -5396,14 +5396,14 @@
 int init_module(void)
 #else
 int SBPCD_INIT(void)
-#endif MODULE
+#endif /* MODULE */
 {
 	int i=0, j=0;
 	int addr[2]={1, CDROM_PORT};
 	int port_index;
-	
+
 	sti();
-	
+
 	msg(DBG_INF,"sbpcd.c %s\n", VERSION);
 #ifndef MODULE
 #if DISTRIBUTION
@@ -5422,11 +5422,11 @@
 		msg(DBG_INF,"with your REAL address.\n");
 		msg(DBG_INF,"= = = = = = = = = = END of WARNING = = = = = == = = =\n");
 	}
-#endif DISTRIBUTION
+#endif /* DISTRIBUTION */
 	sbpcd[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */
 	sbpcd[1]=sbpro_type; /* possibly changed by kernel command line */
-#endif MODULE
-	
+#endif /* MODULE */
+
 	for (port_index=0;port_index<NUM_PROBE;port_index+=2)
 	{
 		addr[1]=sbpcd[port_index];
@@ -5443,7 +5443,7 @@
 		sbpcd_setup(type, addr);
 #if DISTRIBUTION
 		msg(DBG_INF,"Scanning 0x%X (%s)...\n", CDo_command, type);
-#endif DISTRIBUTION
+#endif /* DISTRIBUTION */
 		if (sbpcd[port_index+1]==2)
 		{
 			i=config_spea();
@@ -5451,12 +5451,12 @@
 		}
 #ifdef PATH_CHECK
 		if (check_card(addr[1])) continue;
-#endif PATH_CHECK
+#endif /* PATH_CHECK */
 		i=check_drives();
 		msg(DBG_INI,"check_drives done.\n");
 		if (i>=0) break; /* drive found */
 	} /* end of cycling through the set of possible I/O port addresses */
-	
+
 	if (ndrives==0)
 	{
 		msg(DBG_INF, "No drive found.\n");
@@ -5464,9 +5464,9 @@
 		return -EIO;
 #else
 		goto init_done;
-#endif MODULE
+#endif /* MODULE */
 	}
-	
+
 	if (port_index>0)
           {
             msg(DBG_INF, "You should read linux/Documentation/cdrom/sbpcd\n");
@@ -5474,14 +5474,14 @@
           }
 	check_datarate();
 	msg(DBG_INI,"check_datarate done.\n");
-	
+
 #if 0
 	if (!famL_drive)
 	{
 		OUT(CDo_reset,0);
 		sbp_sleep(HZ);
 	}
-#endif 0
+#endif /* 0 */
 
 	for (j=0;j<NR_SBPCD;j++)
 	{
@@ -5489,7 +5489,7 @@
 		switch_drive(j);
 #if 1
 		if (!famL_drive) cc_DriveReset();
-#endif 0
+#endif /* 0 */
 		if (!st_spinning) cc_SpinUp();
 		D_S[d].sbp_first_frame = -1;  /* First frame in buffer */
 		D_S[d].sbp_last_frame = -1;   /* Last frame in buffer  */
@@ -5500,7 +5500,7 @@
 		D_S[d].f_eject=0;
 #if EJECT
 		if (!fam0_drive) D_S[d].f_eject=1;
-#endif EJECT
+#endif /* EJECT */
 		cc_ReadStatus();
 		i=ResponseStatus();  /* returns orig. status or p_busy_new */
 		if (famT_drive) i=ResponseStatus();  /* returns orig. status or p_busy_new */
@@ -5537,7 +5537,7 @@
 		i=SetSpeed();
 		if (i>=0) D_S[d].CD_changed=1;
 	}
-	
+
 	/*
 	 * Turn on the CD audio channels.
 	 * The addresses are obtained from SOUND_BASE (see sbpcd.h).
@@ -5545,8 +5545,8 @@
 #if SOUND_BASE
 	OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */
 	OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
-#endif SOUND_BASE
-	
+#endif /* SOUND_BASE */
+
 	if (register_blkdev(MAJOR_NR, major_name, &sbpcd_fops) != 0)
 	{
 		msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR);
@@ -5554,20 +5554,20 @@
 		return -EIO;
 #else
 		goto init_done;
-#endif MODULE
+#endif /* MODULE */
 	}
 	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
 	read_ahead[MAJOR_NR] = buffers * (CD_FRAMESIZE / 512);
-	
+
 	request_region(CDo_command,4,major_name);
-	
+
 	for (j=0;j<NR_SBPCD;j++)
 	{
 		if (D_S[j].drv_id==-1) continue;
 		switch_drive(j);
 #if SAFE_MIXED
 		D_S[j].has_data=0;
-#endif SAFE_MIXED
+#endif /* SAFE_MIXED */
 		/*
 		 * allocate memory for the frame buffers
 		 */
@@ -5584,7 +5584,7 @@
 		}
 #ifdef MODULE
 		msg(DBG_INF,"data buffer size: %d frames.\n",buffers);
-#endif MODULE
+#endif /* MODULE */
 		if (D_S[j].sbp_audsiz>0)
 		{
 			D_S[j].aud_buf=(u_char *) vmalloc(D_S[j].sbp_audsiz*CD_FRAMESIZE_RAW);
@@ -5603,15 +5603,15 @@
 #if !(SBPCD_ISSUE-1)
 #ifdef CONFIG_SBPCD2
 	sbpcd2_init();
-#endif CONFIG_SBPCD2
+#endif /* CONFIG_SBPCD2 */
 #ifdef CONFIG_SBPCD3
 	sbpcd3_init();
-#endif CONFIG_SBPCD3
+#endif /* CONFIG_SBPCD3 */
 #ifdef CONFIG_SBPCD4
 	sbpcd4_init();
-#endif CONFIG_SBPCD4
+#endif /* CONFIG_SBPCD4 */
 #endif !(SBPCD_ISSUE-1)
-#endif MODULE
+#endif /* MODULE */
 	return 0;
 }
 /*==========================================================================*/
@@ -5619,14 +5619,14 @@
 void cleanup_module(void)
 {
 	int j;
-	
+
 	if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
 	{
 		msg(DBG_INF, "What's that: can't unregister %s.\n", major_name);
 		return;
 	}
 	release_region(CDo_command,4);
-	
+
 	for (j=0;j<NR_SBPCD;j++)
 	{
 		if (D_S[j].drv_id==-1) continue;
@@ -5635,7 +5635,7 @@
 	}
 	msg(DBG_INF, "%s module released.\n", major_name);
 }
-#endif MODULE
+#endif /* MODULE */
 /*==========================================================================*/
 /*
  * Check if the media has changed in the CD-ROM drive.
diff -u --recursive --new-file linux-2.0.39/drivers/char/lp_m68k.c linux-2.0.40/drivers/char/lp_m68k.c
--- linux-2.0.39/drivers/char/lp_m68k.c	Mon May  6 11:49:43 1996
+++ linux-2.0.40/drivers/char/lp_m68k.c	Mon Aug 20 13:27:26 2001
@@ -182,7 +182,7 @@
 #endif
 {
   unsigned long total_bytes_written = 0;
-  unsigned int flags;
+  unsigned long flags;
   int rc;
   int dev = MINOR(inode->i_rdev);
 
diff -u --recursive --new-file linux-2.0.39/drivers/char/misc.c linux-2.0.40/drivers/char/misc.c
--- linux-2.0.39/drivers/char/misc.c	Thu Jun  4 00:17:47 1998
+++ linux-2.0.40/drivers/char/misc.c	Sat Feb 24 02:22:07 2001
@@ -197,7 +197,7 @@
 		S_IFREG | S_IRUGO, 1, 0, 0,
 		0, NULL /* ops -- default to array */,
 		&proc_misc_read /* get_info */,
-	});	
+	});
 #endif /* PROC_FS */
 #ifdef CONFIG_BUSMOUSE
 	bus_mouse_init();
@@ -220,14 +220,18 @@
 #ifdef CONFIG_SUN_MOUSE
 	sun_mouse_init();
 #endif
-#ifdef CONFIG_SOFT_WATCHDOG
-	watchdog_init();
-#endif
+	/* In 2.0.xx, only the first misc_register() is significant for
+	 * each minor. So we load the hardware watchdogs first, then
+	 * the softdog driver.
+	 */
 #ifdef CONFIG_WDT
 	wdt_init();
 #endif
 #ifdef CONFIG_PCWATCHDOG
 	pcwatchdog_init();
+#endif
+#ifdef CONFIG_SOFT_WATCHDOG
+	watchdog_init();
 #endif
 #ifdef CONFIG_APM
 	apm_bios_init();
diff -u --recursive --new-file linux-2.0.39/drivers/char/vga.c linux-2.0.40/drivers/char/vga.c
--- linux-2.0.39/drivers/char/vga.c	Tue May  7 06:50:53 1996
+++ linux-2.0.40/drivers/char/vga.c	Thu Aug 23 18:49:46 2001
@@ -271,7 +271,7 @@
 	    /* Make sure that the hardware is not blanked */
 	    outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
 	  }
-#endif CONFIG_HGA
+#endif /* CONFIG_HGA */
 
 	if (video_mem_term - video_mem_base < offset + video_screen_size)
 	  offset = 0;	/* strange ... */
diff -u --recursive --new-file linux-2.0.39/drivers/isdn/hisax/elsa_ser.c linux-2.0.40/drivers/isdn/hisax/elsa_ser.c
--- linux-2.0.39/drivers/isdn/hisax/elsa_ser.c	Sun Nov 15 19:32:58 1998
+++ linux-2.0.40/drivers/isdn/hisax/elsa_ser.c	Thu Aug 23 18:56:11 2001
@@ -453,7 +453,7 @@
 			}
 		}
 	}
-#endif 0
+#endif /* 0 */
 }
 #endif
 
diff -u --recursive --new-file linux-2.0.39/drivers/isdn/icn/icn.c linux-2.0.40/drivers/isdn/icn/icn.c
--- linux-2.0.39/drivers/isdn/icn/icn.c	Sun Nov 15 19:32:59 1998
+++ linux-2.0.40/drivers/isdn/icn/icn.c	Mon Aug 20 13:36:28 2001
@@ -772,7 +772,7 @@
 	int left;
 	u_char c;
 	int ch;
-	int flags;
+	unsigned long flags;
 	int i;
 	u_char *p;
 	isdn_ctrl cmd;
diff -u --recursive --new-file linux-2.0.39/drivers/isdn/isdn_common.c linux-2.0.40/drivers/isdn/isdn_common.c
--- linux-2.0.39/drivers/isdn/isdn_common.c	Sun Nov 15 19:32:59 1998
+++ linux-2.0.40/drivers/isdn/isdn_common.c	Mon Aug 20 13:30:08 2001
@@ -391,7 +391,7 @@
 	}
 
 	if (tf) {
-		int flags;
+		unsigned long flags;
 
 		save_flags(flags);
 		cli();
@@ -405,7 +405,7 @@
 void
 isdn_timer_ctrl(int tf, int onoff)
 {
-	int flags;
+	unsigned long flags;
 
 	save_flags(flags);
 	cli();
@@ -2055,7 +2055,7 @@
 void
 cleanup_module(void)
 {
-	int flags;
+	unsigned long flags;
 	int i;
 
 #ifdef CONFIG_ISDN_PPP
diff -u --recursive --new-file linux-2.0.39/drivers/isdn/isdn_net.c linux-2.0.40/drivers/isdn/isdn_net.c
--- linux-2.0.39/drivers/isdn/isdn_net.c	Sun Jun 13 19:21:01 1999
+++ linux-2.0.40/drivers/isdn/isdn_net.c	Mon Aug 20 13:31:41 2001
@@ -777,7 +777,7 @@
 	isdn_net_dev *p = dev->netdev;
 	int anymore = 0;
 	int i;
-	int flags;
+	unsigned long flags;
 	isdn_ctrl cmd;
 
 	while (p) {
@@ -2521,7 +2521,7 @@
 			chidx = p->local.pre_channel;
 		}
 		if (cfg->exclusive > 0) {
-			int flags;
+			unsigned long flags;
 
 			/* If binding is exclusive, try to grab the channel */
 			save_flags(flags);
@@ -2733,7 +2733,7 @@
 	int more = 0;
 	int count = 0;
 	isdn_net_phone *n;
-	int flags;
+	unsigned long flags;
 	int ret;
 
 	if (!p)
@@ -2771,7 +2771,7 @@
 	int inout = phone->outgoing & 1;
 	isdn_net_phone *n;
 	isdn_net_phone *m;
-	int flags;
+	unsigned long flags;
 
 	if (p) {
 		save_flags(flags);
@@ -2807,7 +2807,7 @@
 {
 	isdn_net_phone *n;
 	isdn_net_phone *m;
-	int flags;
+	unsigned long flags;
 	int i;
 
 	save_flags(flags);
@@ -2856,7 +2856,7 @@
 static int
 isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
 {
-	int flags;
+	unsigned long flags;
 
 	save_flags(flags);
 	cli();
@@ -2942,7 +2942,7 @@
 int
 isdn_net_rmall(void)
 {
-	int flags;
+	unsigned long flags;
 	int ret;
 
 	/* Walk through netdev-chain */
diff -u --recursive --new-file linux-2.0.39/drivers/isdn/isdnloop/isdnloop.c linux-2.0.40/drivers/isdn/isdnloop/isdnloop.c
--- linux-2.0.39/drivers/isdn/isdnloop/isdnloop.c	Sun Nov 15 19:33:01 1998
+++ linux-2.0.40/drivers/isdn/isdnloop/isdnloop.c	Mon Aug 20 13:37:48 2001
@@ -318,7 +318,7 @@
 	int left;
 	u_char c;
 	int ch;
-	int flags;
+	unsigned long flags;
 	u_char *p;
 	isdn_ctrl cmd;
 
diff -u --recursive --new-file linux-2.0.39/drivers/net/atp.c linux-2.0.40/drivers/net/atp.c
--- linux-2.0.39/drivers/net/atp.c	Tue Aug 12 22:21:12 1997
+++ linux-2.0.40/drivers/net/atp.c	Mon Aug 20 13:39:49 2001
@@ -537,7 +537,7 @@
 	} else {
 		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 		unsigned char *buf = skb->data;
-		int flags;
+		unsigned long flags;
 
 		/* Disable interrupts by writing 0x00 to the Interrupt Mask Register.
 		   This sequence must not be interrupted by an incoming packet. */
diff -u --recursive --new-file linux-2.0.39/drivers/net/auto_irq.c linux-2.0.40/drivers/net/auto_irq.c
--- linux-2.0.39/drivers/net/auto_irq.c	Thu Jun  4 00:17:47 1998
+++ linux-2.0.40/drivers/net/auto_irq.c	Mon Oct  8 14:06:31 2001
@@ -24,6 +24,20 @@
 
     The idea of using the setup timeout to filter out bogus IRQs came from
     the serial driver.
+
+Update 2000-09-04, by Michael Deutschmann <michael@talamasca.ocis.net>:
+    
+    The code used to rely upon freeing an IRQ handler, within the same 
+    handler.  This is not correct -- it causes the kernel to free a 
+    structure that is still in use.  
+
+    Because the read-after-free takes place with interrupts off, it's
+    probably impossible for anything else to reallocate the memory and 
+    trash the structure -- but in SADISTIC_KMALLOC mode it will crash 
+    every time.
+
+    I've fixed the code so it doesn't do that.
+
 */
 
 
@@ -52,13 +66,14 @@
 
 static void autoirq_probe(int irq, void *dev_id, struct pt_regs * regs)
 {
+	/* Only act on first instance of this IRQ.  We can't free the 
+	 * handler from here, so we just make sure second trips do nothing.
+	 */
+	if (test_bit(irq, (void *)&irq_bitmap)) 
+            return; 
+
 	irq_number = irq;
 	set_bit(irq, (void *)&irq_bitmap);	/* irq_bitmap |= 1 << irq; */
-	/* This code used to disable the irq. However, the interrupt stub
-	 * would then re-enable the interrupt with (potentially) disastrous
-	 * consequences
-	 */
-	free_irq(irq, dev_id);
 	return;
 }
 
@@ -101,8 +116,6 @@
 	while (timeout > jiffies  &&  --boguscount > 0)
 		if (irq_number)
 			break;
-
-	irq_handled &= ~irq_bitmap;	/* This eliminates the already reset handlers */
 
 	/* Retract the irq handlers that we installed. */
 	for (i = 0; i < 16; i++) {
diff -u --recursive --new-file linux-2.0.39/drivers/net/tulip.c linux-2.0.40/drivers/net/tulip.c
--- linux-2.0.39/drivers/net/tulip.c	Sun Jun 13 19:21:02 1999
+++ linux-2.0.40/drivers/net/tulip.c	Thu Aug 23 18:49:34 2001
@@ -296,7 +296,7 @@
 	0x125B, 0x1400, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
   {0},
 };
-#endif CARD_BUS
+#endif /* CARD_BUS */
 
 /* This table use during operation for capabilities and media timer. */
 
diff -u --recursive --new-file linux-2.0.39/drivers/sbus/char/sunserial.c linux-2.0.40/drivers/sbus/char/sunserial.c
--- linux-2.0.39/drivers/sbus/char/sunserial.c	Mon May  6 11:26:09 1996
+++ linux-2.0.40/drivers/sbus/char/sunserial.c	Mon Aug 20 13:43:45 2001
@@ -904,7 +904,8 @@
 void kbd_put_char(unsigned char ch)
 {
 	struct sun_zschannel *chan = zs_kbdchan;
-	int flags, loops = 0;
+	int loops = 0;
+	unsigned long flags;
 
 	if(!chan)
 		return;
@@ -923,7 +924,8 @@
 void mouse_put_char(char ch)
 {
 	struct sun_zschannel *chan = zs_mousechan;
-	int flags, loops = 0;
+	int loops = 0;
+	unsigned long flags;
 
 	if(!chan)
 		return;
@@ -944,7 +946,8 @@
 static void rs_put_char(char ch)
 {
 	struct sun_zschannel *chan = zs_conschan;
-	int flags, loops = 0;
+	int loops = 0;
+	unsigned long flags;
 
 	if(!chan)
 		return;
@@ -1900,8 +1903,9 @@
 /* rs_init inits the driver */
 int rs_init(void)
 {
-	int chip, channel, i, flags;
+	int chip, channel, i;
 	struct sun_serial *info;
+	unsigned long flags;
 
 #if CONFIG_AP1000
         printk("not doing rs_init()\n");
@@ -1917,7 +1921,7 @@
 
 	/* Initialize the tty_driver structure */
 	/* SPARC: Not all of this is exactly right for us. */
-	
+
 	memset(&serial_driver, 0, sizeof(struct tty_driver));
 	serial_driver.magic = TTY_DRIVER_MAGIC;
 	serial_driver.name = "ttyS";
diff -u --recursive --new-file linux-2.0.39/drivers/scsi/NCR5380.h linux-2.0.40/drivers/scsi/NCR5380.h
--- linux-2.0.39/drivers/scsi/NCR5380.h	Thu Jun  4 00:17:48 1998
+++ linux-2.0.40/drivers/scsi/NCR5380.h	Thu Aug 23 18:49:54 2001
@@ -368,6 +368,6 @@
 }
 #endif /* defined(i386) || defined(__alpha__) */
 #endif /* defined(REAL_DMA)  */
-#endif __KERNEL_
+#endif /* __KERNEL_ */
 #endif /* ndef ASM */
 #endif /* NCR5380_H */
diff -u --recursive --new-file linux-2.0.39/drivers/scsi/NCR53c406a.c linux-2.0.40/drivers/scsi/NCR53c406a.c
--- linux-2.0.39/drivers/scsi/NCR53c406a.c	Mon Jul 13 22:47:32 1998
+++ linux-2.0.40/drivers/scsi/NCR53c406a.c	Thu Aug 23 18:52:42 2001
@@ -222,8 +222,8 @@
     (void *)0xc8000
 };
 #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
-#endif USE_BIOS
-		       
+#endif /* USE_BIOS */
+
 /* possible i/o port addresses */
 static unsigned short ports[] = { 0x230, 0x330 };
 #define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
@@ -244,7 +244,7 @@
     { "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82 },
 };
 #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
-#endif USE_BIOS
+#endif /* USE_BIOS */
 
 /* ============================================================ */
 
@@ -345,10 +345,10 @@
     clear_dma_ff(dma_chan);
     tmp = get_dma_residue(dma_chan);
     restore_flags(flags);
-    
+
     return tmp;
 }
-#endif USE_DMA
+#endif /* USE_DMA */
 
 #if USE_PIO
 static __inline__ int NCR53c406a_pio_read(unsigned char *request, 
@@ -357,14 +357,14 @@
     int	i;
     int	len;	/* current scsi fifo size */
     unsigned long flags = 0;
-    
+
     REG1;
     while (reqlen) {
         i = inb(PIO_STATUS);
         /*    VDEB(printk("pio_status=%x\n", i)); */
         if (i & 0x80) 
             return 0;
-        
+
         switch( i & 0x1e ) {
         default:
         case 0x10:
@@ -456,15 +456,15 @@
     }
     return 0;
 }
-#endif USE_PIO
+#endif /* USE_PIO */
 
-int 
+int
 NCR53c406a_detect(Scsi_Host_Template * tpnt){
     struct Scsi_Host *shpnt;
 #ifndef PORT_BASE
     int i;
 #endif
-    
+
 #if USE_BIOS
     int ii, jj;
     bios_base = 0;
@@ -475,15 +475,15 @@
                        (void *) signatures[jj].signature,
                        (int) signatures[jj].sig_length))
                 bios_base=addresses[ii];
-    
+
     if(!bios_base){
         printk("NCR53c406a: BIOS signature not found\n");
         return 0;
     }
-    
+
     DEB(printk("NCR53c406a BIOS found at %X\n", (unsigned int) bios_base););
-#endif USE_BIOS
-    
+#endif /* USE_BIOS */
+
 #ifdef PORT_BASE
     if (check_region(port_base, 0x10)) /* ports already snatched */
         port_base = 0;
@@ -511,18 +511,18 @@
             }
         }
     }
-#endif PORT_BASE
-    
+#endif /* PORT_BASE */
+
     if(!port_base){		/* no ports found */
         printk("NCR53c406a: no available ports found\n");
         return 0;
     }
-    
+
     DEB(printk("NCR53c406a detected\n"));
-    
+
     calc_port_addr();
     chip_init();
-    
+
 #ifndef IRQ_LEV
     if (irq_level < 0) {		/* LILO override if >= 0*/
         irq_level=irq_probe();
@@ -532,10 +532,10 @@
         }
     }
 #endif
-    
+
     DEB(printk("NCR53c406a: using port_base %x\n", port_base));
     request_region(port_base, 0x10, "NCR53c406a");
-    
+
     if(irq_level > 0) {
         if(request_irq(irq_level, NCR53c406a_intr, 0, "NCR53c406a", NULL)){
             printk("NCR53c406a: unable to allocate IRQ %d\n", irq_level);
@@ -550,26 +550,26 @@
 #if USE_DMA
         printk("NCR53c406a: No interrupts found and DMA mode defined. Giving up.\n");
         return 0;
-#endif USE_DMA
+#endif /* USE_DMA */
     }
     else {
         DEB(printk("NCR53c406a: Shouldn't get here!\n"));
         return 0;
     }
-    
+
 #if USE_DMA
     dma_chan = DMA_CHAN;
     if(request_dma(dma_chan, "NCR53c406a") != 0){
         printk("NCR53c406a: unable to allocate DMA channel %d\n", dma_chan);
         return 0;
     }
-    
+
     DEB(printk("Allocated DMA channel %d\n", dma_chan));
-#endif USE_DMA 
-    
+#endif /* USE_DMA */
+
     tpnt->present = 1;
     tpnt->proc_dir = &proc_scsi_NCR53c406a;
-    
+
     shpnt = scsi_register(tpnt, 0);
     shpnt->irq = irq_level;
     shpnt->io_port = port_base;
@@ -796,9 +796,9 @@
     printk("\n");
 #else
     printk(", pio=%02x\n", pio_status);
-#endif USE_DMA
-#endif NCR53C406A_DEBUG
-    
+#endif /* USE_DMA */
+#endif /* NCR53C406A_DEBUG */
+
     if(int_reg & 0x80){         /* SCSI reset intr */
         rtrc(3);
         DEB(printk("NCR53c406a: reset intr received\n"));
@@ -807,7 +807,7 @@
         current_SC->scsi_done(current_SC);
         return;
     }
-    
+
 #if USE_PIO
     if(pio_status & 0x80) {
         printk("NCR53C406A: Warning: PIO error!\n");
@@ -816,8 +816,8 @@
         current_SC->scsi_done(current_SC);
         return;
     }
-#endif USE_PIO
-    
+#endif /* USE_PIO */
+
     if(status & 0x20) {		/* Parity error */
         printk("NCR53c406a: Warning: parity error!\n");
         current_SC->SCp.phase = idle;
@@ -861,7 +861,7 @@
 #if USE_DMA			/* No s/g support for DMA */
             NCR53c406a_dma_write(current_SC->request_buffer, 
                                  current_SC->request_bufflen);
-#endif USE_DMA
+#endif /* USE_DMA */
             outb(TRANSFER_INFO | DMA_OP, CMD_REG); 
 #if USE_PIO
             if (!current_SC->use_sg) /* Don't use scatter-gather */
@@ -876,10 +876,10 @@
                 }
             }
             REG0;
-#endif USE_PIO
+#endif /* USE_PIO */
         }
         break;
-        
+
     case 0x01:			/* DATA-IN */
         if(int_reg & 0x10){     /* Target requesting info transfer */
             rtrc(6);
@@ -890,7 +890,7 @@
 #if USE_DMA			/* No s/g support for DMA */
             NCR53c406a_dma_read(current_SC->request_buffer, 
                                 current_SC->request_bufflen);
-#endif USE_DMA
+#endif /* USE_DMA */
             outb(TRANSFER_INFO | DMA_OP, CMD_REG); 
 #if USE_PIO
             if (!current_SC->use_sg) /* Don't use scatter-gather */
@@ -905,10 +905,10 @@
                 }
             }
             REG0;
-#endif USE_PIO
+#endif /* USE_PIO */
         }
         break;
-        
+
     case 0x02:			/* COMMAND */
         current_SC->SCp.phase = command_ph;
         printk("NCR53c406a: Warning: Unknown interrupt occurred in command phase!\n");
@@ -978,17 +978,17 @@
         probe_irq_off(irqs);
         return -1;
     }
-    
+
     irq = probe_irq_off(irqs);
-    
+
     /* Kick the chip */
     outb(CHIP_RESET, CMD_REG);
     outb(SCSI_NOP, CMD_REG);
     chip_init();
-    
+
     return irq;
 }
-#endif IRQ_LEV
+#endif /* IRQ_LEV */
 
 static void chip_init()
 {
@@ -999,12 +999,12 @@
     outb(0x01, PIO_STATUS);
 #endif
     outb(0x00, PIO_FLAG);
-    
+
     outb(C4_IMG, CONFIG4);	/* REG0; */
     outb(C3_IMG, CONFIG3);
     outb(C2_IMG, CONFIG2);
     outb(C1_IMG, CONFIG1);
-    
+
     outb(0x05, CLKCONV);        /* clock conversion factor */
     outb(0x9C, SRTIMOUT);       /* Selection timeout */
     outb(0x05, SYNCPRD);        /* Synchronous transfer period */
diff -u --recursive --new-file linux-2.0.39/drivers/scsi/aha152x.c linux-2.0.40/drivers/scsi/aha152x.c
--- linux-2.0.39/drivers/scsi/aha152x.c	Sun Nov 15 19:33:07 1998
+++ linux-2.0.40/drivers/scsi/aha152x.c	Mon Aug 20 14:00:37 2001
@@ -1536,7 +1536,7 @@
 void aha152x_intr(int irqno, void *dev_id, struct pt_regs * regs)
 {
   struct Scsi_Host *shpnt = aha152x_host[irqno-IRQ_MIN];
-  unsigned int flags;
+  unsigned long flags;
   int done=0, phase;
 
 #if defined(DEBUG_RACE)
diff -u --recursive --new-file linux-2.0.39/drivers/scsi/aha1542.c linux-2.0.40/drivers/scsi/aha1542.c
--- linux-2.0.39/drivers/scsi/aha1542.c	Sun Jun 13 19:21:02 1999
+++ linux-2.0.40/drivers/scsi/aha1542.c	Mon Aug 20 14:01:35 2001
@@ -356,7 +356,7 @@
     void (*my_done)(Scsi_Cmnd *) = NULL;
     int errstatus, mbi, mbo, mbistatus;
     int number_serviced;
-    unsigned int flags;
+    unsigned long flags;
     struct Scsi_Host * shost;
     Scsi_Cmnd * SCtmp;
     int flag;
diff -u --recursive --new-file linux-2.0.39/drivers/scsi/aic7xxx.c linux-2.0.40/drivers/scsi/aic7xxx.c
--- linux-2.0.39/drivers/scsi/aic7xxx.c	Sun Jun 13 19:21:02 1999
+++ linux-2.0.40/drivers/scsi/aic7xxx.c	Thu Aug 23 18:50:05 2001
@@ -9455,7 +9455,7 @@
       } /* while(pdev=....) */
     } /* for PCI_DEVICES */
   } /* PCI BIOS present */
-#endif CONFIG_PCI
+#endif /* CONFIG_PCI */
   /*
    * Now, we re-order the probed devices by BIOS address and BUS class.
    * In general, we follow this algorithm to make the adapters show up
diff -u --recursive --new-file linux-2.0.39/drivers/scsi/pci2000.c linux-2.0.40/drivers/scsi/pci2000.c
--- linux-2.0.39/drivers/scsi/pci2000.c	Thu Sep  7 03:06:15 2000
+++ linux-2.0.40/drivers/scsi/pci2000.c	Wed Oct  3 17:02:47 2001
@@ -53,7 +53,9 @@
 #include "pci2000.h"
 #include "psi_roy.h"
 
-#include<linux/stat.h>
+#include "pci2220i.h"
+
+#include <linux/stat.h>
 
 struct proc_dir_entry Proc_Scsi_Pci2000 =
 	{ PROC_SCSI_PCI2000, 7, "pci2000", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
diff -u --recursive --new-file linux-2.0.39/drivers/scsi/ultrastor.c linux-2.0.40/drivers/scsi/ultrastor.c
--- linux-2.0.39/drivers/scsi/ultrastor.c	Wed Aug 13 05:27:06 1997
+++ linux-2.0.40/drivers/scsi/ultrastor.c	Mon Aug 20 14:06:03 2001
@@ -333,7 +333,7 @@
 {
   static char fmt[80] = "abort %d (%x); MSCP free pool: %x;";
   register int i;
-  int flags;
+  unsigned long flags;
   save_flags(flags);
   cli();
 
@@ -681,7 +681,7 @@
     int mscp_index;
 #endif
     unsigned int status;
-    int flags;
+    unsigned long flags;
 
     /* Next test is for debugging; "can't happen" */
     if ((config.mscp_free & ((1U << ULTRASTOR_MAX_CMDS) - 1)) == 0)
@@ -853,7 +853,7 @@
       {
 	int port0 = (config.slot << 12) | 0xc80;
 	int i;
-	int flags;
+	unsigned long flags;
 	save_flags(flags);
 	cli();
 	strcpy(out, "OGM %d:%x ICM %d:%x ports:  ");
@@ -879,7 +879,7 @@
     if (config.slot ? inb(config.icm_address - 1) == 2 :
 	(inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1))
       {
-	int flags;
+	unsigned long flags;
 	save_flags(flags);
 	printk("Ux4F: abort while completed command pending\n");
 	restore_flags(flags);
@@ -901,7 +901,7 @@
        and the interrupt handler will call done.  */
     if (config.slot && inb(config.ogm_address - 1) == 0)
       {
-	int flags;
+	unsigned long flags;
 
 	save_flags(flags);
 	cli();
@@ -953,7 +953,7 @@
 
 int ultrastor_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
 {
-    int flags;
+    unsigned long flags;
     register int i;
 #if (ULTRASTOR_DEBUG & UD_RESET)
     printk("US14F: reset: called\n");
diff -u --recursive --new-file linux-2.0.39/drivers/sound/gus_wave.c linux-2.0.40/drivers/sound/gus_wave.c
--- linux-2.0.39/drivers/sound/gus_wave.c	Wed Aug 21 08:18:09 1996
+++ linux-2.0.40/drivers/sound/gus_wave.c	Mon Aug 20 16:55:55 2001
@@ -545,7 +545,7 @@
 {
   unsigned        vol, prev_vol, phase;
   unsigned char   rate;
-  long int        flags;
+  unsigned long  flags;
 
   if (voices[voice].mode & WAVE_SUSTAIN_ON && voices[voice].env_phase == 2)
     {
@@ -618,7 +618,7 @@
 }
 
 static void
-start_release (int voice, long int flags)
+start_release (int voice, unsigned long flags)
 {
   if (gus_read8 (0x00) & 0x03)
     return;			/* Voice already stopped */
@@ -639,7 +639,7 @@
 gus_voice_fade (int voice)
 {
   int             instr_no = sample_map[voice], is16bits;
-  long int        flags;
+  unsigned long   flags;
 
   save_flags (flags);
   cli ();
@@ -1581,7 +1581,7 @@
 static int
 guswave_start_note (int dev, int voice, int note_num, int volume)
 {
-  long int        flags;
+  unsigned long   flags;
   int             mode;
   int             ret_val = 0;
 
diff -u --recursive --new-file linux-2.0.39/fs/buffer.c linux-2.0.40/fs/buffer.c
--- linux-2.0.39/fs/buffer.c	Sun Nov 15 19:33:11 1998
+++ linux-2.0.40/fs/buffer.c	Wed Sep 12 15:29:46 2001
@@ -99,7 +99,7 @@
 
 /* These are the min and max parameter values that we will allow to be assigned */
 int bdflush_min[N_PARAM] = {  0,  10,    5,   25,  0,   100,   100, 1, 1};
-int bdflush_max[N_PARAM] = {100,5000, 2000, 2000,100, 60000, 60000, 2047, 5};
+int bdflush_max[N_PARAM] = {100, 5000, 2000, 2000, 100, 60000, 60000, 2047, 5};
 
 /*
  * Rewrote the wait-routines to use the "new" wait-queue functionality,
@@ -266,7 +266,7 @@
 		return -EBADF;
 	if (!file->f_op || !file->f_op->fsync)
 		return -EINVAL;
-	if (file->f_op->fsync(inode,file))
+	if (file->f_op->fsync(inode, file))
 		return -EIO;
 	return 0;
 }
@@ -281,7 +281,7 @@
 	if (!file->f_op || !file->f_op->fsync)
 		return -EINVAL;
 	/* this needs further work, at the moment it is identical to fsync() */
-	if (file->f_op->fsync(inode,file))
+	if (file->f_op->fsync(inode, file))
 		return -EIO;
 	return 0;
 }
@@ -311,8 +311,8 @@
 	}
 }
 
-#define _hashfn(dev,block) (((unsigned)(HASHDEV(dev)^block))&HASH_MASK)
-#define hash(dev,block) hash_table[_hashfn(dev,block)]
+#define _hashfn(dev, block) (((unsigned)(HASHDEV(dev)^block))&HASH_MASK)
+#define hash(dev, block) hash_table[_hashfn(dev, block)]
 
 static inline void remove_from_hash_queue(struct buffer_head * bh)
 {
@@ -320,8 +320,8 @@
 		bh->b_next->b_prev = bh->b_prev;
 	if (bh->b_prev)
 		bh->b_prev->b_next = bh->b_next;
-	if (hash(bh->b_dev,bh->b_blocknr) == bh)
-		hash(bh->b_dev,bh->b_blocknr) = bh->b_next;
+	if (hash(bh->b_dev, bh->b_blocknr) == bh)
+		hash(bh->b_dev, bh->b_blocknr) = bh->b_next;
 	bh->b_next = bh->b_prev = NULL;
 }
 
@@ -440,17 +440,17 @@
 	bh->b_next = NULL;
 	if (!(bh->b_dev))
 		return;
-	bh->b_next = hash(bh->b_dev,bh->b_blocknr);
-	hash(bh->b_dev,bh->b_blocknr) = bh;
+	bh->b_next = hash(bh->b_dev, bh->b_blocknr);
+	hash(bh->b_dev, bh->b_blocknr) = bh;
 	if (bh->b_next)
 		bh->b_next->b_prev = bh;
 }
 
 static inline struct buffer_head * find_buffer(kdev_t dev, int block, int size)
-{		
+{
 	struct buffer_head * tmp;
 
-	for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
+	for (tmp = hash(dev, block) ; tmp != NULL ; tmp = tmp->b_next)
 		if (tmp->b_blocknr == block && tmp->b_dev == dev)
 			if (tmp->b_size == size)
 				return tmp;
@@ -479,7 +479,7 @@
 	struct buffer_head * bh;
 
 	for (;;) {
-		if (!(bh=find_buffer(dev,block,size)))
+		if (!(bh=find_buffer(dev, block, size)))
 			return NULL;
 		bh->b_count++;
 		wait_on_buffer(bh);
@@ -568,26 +568,26 @@
 
 	if (!bh)
 		goto no_candidate;
-	
+
 	for (; (*list_len) > 0; bh = bh->b_next_free, (*list_len)--) {
 		if (size != bh->b_size) {
 			/* this provides a mechanism for freeing blocks
 			   of other sizes, this is necessary now that we
 			   no longer have the lav code. */
-			try_to_free_buffer(bh,&bh,1);
+			try_to_free_buffer(bh, &bh, 1);
 			if (!bh)
 				break;
 			lookahead = 7;
 			continue;
 		}
-		else if (buffer_locked(bh) && 
+		else if (buffer_locked(bh) &&
 			 (bh->b_list == BUF_LOCKED || bh->b_list == BUF_LOCKED1)) {
 			if (!--lookahead) {
 				(*list_len) = 0;
 				goto no_candidate;
 			}
 		}
-		else if (can_reclaim(bh,size))
+		else if (can_reclaim(bh, size))
 			return bh;
 	}
 
@@ -602,7 +602,7 @@
 		kfree(bh);
 		return;
 	}
-	memset(bh,0,sizeof(*bh));
+	memset(bh, 0, sizeof(*bh));
 	nr_unused_buffer_heads++;
 	bh->b_next_free = unused_list;
 	unused_list = bh;
@@ -707,15 +707,15 @@
 			needed -= bh->b_size;
 			buffers[i]--;
 			if(buffers[i] == 0) candidate[i] = NULL;
-		
-			if (candidate[i] && !can_reclaim(candidate[i],size))
-				candidate[i] = find_candidate(candidate[i],&buffers[i], size);
+
+			if (candidate[i] && !can_reclaim(candidate[i], size))
+				candidate[i] = find_candidate(candidate[i], &buffers[i], size);
 		}
 		goto repeat;
 	}
 
 	/* Too bad, that was not enough. Try a little harder to grow some. */
-	
+
 	if (nr_free_pages > limit) {
 		if (grow_buffers(GFP_BUFFER, size)) {
 			needed -= PAGE_SIZE;
@@ -806,7 +806,7 @@
 refill:
 	allow_interrupts();
 	refill_freelist(size);
-	if (!find_buffer(dev,block,size))
+	if (!find_buffer(dev, block, size))
 		goto get_free;
 	goto repeat;
 }
@@ -946,29 +946,29 @@
 	if (pos >= filesize)
 		return NULL;
 
-	if (block < 0 || !(bh = getblk(dev,block,bufsize)))
+	if (block < 0 || !(bh = getblk(dev, block, bufsize)))
 		return NULL;
 
 	index = BUFSIZE_INDEX(bh->b_size);
 
 	if (buffer_uptodate(bh))
-		return(bh);   
+		return(bh);
 	else ll_rw_block(READ, 1, &bh);
 
 	blocks = (filesize - pos) >> (9+index);
 
 	if (blocks < (read_ahead[MAJOR(dev)] >> index))
 		blocks = read_ahead[MAJOR(dev)] >> index;
-	if (blocks > NBUF) 
+	if (blocks > NBUF)
 		blocks = NBUF;
 
-/*	if (blocks) printk("breada (new) %d blocks\n",blocks); */
+/*	if (blocks) printk("breada (new) %d blocks\n", blocks); */
 
 
 	bhlist[0] = bh;
 	j = 1;
 	for(i=1; i<blocks; i++) {
-		bh = getblk(dev,block+i,bufsize);
+		bh = getblk(dev, block+i, bufsize);
 		if (buffer_uptodate(bh)) {
 			brelse(bh);
 			break;
@@ -1020,7 +1020,7 @@
 		/* we now use kmalloc() here instead of gfp as we want
                    to be able to easily release buffer heads - they
                    took up quite a bit of memory (tridge) */
-		bh = (struct buffer_head *) kmalloc(sizeof(*bh),GFP_IO);
+		bh = (struct buffer_head *) kmalloc(sizeof(*bh), GFP_IO);
 		if (bh) {
 			put_unused_buffer_head(bh);
 			nr_buffer_heads++;
@@ -1373,7 +1373,7 @@
 	int isize;
 
 	if ((size & 511) || (size > PAGE_SIZE)) {
-		printk("VFS: grow_buffers: size = %d\n",size);
+		printk("VFS: grow_buffers: size = %d\n", size);
 		return 0;
 	}
 
@@ -1477,9 +1477,9 @@
 	int nlist;
 	static char *buf_types[NR_LIST] = {"CLEAN","LOCKED","LOCKED1","DIRTY"};
 
-	printk("Buffer memory:   %6dkB\n",buffermem>>10);
-	printk("Buffer heads:    %6d\n",nr_buffer_heads);
-	printk("Buffer blocks:   %6d\n",nr_buffers);
+	printk("Buffer memory:   %6dkB\n", buffermem>>10);
+	printk("Buffer heads:    %6d\n", nr_buffer_heads);
+	printk("Buffer blocks:   %6d\n", nr_buffers);
 
 	for(nlist = 0; nlist < NR_LIST; nlist++) {
 	  found = locked = dirty = used = lastused = protected = 0;
@@ -1515,7 +1515,7 @@
 	hash_table = (struct buffer_head **)vmalloc(NR_HASH*sizeof(struct buffer_head *));
 	if (!hash_table)
 		panic("Failed to allocate buffer hash table\n");
-	memset(hash_table,0,NR_HASH*sizeof(struct buffer_head *));
+	memset(hash_table, 0, NR_HASH*sizeof(struct buffer_head *));
 
 	lru_list[BUF_CLEAN] = 0;
 	grow_buffers(GFP_KERNEL, BLOCK_SIZE);
@@ -1577,7 +1577,7 @@
 		allow_interrupts();
 
 		bh = lru_list[nlist];
-		if(bh) 
+		if (bh)
 			 for (i = nr_buffers_type[nlist]; i-- > 0; bh = next) {
 				 /* We may have stalled while waiting for I/O to complete. */
 				 if(bh->b_list != nlist) goto repeat;
@@ -1681,7 +1681,7 @@
 	/*
 	 *	We have a bare-bones task_struct, and really should fill
 	 *	in a few more things so "top" and /proc/2/{exe,root,cwd}
-	 *	display semi-sane things. Not real crucial though...  
+	 *	display semi-sane things. Not real crucial though...
 	 */
 
 	current->session = 1;
@@ -1748,15 +1748,14 @@
 					  ndirty++;
 					  bh->b_flushtime = 0;
 					  if (major == LOOP_MAJOR) {
-						  ll_rw_block(wrta_cmd,1, &bh);
+						  ll_rw_block(wrta_cmd, 1, &bh);
 						  wrta_cmd = WRITEA;
 						  if (buffer_dirty(bh))
 							  --ndirty;
-					  }
-					  else
-					  ll_rw_block(WRITE, 1, &bh);
+					  } else
+						  ll_rw_block(WRITE, 1, &bh);
 #ifdef DEBUG
-					  if(nlist != BUF_DIRTY) ncount++;
+					  if (nlist != BUF_DIRTY) ncount++;
 #endif
 					  bh->b_count--;
 					  next->b_count--;
diff -u --recursive --new-file linux-2.0.39/fs/exec.c linux-2.0.40/fs/exec.c
--- linux-2.0.39/fs/exec.c	Tue Apr 25 16:16:37 2000
+++ linux-2.0.40/fs/exec.c	Sat Mar  3 16:45:30 2001
@@ -497,8 +497,9 @@
 	int ch;
 	char * name;
 
+	bprm->dumpable = 0;
 	if (current->euid == current->uid && current->egid == current->gid)
-		current->dumpable = 1;
+		bprm->dumpable = 1;
 	name = bprm->filename;
 	for (i=0; (ch = *(name++)) != '\0';) {
 		if (ch == '/')
@@ -515,9 +516,9 @@
 
 	flush_thread();
 
-	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 
-	    permission(bprm->inode,MAY_READ))
-		current->dumpable = 0;
+	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
+	    permission(bprm->inode, MAY_READ))
+		bprm->dumpable = 0;
 
 	flush_old_signals(current->sig);
 	flush_old_files(current->files);
@@ -707,6 +708,7 @@
 int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs)
 {
 	struct linux_binprm bprm;
+	int was_dumpable;
 	int retval;
 	int i;
 
@@ -726,6 +728,9 @@
 	if ((bprm.envc = count(envp, sizeof(char *), bprm.p)) < 0)
 		return bprm.envc;
 
+	was_dumpable = current->dumpable;
+	current->dumpable = 0;
+
 	retval = prepare_binprm(&bprm);
 	
 	if(retval>=0) {
@@ -739,14 +744,20 @@
 
 	if(retval>=0)
 		retval = search_binary_handler(&bprm,regs);
-	if(retval>=0)
+
+	if(retval>=0) {
 		/* execve success */
+		current->dumpable = bprm.dumpable;
 		return retval;
+	}
 
 	/* Something went wrong, return the inode and free the argument pages*/
 	if(!bprm.dont_iput)
 		iput(bprm.inode);
 	for (i=0 ; i<MAX_ARG_PAGES ; i++)
 		free_page(bprm.page[i]);
+
+	current->dumpable = was_dumpable;
+
 	return(retval);
 }
diff -u --recursive --new-file linux-2.0.39/fs/ext2/dir.c linux-2.0.40/fs/ext2/dir.c
--- linux-2.0.39/fs/ext2/dir.c	Fri Jan 21 16:17:50 2000
+++ linux-2.0.40/fs/ext2/dir.c	Sun Sep 23 14:52:15 2001
@@ -145,7 +145,7 @@
 					brelse (bha[i]);
 			}
 		}
-		
+
 revalidate:
 		/* If the dir block has changed since the last call to
 		 * readdir(2), then we might be pointing to an invalid
@@ -153,7 +153,7 @@
 		 * to make sure. */
 		if (filp->f_version != inode->i_version) {
 			for (i = 0; i < sb->s_blocksize && i < offset; ) {
-				de = (struct ext2_dir_entry *) 
+				de = (struct ext2_dir_entry_2 *)
 					(bh->b_data + i);
 				/* It's too expensive to do a full
 				 * dirent test each time round this
@@ -170,8 +170,8 @@
 				| offset;
 			filp->f_version = inode->i_version;
 		}
-		
-		while (!error && filp->f_pos < inode->i_size 
+
+		while (!error && filp->f_pos < inode->i_size
 		       && offset < sb->s_blocksize) {
 			de = (struct ext2_dir_entry_2 *) (bh->b_data + offset);
 			if (!ext2_check_dir_entry ("ext2_readdir", inode, de,
diff -u --recursive --new-file linux-2.0.39/fs/ext2/super.c linux-2.0.40/fs/ext2/super.c
--- linux-2.0.39/fs/ext2/super.c	Tue Jul 11 18:41:19 2000
+++ linux-2.0.40/fs/ext2/super.c	Sun Sep 23 14:53:01 2001
@@ -711,7 +711,6 @@
 void ext2_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
 {
 	unsigned long overhead;
-	unsigned long overhead_per_group;
 	struct statfs tmp;
 	int ngroups, i;
 
diff -u --recursive --new-file linux-2.0.39/fs/ext2/truncate.c linux-2.0.40/fs/ext2/truncate.c
--- linux-2.0.39/fs/ext2/truncate.c	Mon Dec 11 05:56:35 1995
+++ linux-2.0.40/fs/ext2/truncate.c	Tue Aug 21 11:24:22 2001
@@ -93,9 +93,9 @@
 		if (free_count == 0) {
 			block_to_free = tmp;
 			free_count++;
-		} else if (free_count > 0 && block_to_free == tmp - free_count)
+		} else if (free_count > 0 && block_to_free == tmp - free_count) {
 			free_count++;
-		else {
+		} else {
 			ext2_free_blocks (inode, block_to_free, free_count);
 			block_to_free = tmp;
 			free_count = 1;
@@ -160,9 +160,9 @@
 		if (free_count == 0) {
 			block_to_free = tmp;
 			free_count++;
-		} else if (free_count > 0 && block_to_free == tmp - free_count)
+		} else if (free_count > 0 && block_to_free == tmp - free_count) {
 			free_count++;
-		else {
+		} else {
 			ext2_free_blocks (inode, block_to_free, free_count);
 			block_to_free = tmp;
 			free_count = 1;
@@ -177,16 +177,17 @@
 	for (i = 0; i < addr_per_block; i++)
 		if (*(ind++))
 			break;
-	if (i >= addr_per_block)
-		if (ind_bh->b_count != 1)
+	if (i >= addr_per_block) {
+		if (ind_bh->b_count != 1) {
 			retry = 1;
-		else {
+		} else {
 			tmp = *p;
 			*p = 0;
 			inode->i_blocks -= blocks;
 			inode->i_dirt = 1;
 			ext2_free_blocks (inode, tmp, 1);
 		}
+	}
 	if (IS_SYNC(inode) && buffer_dirty(ind_bh)) {
 		ll_rw_block (WRITE, 1, &ind_bh);
 		wait_on_buffer (ind_bh);
@@ -238,9 +239,9 @@
 		if (*(dind++))
 			break;
 	if (i >= addr_per_block)
-		if (dind_bh->b_count != 1)
+		if (dind_bh->b_count != 1) {
 			retry = 1;
-		else {
+		} else {
 			tmp = *p;
 			*p = 0;
 			inode->i_blocks -= blocks;
@@ -296,16 +297,17 @@
 	for (i = 0; i < addr_per_block; i++)
 		if (*(tind++))
 			break;
-	if (i >= addr_per_block)
-		if (tind_bh->b_count != 1)
+	if (i >= addr_per_block) {
+		if (tind_bh->b_count != 1) {
 			retry = 1;
-		else {
+		} else {
 			tmp = *p;
 			*p = 0;
 			inode->i_blocks -= blocks;
 			inode->i_dirt = 1;
 			ext2_free_blocks (inode, tmp, 1);
 		}
+	}
 	if (IS_SYNC(inode) && buffer_dirty(tind_bh)) {
 		ll_rw_block (WRITE, 1, &tind_bh);
 		wait_on_buffer (tind_bh);
@@ -313,7 +315,7 @@
 	brelse (tind_bh);
 	return retry;
 }
-		
+
 void ext2_truncate (struct inode * inode)
 {
 	int retry;
diff -u --recursive --new-file linux-2.0.39/fs/isofs/inode.c linux-2.0.40/fs/isofs/inode.c
--- linux-2.0.39/fs/isofs/inode.c	Sun Jun 13 19:21:03 1999
+++ linux-2.0.40/fs/isofs/inode.c	Tue Aug 21 17:47:07 2001
@@ -241,18 +241,18 @@
 				       CDROMMULTISESSION,
 				       (unsigned long) &ms_info);
       set_fs(old_fs);
-#if 0 
+#if 0
       printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
       if (i==0)
 	{
 	  printk("isofs.inode: XA disk: %s\n", ms_info.xa_flag ? "yes":"no");
 	  printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
 	}
-#endif 0
+#endif /* 0 */
       if (i==0)
 #if WE_OBEY_THE_WRITTEN_STANDARDS
         if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
-#endif WE_OBEY_THE_WRITTEN_STANDARDS
+#endif /* WE_OBEY_THE_WRITTEN_STANDARDS */
           vol_desc_start=ms_info.addr.lba;
     }
   return vol_desc_start;
@@ -302,7 +302,7 @@
 	printk("gid = %d\n", opt.gid);
 	printk("uid = %d\n", opt.uid);
 #endif
-	
+
 	blocksize_bits = 0;
 	{
 	  int i = opt.blocksize;
@@ -318,7 +318,7 @@
 	s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
 
 	vol_desc_start = isofs_get_last_session(dev);
-	
+
 	for (iso_blknum = vol_desc_start+16;
              iso_blknum < vol_desc_start+100; iso_blknum++)
 	{
@@ -405,7 +405,7 @@
 	    printk("Multi-volume disks not supported.\n");
 	    goto out;
 	  }
-#endif IGNORE_WRONG_MULTI_VOLUME_SPECS
+#endif /* IGNORE_WRONG_MULTI_VOLUME_SPECS */
 	  s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
 	  s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
 	  s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
@@ -416,14 +416,14 @@
 	    printk("Multi-volume disks not supported.\n");
 	    goto out;
 	  }
-#endif IGNORE_WRONG_MULTI_VOLUME_SPECS
+#endif /* IGNORE_WRONG_MULTI_VOLUME_SPECS */
 	  s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
 	  s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
 	  s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
 	}
-	
+
 	s->u.isofs_sb.s_ninodes = 0; /* No way to figure this out easily */
-	
+
 	/* RDE: convert log zone size to bit shift */
 
 	orig_zonesize = s -> u.isofs_sb.s_log_zone_size;
@@ -438,16 +438,16 @@
 	  }
 
 	s->s_magic = ISOFS_SUPER_MAGIC;
-	
+
 	/* The CDROM is read-only, has no nodes (devices) on it, and since
 	   all of the files appear to be owned by root, we really do not want
 	   to allow suid.  (suid or devices will not show up unless we have
 	   Rock Ridge extensions) */
-	
+
 	s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
-	
+
 	brelse(bh);
-	
+
 	/* RDE: data zone now byte offset! */
 
 	s->u.isofs_sb.s_firstdatazone = ((isonum_733 (rootp->extent) + 
@@ -564,7 +564,7 @@
 #else
 	check_disk_change(s->s_dev);
 	return s;
-#endif	
+#endif
 
  out: /* Kick out for various error conditions */
 	brelse(bh);
@@ -657,7 +657,7 @@
 #endif
 			nextino = ino->u.isofs_i.i_next_section_ino;
 			iput(ino);
-		
+
 			if(++i > MAX_FILE_SECTIONS) {
 				printk("isofs_bmap: More than %d file sections ?!?, aborting...\n",
 				       MAX_FILE_SECTIONS);
@@ -880,14 +880,14 @@
 	printk("Get inode %d: %d %d: %d\n",inode->i_ino, block, 
 	       ((int)pnt) & 0x3ff, inode->i_size);
 #endif
-	
+
 	inode->i_mtime = inode->i_atime = inode->i_ctime = 
 	  iso_date(raw_inode->date, high_sierra);
 
 	inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) + 
 					   isonum_711 (raw_inode->ext_attr_length))
 	  << inode -> i_sb -> u.isofs_sb.s_log_zone_size;
-	
+
 	inode->u.isofs_i.i_backlink = 0xffffffff; /* Will be used for previous directory */
 	switch (inode->i_sb->u.isofs_sb.s_conversion){
 	case 'a':
@@ -912,12 +912,12 @@
 	  /* hmm..if we want uid or gid set, override the rock ridge setting */
 	 test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid);
 	}
-	
+
 #ifdef DEBUG
 	printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
 #endif
 	brelse(bh);
-	
+
 	inode->i_op = NULL;
 
 	/* get the volume sequence number */
@@ -940,7 +940,7 @@
 	    (volume_seq_no != 0) && (volume_seq_no != 1)) {
 		printk("Multi volume CD somehow got mounted.\n");
 	} else
-#endif IGNORE_WRONG_MULTI_VOLUME_SPECS
+#endif /* IGNORE_WRONG_MULTI_VOLUME_SPECS */
 	{
 	  if (S_ISREG(inode->i_mode))
 	    inode->i_op = &isofs_file_inode_operations;
diff -u --recursive --new-file linux-2.0.39/fs/pipe.c linux-2.0.40/fs/pipe.c
--- linux-2.0.39/fs/pipe.c	Sun Nov 15 19:33:14 1998
+++ linux-2.0.40/fs/pipe.c	Wed Aug 22 10:22:55 2001
@@ -35,11 +35,13 @@
 	if (filp->f_flags & O_NONBLOCK) {
 		if (PIPE_LOCK(*inode))
 			return -EAGAIN;
-		if (PIPE_EMPTY(*inode))
-			if (PIPE_WRITERS(*inode))
+		if (PIPE_EMPTY(*inode)) {
+			if (PIPE_WRITERS(*inode)) {
 				return -EAGAIN;
-			else
+			} else {
 				return 0;
+			}
+		}
 	} else while (PIPE_EMPTY(*inode) || PIPE_LOCK(*inode)) {
 		if (PIPE_EMPTY(*inode)) {
 			if (!PIPE_WRITERS(*inode))
diff -u --recursive --new-file linux-2.0.39/fs/proc/array.c linux-2.0.40/fs/proc/array.c
--- linux-2.0.39/fs/proc/array.c	Tue Apr 25 16:16:37 2000
+++ linux-2.0.40/fs/proc/array.c	Thu Aug 23 19:29:10 2001
@@ -14,7 +14,7 @@
  *                      EVERY character on the current page.
  *                      <middelin@polyware.iaf.nl>
  *
- * Danny ter Haar    :	added cpuinfo 
+ * Danny ter Haar    :	added cpuinfo
  *			<dth@cistron.nl>
  *
  * Alessandro Rubini :  profile extension.
diff -u --recursive --new-file linux-2.0.39/include/asm-i386/bugs.h linux-2.0.40/include/asm-i386/bugs.h
--- linux-2.0.39/include/asm-i386/bugs.h	Sun Jun 13 19:21:03 1999
+++ linux-2.0.40/include/asm-i386/bugs.h	Thu Aug 23 18:48:53 2001
@@ -228,8 +228,7 @@
 
                 if (d > 20*K6_BUG_LOOP) {
                         printk("system stability may be impaired when more than 32 MB are used.\n");
-		}
-                else 
+		} else
                         printk("probably OK (after B9730xxxx).\n");
         }
 }
@@ -346,7 +345,7 @@
 				int eax, dummy;
 
 				/* get processor info */
-			
+
 				cpuid(1, &eax, &dummy, &dummy,
 				      &x86_capability);
 
diff -u --recursive --new-file linux-2.0.39/include/asm-i386/math_emu.h linux-2.0.40/include/asm-i386/math_emu.h
--- linux-2.0.39/include/asm-i386/math_emu.h	Fri Nov  7 18:11:42 1997
+++ linux-2.0.40/include/asm-i386/math_emu.h	Mon Oct  8 23:54:43 2001
@@ -3,17 +3,8 @@
 
 #include <asm/sigcontext.h>
 
-void restore_i387_soft(struct _fpstate *buf);
-struct _fpstate * save_i387_soft(struct _fpstate * buf);
-
-struct fpu_reg {
-	char sign;
-	char tag;
-	long exp;
-	unsigned sigl;
-	unsigned sigh;
-};
-
+int restore_i387_soft(void *s387, struct _fpstate *buf);
+int save_i387_soft(void *s387, struct _fpstate * buf);
 
 /* This structure matches the layout of the data saved to the stack
    following a device-not-present interrupt, part of it saved
@@ -44,14 +35,5 @@
 	long ___vm86_fs;
 	long ___vm86_gs;
 };
-
-/* Interface for converting data between the emulator format
- * and the hardware format. Used for core dumping and for
- * ptrace(2) */
-void hardreg_to_softreg(const char hardreg[10],
-			      struct fpu_reg *soft_reg);
-
-void softreg_to_hardreg(const struct fpu_reg *rp, char d[10],
-			long int control_word);
 
 #endif
diff -u --recursive --new-file linux-2.0.39/include/asm-i386/processor.h linux-2.0.40/include/asm-i386/processor.h
--- linux-2.0.39/include/asm-i386/processor.h	Sun Jun 13 19:21:03 1999
+++ linux-2.0.40/include/asm-i386/processor.h	Mon Oct  8 23:54:43 2001
@@ -114,9 +114,8 @@
 	long	fcs;
 	long	foo;
 	long	fos;
-	long    top;
-	struct fpu_reg	regs[8];	/* 8*16 bytes for each FP-reg = 128 bytes */
-	unsigned char	lookahead;
+	long    st_space[20];   /* 8*10 bytes for each FP-reg = 80 bytes */
+	unsigned char   ftop, changed, lookahead, no_update, rm, alimit;
 	struct info	*info;
 	unsigned long	entry_eip;
 };
diff -u --recursive --new-file linux-2.0.39/include/asm-m68k/zorro.h linux-2.0.40/include/asm-m68k/zorro.h
--- linux-2.0.39/include/asm-m68k/zorro.h	Mon May 20 06:54:29 1996
+++ linux-2.0.40/include/asm-m68k/zorro.h	Thu Aug 23 18:49:08 2001
@@ -385,7 +385,7 @@
 #ifdef CONFIG_ZORRO
 extern void zorro_identify(void);
 extern int zorro_get_list(char *buffer);
-#endif CONFIG_ZORRO
+#endif /* CONFIG_ZORRO */
 
 #endif	/* __ASSEMBLY__ */
 
diff -u --recursive --new-file linux-2.0.39/include/asm-sparc/bitops.h linux-2.0.40/include/asm-sparc/bitops.h
--- linux-2.0.39/include/asm-sparc/bitops.h	Sun Apr 21 11:30:33 1996
+++ linux-2.0.40/include/asm-sparc/bitops.h	Mon Aug 20 14:14:52 2001
@@ -31,9 +31,10 @@
 
 extern __inline__ unsigned long set_bit(unsigned long nr, SMPVOL void *addr)
 {
-	int mask, flags;
+	int mask;
 	unsigned long *ADDR = (unsigned long *) addr;
 	unsigned long oldbit;
+	unsigned long flags;
 
 	ADDR += nr >> 5;
 	mask = 1 << (nr & 31);
@@ -46,9 +47,10 @@
 
 extern __inline__ unsigned long clear_bit(unsigned long nr, SMPVOL void *addr)
 {
-	int mask, flags;
+	int mask;
 	unsigned long *ADDR = (unsigned long *) addr;
 	unsigned long oldbit;
+	unsigned long flags;
 
 	ADDR += nr >> 5;
 	mask = 1 << (nr & 31);
@@ -61,9 +63,10 @@
 
 extern __inline__ unsigned long change_bit(unsigned long nr, SMPVOL void *addr)
 {
-	int mask, flags;
+	int mask;
 	unsigned long *ADDR = (unsigned long *) addr;
 	unsigned long oldbit;
+	unsigned long flags;
 
 	ADDR += nr >> 5;
 	mask = 1 << (nr & 31);
@@ -144,8 +147,9 @@
 
 extern __inline__ int ext2_set_bit(int nr,void * addr)
 {
-	int		mask, retval, flags;
+	int		mask, retval;
 	unsigned char	*ADDR = (unsigned char *) addr;
+	unsigned long	flags;
 
 	ADDR += nr >> 3;
 	mask = 1 << (nr & 0x07);
@@ -158,8 +162,9 @@
 
 extern __inline__ int ext2_clear_bit(int nr, void * addr)
 {
-	int		mask, retval, flags;
+	int		mask, retval;
 	unsigned char	*ADDR = (unsigned char *) addr;
+	unsigned long	flags;
 
 	ADDR += nr >> 3;
 	mask = 1 << (nr & 0x07);
diff -u --recursive --new-file linux-2.0.39/include/asm-sparc/head.h linux-2.0.40/include/asm-sparc/head.h
--- linux-2.0.39/include/asm-sparc/head.h	Mon May  6 11:26:16 1996
+++ linux-2.0.40/include/asm-sparc/head.h	Thu Aug 23 18:49:25 2001
@@ -99,4 +99,4 @@
 #define WINDOW_FILL \
         rd %psr, %l0; rd %wim, %l3; b fill_window_entry; andcc %l0, PSR_PS, %g0;
 
-#endif __SPARC_HEAD_H
+#endif /* __SPARC_HEAD_H */
diff -u --recursive --new-file linux-2.0.39/include/linux/binfmts.h linux-2.0.40/include/linux/binfmts.h
--- linux-2.0.39/include/linux/binfmts.h	Wed Oct 15 23:56:43 1997
+++ linux-2.0.40/include/linux/binfmts.h	Sat Mar  3 16:45:30 2001
@@ -24,6 +24,7 @@
 	char * filename;	/* Name of binary */
 	unsigned long loader, exec;
 	int dont_iput;		/* binfmt handler has put inode */
+	int dumpable;
 };
 
 /*
diff -u --recursive --new-file linux-2.0.39/include/linux/blk.h linux-2.0.40/include/linux/blk.h
--- linux-2.0.39/include/linux/blk.h	Sun Jun 13 19:21:04 1999
+++ linux-2.0.40/include/linux/blk.h	Wed Sep 12 15:37:34 2001
@@ -30,63 +30,63 @@
  */
 #if defined(IDE_DRIVER) || defined(MD_DRIVER)
 #define SECTOR_MASK ((BLOCK_SIZE >> 9) - 1)
-#else
+#else /* defined(IDE_DRIVER) || defined(MD_DRIVER) */
 #define SECTOR_MASK (blksize_size[MAJOR_NR] &&     \
 	blksize_size[MAJOR_NR][MINOR(CURRENT->rq_dev)] ? \
 	((blksize_size[MAJOR_NR][MINOR(CURRENT->rq_dev)] >> 9) - 1) :  \
 	((BLOCK_SIZE >> 9)  -  1))
-#endif /* IDE_DRIVER */
+#endif /* !(defined(IDE_DRIVER) || defined(MD_DRIVER)) */
 
 #define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0)
 
 #ifdef CONFIG_CDU31A
 extern int cdu31a_init(void);
-#endif CONFIG_CDU31A
+#endif /* CONFIG_CDU31A */
 #ifdef CONFIG_MCD
 extern int mcd_init(void);
-#endif CONFIG_MCD
+#endif /* CONFIG_MCD */
 #ifdef CONFIG_MCDX
 extern int mcdx_init(void);
-#endif CONFIG_MCDX
+#endif /* CONFIG_MCDX */
 #ifdef CONFIG_SBPCD
 extern int sbpcd_init(void);
-#endif CONFIG_SBPCD
+#endif /* CONFIG_SBPCD */
 #ifdef CONFIG_AZTCD
 extern int aztcd_init(void);
-#endif CONFIG_AZTCD
+#endif /* CONFIG_AZTCD */
 #ifdef CONFIG_CDU535
 extern int sony535_init(void);
-#endif CONFIG_CDU535
+#endif /* CONFIG_CDU535 */
 #ifdef CONFIG_GSCD
 extern int gscd_init(void);
-#endif CONFIG_GSCD
+#endif /* CONFIG_GSCD */
 #ifdef CONFIG_CM206
 extern int cm206_init(void);
-#endif CONFIG_CM206
+#endif /* CONFIG_CM206 */
 #ifdef CONFIG_OPTCD
 extern int optcd_init(void);
-#endif CONFIG_OPTCD
+#endif /* CONFIG_OPTCD */
 #ifdef CONFIG_SJCD
 extern int sjcd_init(void);
-#endif CONFIG_SJCD
+#endif /* CONFIG_SJCD */
 #ifdef CONFIG_CDI_INIT
 extern int cdi_init(void);
-#endif CONFIG_CDI_INIT
+#endif /* CONFIG_CDI_INIT */
 #ifdef CONFIG_BLK_DEV_HD
 extern int hd_init(void);
-#endif
+#endif /* CONFIG_BLK_DEV_HD */
 #ifdef CONFIG_BLK_DEV_IDE
 extern int ide_init(void);
-#endif
+#endif /* CONFIG_BLK_DEV_IDE */
 #ifdef CONFIG_BLK_DEV_XD
 extern int xd_init(void);
-#endif
+#endif /* CONFIG_BLK_DEV_XD */
 #ifdef CONFIG_BLK_DEV_LOOP
 extern int loop_init(void);
-#endif
+#endif /* CONFIG_BLK_DEV_LOOP */
 #ifdef CONFIG_BLK_DEV_MD
 extern int md_init(void);
-#endif CONFIG_BLK_DEV_MD
+#endif /* CONFIG_BLK_DEV_MD */
 
 extern void set_device_ro(kdev_t dev,int flag);
 void add_blkdev_randomness(int major);
@@ -106,7 +106,7 @@
 extern int mount_initrd; /* zero if initrd should not be mounted */
 void initrd_init(void);
 
-#endif
+#endif /* CONFIG_BLK_DEV_INITRD */
 
 #define RO_IOCTLS(dev,where) \
   case BLKROSET: { int __err;  if (!suser()) return -EACCES; \
@@ -114,7 +114,7 @@
 		   if (!__err) set_device_ro((dev),get_fs_long((long *) (where))); return __err; } \
   case BLKROGET: { int __err = verify_area(VERIFY_WRITE, (void *) (where), sizeof(long)); \
 		   if (!__err) put_fs_long(0!=is_read_only(dev),(long *) (where)); return __err; }
-		 
+
 #if defined(MAJOR_NR) || defined(IDE_DRIVER)
 
 /*
@@ -133,7 +133,7 @@
 #define DEVICE_NAME "ramdisk"
 #define DEVICE_REQUEST rd_request
 #define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device) 
+#define DEVICE_ON(device)
 #define DEVICE_OFF(device)
 #define DEVICE_NO_RANDOM
 
@@ -163,7 +163,7 @@
 #elif (MAJOR_NR == SCSI_DISK_MAJOR)
 
 #define DEVICE_NAME "scsidisk"
-#define DEVICE_INTR do_sd  
+#define DEVICE_INTR do_sd
 #define TIMEOUT_VALUE (2*HZ)
 #define DEVICE_REQUEST do_sd_request
 #define DEVICE_NR(device) (MINOR(device) >> 4)
@@ -182,7 +182,7 @@
 #elif (MAJOR_NR == SCSI_TAPE_MAJOR)
 
 #define DEVICE_NAME "scsitape"
-#define DEVICE_INTR do_st  
+#define DEVICE_INTR do_st
 #define DEVICE_NR(device) (MINOR(device) & 0x7f)
 #define DEVICE_ON(device)
 #define DEVICE_OFF(device)
@@ -327,13 +327,13 @@
 
 #ifndef CURRENT
 #define CURRENT (blk_dev[MAJOR_NR].current_request)
-#endif
+#endif /* !CURRENT */
 
 #define CURRENT_DEV DEVICE_NR(CURRENT->rq_dev)
 
 #ifdef DEVICE_INTR
 static void (*DEVICE_INTR)(void) = NULL;
-#endif
+#endif /* DEVICE_INTR */
 #ifdef DEVICE_TIMEOUT
 
 #define SET_TIMER \
@@ -349,19 +349,19 @@
 else \
 	CLEAR_TIMER;
 
-#else
+#else /* DEVICE_TIMEOUT */
 
 #define SET_INTR(x) (DEVICE_INTR = (x))
 
-#endif /* DEVICE_TIMEOUT */
+#endif /* !DEVICE_TIMEOUT */
 
 static void (DEVICE_REQUEST)(void);
-  
+
 #ifdef DEVICE_INTR
 #define CLEAR_INTR SET_INTR(NULL)
-#else
+#else /* DEVICE_INTR */
 #define CLEAR_INTR
-#endif
+#endif /* !DEVICE_INTR */
 
 #define INIT_REQUEST \
 	if (!CURRENT) {\
@@ -380,19 +380,19 @@
 /* end_request() - SCSI devices have their own version */
 /*               - IDE drivers have their own copy too */
 
-#if ! SCSI_BLK_MAJOR(MAJOR_NR) && (MAJOR_NR != COMPAQ_SMART2_MAJOR)
+#if !SCSI_BLK_MAJOR(MAJOR_NR) && (MAJOR_NR != COMPAQ_SMART2_MAJOR)
 
 #if defined(IDE_DRIVER) && !defined(_IDE_C) /* shared copy for IDE modules */
 void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
-#else
+#else /* defined(IDE_DRIVER) && !defined(_IDE_C) */
 
 #ifdef IDE_DRIVER
 void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup) {
 	struct request *req = hwgroup->rq;
-#else
+#else /* IDE_DRIVER */
 static void end_request(int uptodate) {
 	struct request *req = CURRENT;
-#endif /* IDE_DRIVER */
+#endif /* !IDE_DRIVER */
 	struct buffer_head * bh;
 	int nsect;
 
@@ -412,24 +412,21 @@
 	if ((bh = req->bh) != NULL) {
 		req->bh = bh->b_reqnext;
 		bh->b_reqnext = NULL;
- 
- 		/*
- 		 * This is our 'MD IO has finished' event handler.
- 		 * note that b_state should be cached in a register
- 		 * anyways, so the overhead if this checking is almost 
- 		 * zero. But anyways .. we never get OO for free :)
- 		 */
- 		if (test_bit(BH_MD, &bh->b_state)) {
- 			struct md_personality * pers=(struct md_personality *)bh->personality;
- 			pers->end_request(bh,uptodate);
- 		}
- 		/*
- 		 * the normal (nonmirrored and no RAID5) case:
- 		 */
- 		else {
- 			mark_buffer_uptodate(bh, uptodate);
- 			unlock_buffer(bh);
- 		}
+
+		/* This is our 'MD IO has finished' event handler.
+		 * note that b_state should be cached in a register
+		 * anyways, so the overhead if this checking is almost
+		 * zero. But anyways .. we never get OO for free :)
+		 */
+		if (test_bit(BH_MD, &bh->b_state)) {
+			struct md_personality * pers=(struct md_personality *)bh->personality;
+			pers->end_request(bh,uptodate);
+		} else {
+			/* the normal (nonmirrored and no RAID5) case:
+			 */
+			mark_buffer_uptodate(bh, uptodate);
+			unlock_buffer(bh);
+		}
 		if ((bh = req->bh) != NULL) {
 			req->current_nr_sectors = bh->b_size >> 9;
 			if (req->nr_sectors < req->current_nr_sectors) {
@@ -442,21 +439,21 @@
 	}
 #ifndef DEVICE_NO_RANDOM
 	add_blkdev_randomness(MAJOR(req->rq_dev));
-#endif
+#endif /* !DEVICE_NO_RANDOM */
 #ifdef IDE_DRIVER
 	blk_dev[MAJOR(req->rq_dev)].current_request = req->next;
 	hwgroup->rq = NULL;
-#else
+#else /* IDE_DRIVER */
 	DEVICE_OFF(req->rq_dev);
 	CURRENT = req->next;
-#endif /* IDE_DRIVER */
+#endif /* !IDE_DRIVER */
 	if (req->sem != NULL)
 		up(req->sem);
 	req->rq_status = RQ_INACTIVE;
 	wake_up(&wait_for_request);
 }
-#endif /* defined(IDE_DRIVER) && !defined(_IDE_C) */
-#endif /* ! SCSI_BLK_MAJOR(MAJOR_NR) */
+#endif /* !(defined(IDE_DRIVER) && !defined(_IDE_C)) */
+#endif /* !SCSI_BLK_MAJOR(MAJOR_NR) */
 #endif /* (MAJOR_NR != SCSI_TAPE_MAJOR) */
 
 #endif /* defined(MAJOR_NR) || defined(IDE_DRIVER) */
diff -u --recursive --new-file linux-2.0.39/include/linux/cdrom.h linux-2.0.40/include/linux/cdrom.h
--- linux-2.0.39/include/linux/cdrom.h	Fri Sep 20 16:00:36 1996
+++ linux-2.0.40/include/linux/cdrom.h	Thu Aug 23 18:33:07 2001
@@ -67,14 +67,14 @@
  * CDROM IOCTL structures
  */
 
-struct cdrom_blk 
+struct cdrom_blk
 {
 	unsigned from;
 	unsigned short len;
 };
 
 
-struct cdrom_msf 
+struct cdrom_msf
 {
 	u_char	cdmsf_min0;	/* start minute */
 	u_char	cdmsf_sec0;	/* start second */
@@ -84,7 +84,7 @@
 	u_char	cdmsf_frame1;	/* end frame */
 };
 
-struct cdrom_ti 
+struct cdrom_ti
 {
 	u_char	cdti_trk0;	/* start track */
 	u_char	cdti_ind0;	/* start index */
@@ -92,7 +92,7 @@
 	u_char	cdti_ind1;	/* end index */
 };
 
-struct cdrom_tochdr 	
+struct cdrom_tochdr
 {
 	u_char	cdth_trk0;	/* start track */
 	u_char	cdth_trk1;	/* end track */
@@ -111,7 +111,7 @@
 	int			lba;
 };
 
-struct cdrom_tocentry 
+struct cdrom_tocentry
 {
 	u_char	cdte_track;
 	u_char	cdte_adr	:4;
@@ -137,7 +137,7 @@
  */
 #define	CDROM_LEADOUT	0xAA
 
-struct cdrom_subchnl 
+struct cdrom_subchnl
 {
 	u_char	cdsc_format;
 	u_char	cdsc_audiostatus;
@@ -204,9 +204,9 @@
 
 #ifdef FIVETWELVE
 #define	CDROM_MODE1_SIZE	512
-#else
+#else /* FIVETWELVE */
 #define	CDROM_MODE1_SIZE	2048
-#endif FIVETWELVE
+#endif /* !FIVETWELVE */
 #define	CDROM_MODE2_SIZE	2336
 
 /*
@@ -419,7 +419,7 @@
 /*
  * cache parameters
  */
-struct ccs_cache 
+struct ccs_cache
 {
 	u_char	_r1	: 2;	/* reserved */
 	u_char	page_code : 6;	/* page code */
@@ -433,13 +433,13 @@
 	u_char	_r2[8];
 };
 
-#endif  _LINUX_CDROM_H
+#endif /* _LINUX_CDROM_H */
 /*==========================================================================*/
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
  * adjust the settings for this buffer only.  This must remain at the end
- * of the file. 
+ * of the file.
  * ---------------------------------------------------------------------------
  * Local variables:
  * c-indent-level: 8
diff -u --recursive --new-file linux-2.0.39/include/linux/cm206.h linux-2.0.40/include/linux/cm206.h
--- linux-2.0.39/include/linux/cm206.h	Wed May 15 09:06:26 1996
+++ linux-2.0.40/include/linux/cm206.h	Thu Aug 23 18:34:14 2001
@@ -137,7 +137,7 @@
 #if !defined(CDROM_GET_UPC)
 #define CDROM_GET_UPC _IO( 'S', 0x11 )
 #define CDROMRESET _IO( 'S', 0x12 )
-#endif
+#endif /* !defined(CDROM_GET_UPC) */
 
 #ifdef STATISTICS
 
@@ -147,10 +147,10 @@
 #ifdef __KERNEL__
 #define x(a) st_ ## a
 #define y enum
-#else
+#else /* __KERNEL__ */
 #define x(a) #a
-#define y char * stats_name[] = 
-#endif
+#define y char * stats_name[] =
+#endif /* !__KERNEL__ */
 
 y {x(interrupt), x(data_ready), x(fifo_overflow), x(data_error),
      x(crc_error), x(sync_error), x(lost_intr), x(echo),
@@ -160,18 +160,18 @@
      x(bh), x(open), x(ioctl_multisession), x(attention)
 #ifdef __KERNEL__
      , x(last_entry)
-#endif
+#endif /* __KERNEL__ */
  };
 
 #ifdef __KERNEL__
 #define NR_STATS st_last_entry
-#else
+#else /* __KERNEL__ */
 #define NR_STATS (sizeof(stats_name)/sizeof(char*))
-#endif
+#endif /* __KERNEL__ */
 
 #undef y
 #undef x
 
-#endif STATISTICS
+#endif /* STATISTICS */
 
-#endif LINUX_CM206_H
+#endif /* LINUX_CM206_H */
diff -u --recursive --new-file linux-2.0.39/include/linux/if_frad.h linux-2.0.40/include/linux/if_frad.h
--- linux-2.0.39/include/linux/if_frad.h	Thu Jun  4 00:17:49 1998
+++ linux-2.0.40/include/linux/if_frad.h	Thu Aug 23 18:46:45 2001
@@ -132,13 +132,13 @@
    unsigned char  control	__attribute__((packed));
 
    /* for IP packets, this can be the NLPID */
-   unsigned char  pad		__attribute__((packed)); 
+   unsigned char  pad		__attribute__((packed));
 
    unsigned char  NLPID		__attribute__((packed));
    unsigned char  OUI[3]	__attribute__((packed));
    unsigned short PID		__attribute__((packed));
 
-#define IP_NLPID pad 
+#define IP_NLPID pad
 };
 
 /* see RFC 1490 for the definition of the following */
@@ -190,6 +190,6 @@
 int register_frad(const char *name);
 int unregister_frad(const char *name);
 
-#endif __KERNEL__
+#endif /* __KERNEL__ */
 
-#endif
+#endif /* _FRAD_H_ */
diff -u --recursive --new-file linux-2.0.39/include/linux/kernel.h linux-2.0.40/include/linux/kernel.h
--- linux-2.0.39/include/linux/kernel.h	Thu Aug 14 19:05:47 1997
+++ linux-2.0.40/include/linux/kernel.h	Sat Mar  3 16:45:30 2001
@@ -39,8 +39,12 @@
 NORET_TYPE void do_exit(long error_code)
 	ATTRIB_NORET;
 extern unsigned long simple_strtoul(const char *,char **,unsigned int);
-extern int sprintf(char * buf, const char * fmt, ...);
-extern int vsprintf(char *buf, const char *, va_list);
+extern int sprintf(char *buf, const char *fmt, ...)
+	__attribute__ ((format (printf, 2, 3)));
+extern int vsprintf(char *buf, const char *, va_list)
+	__attribute__ ((format (printf, 2, 0)));
+extern int _vsnprintf(char *buf, int n, const char *, va_list)
+	__attribute__ ((format (printf, 3, 0)));
 
 extern int session_of_pgrp(int pgrp);
 
diff -u --recursive --new-file linux-2.0.39/include/linux/md.h linux-2.0.40/include/linux/md.h
--- linux-2.0.39/include/linux/md.h	Mon Jul 13 22:47:39 1998
+++ linux-2.0.40/include/linux/md.h	Thu Aug 23 18:47:08 2001
@@ -3,15 +3,15 @@
           Copyright (C) 1994-96 Marc ZYNGIER
 	  <zyngier@ufr-info-p7.ibp.fr> or
 	  <maz@gloups.fdn.fr>
-	  
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2, or (at your option)
    any later version.
-   
+
    You should have received a copy of the GNU General Public License
    (for example /usr/src/linux/COPYING); if not, write to the Free
-   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 #ifndef _MD_H
@@ -271,5 +271,5 @@
 extern void md_wakeup_thread(struct md_thread *thread);
 extern int md_update_sb (int minor);
 
-#endif __KERNEL__
-#endif _MD_H
+#endif /* __KERNEL__ */
+#endif /* _MD_H */
diff -u --recursive --new-file linux-2.0.39/include/linux/optcd.h linux-2.0.40/include/linux/optcd.h
--- linux-2.0.39/include/linux/optcd.h	Tue Jun  4 09:53:46 1996
+++ linux-2.0.40/include/linux/optcd.h	Thu Aug 23 18:35:41 2001
@@ -49,4 +49,4 @@
 #define N_BUFS		6
 
 
-#endif _LINUX_OPTCD_H
+#endif /* _LINUX_OPTCD_H */
diff -u --recursive --new-file linux-2.0.39/include/linux/sbpcd.h linux-2.0.40/include/linux/sbpcd.h
--- linux-2.0.39/include/linux/sbpcd.h	Mon Sep  2 14:18:26 1996
+++ linux-2.0.40/include/linux/sbpcd.h	Thu Aug 23 18:35:16 2001
@@ -117,16 +117,16 @@
 /* tray control: eject tray if no disk is in */
 #if DISTRIBUTION
 #define JUKEBOX 0
-#else
+#else /* DISTRIBUTION */
 #define JUKEBOX 1
-#endif DISTRIBUTION
+#endif /* !DISTRIBUTION */
 
 /* tray control: eject tray after last use */
 #if DISTRIBUTION
 #define EJECT 0
-#else
+#else /* DISTRIBUTION */
 #define EJECT 1
-#endif DISTRIBUTION
+#endif /* !DISTRIBUTION */
 
 /* max. number of audio frames to read with one     */
 /* request (allocates n* 2352 bytes kernel memory!) */
@@ -157,14 +157,13 @@
  * nothing to change below here if you are not fully aware what you're doing
  */
 #ifndef _LINUX_SBPCD_H
-
 #define _LINUX_SBPCD_H
 /*==========================================================================*/
 /*==========================================================================*/
 /*
  * driver's own read_ahead, data mode
  */
-#define SBP_BUFFER_FRAMES 8 
+#define SBP_BUFFER_FRAMES 8
 
 #define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */
 #undef  FUTURE
@@ -838,13 +837,13 @@
 
 /*==========================================================================*/
 /*==========================================================================*/
-#endif _LINUX_SBPCD_H
+#endif /* _LINUX_SBPCD_H */
 /*==========================================================================*/
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
  * adjust the settings for this buffer only.  This must remain at the end
- * of the file. 
+ * of the file.
  * ---------------------------------------------------------------------------
  * Local variables:
  * c-indent-level: 8
diff -u --recursive --new-file linux-2.0.39/include/linux/skbuff.h linux-2.0.40/include/linux/skbuff.h
--- linux-2.0.39/include/linux/skbuff.h	Wed Dec 29 12:41:06 1999
+++ linux-2.0.40/include/linux/skbuff.h	Mon Oct  8 14:06:31 2001
@@ -20,8 +20,6 @@
 #include <asm/atomic.h>
 #include <asm/types.h>
 
-#define CONFIG_SKB_CHECK 0
-
 #define HAVE_ALLOC_SKB		/* For the drivers to know */
 #define HAVE_ALIGNABLE_SKB	/* Ditto 8)		   */
 
@@ -209,9 +207,24 @@
 extern int 			skb_check(struct sk_buff *skb,int,int, char *);
 #define IS_SKB(skb)		skb_check((skb), 0, __LINE__,__FILE__)
 #define IS_SKB_HEAD(skb)	skb_check((skb), 1, __LINE__,__FILE__)
+#define IS_SKB_LINKED(skb)	skb_check((skb), 2, __LINE__,__FILE__)
+#define IS_SKB_UNLINKED(skb)	skb_check((skb), 3, __LINE__,__FILE__)
+/* Note: IS_SKB_LINKED will accept skb_heads in addition to linked-in 
+ * data skbs */
+
+extern void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk);
+extern void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk);
+extern struct sk_buff *__skb_dequeue(struct sk_buff_head *list);
+extern void __skb_insert(struct sk_buff *newsk,
+	struct sk_buff * prev, struct sk_buff *next,
+	struct sk_buff_head * list);
+extern void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list);
+
 #else
 #define IS_SKB(skb)		
 #define IS_SKB_HEAD(skb)	
+#define IS_SKB_LINKED(skb)	
+#define IS_SKB_UNLINKED(skb)	
 
 extern __inline__ void skb_queue_head_init(struct sk_buff_head *list)
 {
diff -u --recursive --new-file linux-2.0.39/init/main.c linux-2.0.40/init/main.c
--- linux-2.0.39/init/main.c	Wed Jun 28 14:48:20 2000
+++ linux-2.0.40/init/main.c	Wed Sep 12 15:50:03 2001
@@ -35,13 +35,13 @@
 #include <linux/blk.h>
 #ifdef CONFIG_ROOT_NFS
 #include <linux/nfs_fs.h>
-#endif
+#endif /* CONFIG_ROOT_NFS */
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
-#endif
+#endif /* CONFIG_MTRR */
 #ifdef CONFIG_APM
 #include <linux/apm_bios.h>
-#endif
+#endif /* CONFIG_APM */
 
 #include <asm/bugs.h>
 
@@ -53,7 +53,7 @@
  */
 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6)
 #error sorry, your GCC is too old. It builds incorrect kernels.
-#endif
+#endif /* __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6) */
 
 extern char _stext, _etext;
 extern const char *linux_banner;
@@ -70,7 +70,7 @@
 extern void init_IRQ(void);
 extern void init_modules(void);
 extern long console_init(long, long);
-extern long kmalloc_init(long,long);
+extern long kmalloc_init(long, long);
 extern void sock_init(void);
 extern unsigned long pci_init(unsigned long, unsigned long);
 extern void sysctl_init(void);
@@ -116,108 +116,108 @@
 extern void reboot_setup(char *str, int *ints);
 #ifdef CONFIG_CDU31A
 extern void cdu31a_setup(char *str, int *ints);
-#endif CONFIG_CDU31A
+#endif /* CONFIG_CDU31A */
 #ifdef CONFIG_MCD
 extern void mcd_setup(char *str, int *ints);
-#endif CONFIG_MCD
+#endif /* CONFIG_MCD */
 #ifdef CONFIG_MCDX
 extern void mcdx_setup(char *str, int *ints);
-#endif CONFIG_MCDX
+#endif /* CONFIG_MCDX */
 #ifdef CONFIG_SBPCD
 extern void sbpcd_setup(char *str, int *ints);
-#endif CONFIG_SBPCD
+#endif /* CONFIG_SBPCD */
 #ifdef CONFIG_AZTCD
 extern void aztcd_setup(char *str, int *ints);
-#endif CONFIG_AZTCD
+#endif /* CONFIG_AZTCD */
 #ifdef CONFIG_CDU535
 extern void sonycd535_setup(char *str, int *ints);
-#endif CONFIG_CDU535
+#endif /* CONFIG_CDU535 */
 #ifdef CONFIG_GSCD
 extern void gscd_setup(char *str, int *ints);
-#endif CONFIG_GSCD
+#endif /* CONFIG_GSCD */
 #ifdef CONFIG_CM206
 extern void cm206_setup(char *str, int *ints);
-#endif CONFIG_CM206
+#endif /* CONFIG_CM206 */
 #ifdef CONFIG_OPTCD
 extern void optcd_setup(char *str, int *ints);
-#endif CONFIG_OPTCD
+#endif /* CONFIG_OPTCD */
 #ifdef CONFIG_SJCD
 extern void sjcd_setup(char *str, int *ints);
-#endif CONFIG_SJCD
+#endif /* CONFIG_SJCD */
 #ifdef CONFIG_ISP16_CDI
 extern void isp16_setup(char *str, int *ints);
-#endif CONFIG_ISP16_CDI
+#endif /* CONFIG_ISP16_CDI */
 #ifdef CONFIG_BLK_DEV_RAM
 static void ramdisk_start_setup(char *str, int *ints);
 static void load_ramdisk(char *str, int *ints);
 static void prompt_ramdisk(char *str, int *ints);
 static void ramdisk_size(char *str, int *ints);
 #ifdef CONFIG_BLK_DEV_INITRD
-static void no_initrd(char *s,int *ints);
-#endif
-#endif CONFIG_BLK_DEV_RAM
+static void no_initrd(char *s, int *ints);
+#endif /* CONFIG_BLK_DEV_INITRD */
+#endif /* CONFIG_BLK_DEV_RAM */
 #ifdef CONFIG_ISDN_DRV_ICN
 extern void icn_setup(char *str, int *ints);
-#endif
+#endif /* CONFIG_ISDN_DRV_ICN */
 #ifdef CONFIG_ISDN_DRV_HISAX
 extern void HiSax_setup(char *str, int *ints);
-#endif
+#endif /* CONFIG_ISDN_DRV_HISAX */
 #ifdef CONFIG_ISDN_DRV_PCBIT
 extern void pcbit_setup(char *str, int *ints);
-#endif
+#endif /* CONFIG_ISDN_DRV_PCBIT */
 
 #ifdef CONFIG_ATARIMOUSE
 extern void atari_mouse_setup (char *str, int *ints);
-#endif
+#endif /* CONFIG_ATARIMOUSE */
 #ifdef CONFIG_DMASOUND
 extern void dmasound_setup (char *str, int *ints);
-#endif
+#endif /* CONFIG_DMASOUND */
 #ifdef CONFIG_ATARI_SCSI
 extern void atari_scsi_setup (char *str, int *ints);
-#endif
+#endif /* CONFIG_ATARI_SCSI */
 extern void wd33c93_setup (char *str, int *ints);
 extern void gvp11_setup (char *str, int *ints);
 
 #ifdef CONFIG_CYCLADES
 extern void cy_setup(char *str, int *ints);
-#endif
+#endif /* CONFIG_CYCLADES */
 #ifdef CONFIG_DIGI
 extern void pcxx_setup(char *str, int *ints);
-#endif
+#endif /* CONFIG_DIGI */
 #ifdef CONFIG_RISCOM8
 extern void riscom8_setup(char *str, int *ints);
-#endif
+#endif /* CONFIG_RISCOM8 */
 #ifdef CONFIG_SPECIALIX
 extern void specialix_setup(char *str, int *ints);
-#endif
+#endif /* CONFIG_SPECIALIX */
 #ifdef CONFIG_BAYCOM
 extern void baycom_setup(char *str, int *ints);
-#endif
+#endif /* CONFIG_BAYCOM */
 
 #ifdef CONFIG_PARIDE_PD
 extern void pd_setup(char *str, int *ints);
-#endif
+#endif /* CONFIG_PARIDE_PD */
 #ifdef CONFIG_PARIDE_PF
 extern void pf_setup(char *str, int *ints);
-#endif
+#endif /* CONFIG_PARIDE_PF */
 #ifdef CONFIG_PARIDE_PT
 extern void pt_setup(char *str, int *ints);
-#endif
+#endif /* CONFIG_PARIDE_PT */
 #ifdef CONFIG_PARIDE_PG
 extern void pg_setup(char *str, int *ints);
-#endif
+#endif /* CONFIG_PARIDE_PG */
 #ifdef CONFIG_PARIDE_PCD
 extern void pcd_setup(char *str, int *ints);
-#endif
+#endif /* CONFIG_PARIDE_PCD */
 #ifdef CONFIG_BLK_CPQ_DA
 #ifdef CONFIG_BLK_CPQ_DA_EISA
 extern void cpqarray_setup(char *str, int *ints);
-#endif
-#endif
+#endif /* CONFIG_BLK_CPQ_DA_EISA */
+#endif /* CONFIG_BLK_CPQ_DA */
 
 #if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)
 extern void ipc_init(void);
-#endif
+#endif /* defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD) */
 
 /*
  * Boot command-line arguments
@@ -239,8 +239,8 @@
 extern int rd_image_start;	/* starting block # of image */
 #ifdef CONFIG_BLK_DEV_INITRD
 kdev_t real_root_dev;
-#endif
-#endif
+#endif /* CONFIG_BLK_DEV_INITRD */
+#endif /* CONFIG_BLK_DEV_RAM */
 
 int root_mountflags = MS_RDONLY;
 char *execute_command = 0;
@@ -248,7 +248,7 @@
 #ifdef CONFIG_ROOT_NFS
 char nfs_root_name[NFS_ROOT_NAME_LEN] = { "default" };
 char nfs_root_addrs[NFS_ROOT_ADDRS_LEN] = { "" };
-#endif
+#endif /* CONFIG_ROOT_NFS */
 
 extern void dquot_init(void);
 
@@ -258,7 +258,7 @@
 static char * argv_rc[] = { "/bin/sh", NULL };
 static char * envp_rc[] = { "HOME=/", "TERM=linux", NULL };
 
-static char * argv[] = { "-/bin/sh",NULL };
+static char * argv[] = { "-/bin/sh", NULL };
 static char * envp[] = { "HOME=/usr/root", "TERM=linux", NULL };
 
 char *get_options(char *str, int *ints)
@@ -267,8 +267,8 @@
 	int i=1;
 
 	while (cur && isdigit(*cur) && i <= 10) {
-		ints[i++] = simple_strtoul(cur,NULL,0);
-		if ((cur = strchr(cur,',')) != NULL)
+		ints[i++] = simple_strtoul(cur, NULL, 0);
+		if ((cur = strchr(cur, ',')) != NULL)
 			cur++;
 	}
 	ints[0] = i-1;
@@ -282,9 +282,9 @@
 	else
 #ifdef CONFIG_PROFILE_SHIFT
 		prof_shift = CONFIG_PROFILE_SHIFT;
-#else
+#else /* CONFIG_PROFILE_SHIFT */
 		prof_shift = 2;
-#endif
+#endif /* !CONFIG_PROFILE_SHIFT */
 }
 
 struct kernel_param {
@@ -303,8 +303,8 @@
 	{ "ramdisk_size=", ramdisk_size },
 #ifdef CONFIG_BLK_DEV_INITRD
 	{ "noinitrd", no_initrd },
-#endif
-#endif
+#endif /* CONFIG_BLK_DEV_INITRD */
+#endif /* CONFIG_BLK_DEV_RAM */
 	{ "swap=", swap_setup },
 	{ "buff=", buff_setup },
 	{ "panic=", panic_setup },
@@ -313,182 +313,182 @@
 	{ "no-hlt", no_halt },
 	{ "no387", no_387 },
 	{ "reboot=", reboot_setup },
-#endif
+#endif /* CONFIG_BUGi386 */
 #ifdef CONFIG_INET
 	{ "ether=", eth_setup },
-#endif
+#endif /* CONFIG_INET */
 #ifdef CONFIG_PRINTER
         { "lp=", lp_setup },
-#endif
+#endif /* CONFIG_PRINTER */
 #ifdef CONFIG_SCSI
 	{ "max_scsi_luns=", scsi_luns_setup },
-#endif
+#endif /* CONFIG_SCSI */
 #ifdef CONFIG_SCSI_ADVANSYS
 	{ "advansys=", advansys_setup },
-#endif
+#endif /* CONFIG_SCSI_ADVANSYS */
 #if defined(CONFIG_BLK_DEV_HD)
 	{ "hd=", hd_setup },
-#endif
+#endif /* defined(CONFIG_BLK_DEV_HD) */
 #ifdef CONFIG_CHR_DEV_ST
 	{ "st=", st_setup },
-#endif
+#endif /* CONFIG_CHR_DEV_ST */
 #ifdef CONFIG_BUSMOUSE
 	{ "bmouse=", bmouse_setup },
-#endif
+#endif /* CONFIG_BUSMOUSE */
 #ifdef CONFIG_MS_BUSMOUSE
 	{ "msmouse=", msmouse_setup },
-#endif
+#endif /* CONFIG_MS_BUSMOUSE */
 #ifdef CONFIG_SCSI_SEAGATE
 	{ "st0x=", st0x_setup },
 	{ "tmc8xx=", tmc8xx_setup },
-#endif
+#endif /* CONFIG_SCSI_SEAGATE */
 #ifdef CONFIG_SCSI_T128
 	{ "t128=", t128_setup },
-#endif
+#endif /* CONFIG_SCSI_T128 */
 #ifdef CONFIG_SCSI_PAS16
 	{ "pas16=", pas16_setup },
-#endif
+#endif /* CONFIG_SCSI_PAS16 */
 #ifdef CONFIG_SCSI_GENERIC_NCR5380
 	{ "ncr5380=", generic_NCR5380_setup },
 	{ "ncr53c400=", generic_NCR53C400_setup },
-#endif
+#endif /* CONFIG_SCSI_GENERIC_NCR5380 */
 #ifdef CONFIG_SCSI_AHA152X
 	{ "aha152x=", aha152x_setup},
-#endif
+#endif /* CONFIG_SCSI_AHA152X */
 #ifdef CONFIG_SCSI_AHA1542
 	{ "aha1542=", aha1542_setup},
-#endif
+#endif /* CONFIG_SCSI_AHA1542 */
 #ifdef CONFIG_SCSI_GDTH
 	{ "gdth=", gdth_setup},
-#endif
+#endif /* CONFIG_SCSI_GDTH */
 #ifdef CONFIG_SCSI_AIC7XXX
 	{ "aic7xxx=", aic7xxx_setup},
-#endif
+#endif /* CONFIG_SCSI_AIC7XXX */
 #ifdef CONFIG_SCSI_BUSLOGIC
 	{ "BusLogic=", BusLogic_Setup},
-#endif
+#endif /* CONFIG_SCSI_BUSLOGIC */
 #ifdef CONFIG_SCSI_NCR53C8XX
 	{ "ncr53c8xx=", ncr53c8xx_setup},
-#endif
+#endif /* CONFIG_SCSI_NCR53C8XX */
 #ifdef CONFIG_SCSI_EATA
 	{ "eata=", eata2x_setup},
-#endif
+#endif /* CONFIG_SCSI_EATA */
 #ifdef CONFIG_SCSI_U14_34F
 	{ "u14-34f=", u14_34f_setup},
-#endif
+#endif /* CONFIG_SCSI_U14_34F */
 #ifdef CONFIG_SCSI_AM53C974
         { "AM53C974=", AM53C974_setup},
-#endif
+#endif /* CONFIG_SCSI_AM53C974 */
 #ifdef CONFIG_SCSI_NCR53C406A
 	{ "ncr53c406a=", NCR53c406a_setup},
-#endif
+#endif /* CONFIG_SCSI_NCR53C406A */
 #ifdef CONFIG_SCSI_SYM53C416
-	{ "sym53c416=", sym53c416_setup}, 
-#endif
+	{ "sym53c416=", sym53c416_setup},
+#endif /* CONFIG_SCSI_SYM53C416 */
 #ifdef CONFIG_SCSI_FUTURE_DOMAIN
 	{ "fdomain=", fdomain_setup},
-#endif
+#endif /* CONFIG_SCSI_FUTURE_DOMAIN */
 #ifdef CONFIG_SCSI_IN2000
 	{ "in2000=", in2000_setup},
-#endif
+#endif /* CONFIG_SCSI_IN2000 */
 #ifdef CONFIG_SCSI_7000FASST
 	{ "wd7000=", wd7000_setup},
-#endif
+#endif /* CONFIG_SCSI_7000FASST */
 #ifdef CONFIG_SCSI_PPA
         { "ppa=", ppa_setup },
-#endif
-#if defined(CONFIG_SCSI_DC390T) && ! defined(CONFIG_SCSI_DC390T_NOGENSUPP)
+#endif /* CONFIG_SCSI_PPA */
+#if defined(CONFIG_SCSI_DC390T) && !defined(CONFIG_SCSI_DC390T_NOGENSUPP)
 	{ "tmscsim=", dc390_setup },
-#endif
+#endif /* defined(CONFIG_SCSI_DC390T) && !defined(CONFIG_SCSI_DC390T_NOGENSUPP) */
 #ifdef CONFIG_BLK_DEV_XD
 	{ "xd=", xd_setup },
 	{ "xd_geo=", xd_manual_geo_init },
-#endif
+#endif /* CONFIG_BLK_DEV_XD */
 #ifdef CONFIG_BLK_DEV_FD
 	{ "floppy=", floppy_setup },
-#endif
+#endif /* CONFIG_BLK_DEV_FD */
 #ifdef CONFIG_CDU31A
 	{ "cdu31a=", cdu31a_setup },
-#endif CONFIG_CDU31A
+#endif /* CONFIG_CDU31A */
 #ifdef CONFIG_MCD
 	{ "mcd=", mcd_setup },
-#endif CONFIG_MCD
+#endif /* CONFIG_MCD */
 #ifdef CONFIG_MCDX
 	{ "mcdx=", mcdx_setup },
-#endif CONFIG_MCDX
+#endif /* CONFIG_MCDX */
 #ifdef CONFIG_SBPCD
 	{ "sbpcd=", sbpcd_setup },
-#endif CONFIG_SBPCD
+#endif /* CONFIG_SBPCD */
 #ifdef CONFIG_AZTCD
 	{ "aztcd=", aztcd_setup },
-#endif CONFIG_AZTCD
+#endif /* CONFIG_AZTCD */
 #ifdef CONFIG_CDU535
 	{ "sonycd535=", sonycd535_setup },
-#endif CONFIG_CDU535
+#endif /* CONFIG_CDU535 */
 #ifdef CONFIG_GSCD
 	{ "gscd=", gscd_setup },
-#endif CONFIG_GSCD
+#endif /* CONFIG_GSCD */
 #ifdef CONFIG_CM206
 	{ "cm206=", cm206_setup },
-#endif CONFIG_CM206
+#endif /* CONFIG_CM206 */
 #ifdef CONFIG_OPTCD
 	{ "optcd=", optcd_setup },
-#endif CONFIG_OPTCD
+#endif /* CONFIG_OPTCD */
 #ifdef CONFIG_SJCD
 	{ "sjcd=", sjcd_setup },
-#endif CONFIG_SJCD
+#endif /* CONFIG_SJCD */
 #ifdef CONFIG_ISP16_CDI
 	{ "isp16=", isp16_setup },
-#endif CONFIG_ISP16_CDI
+#endif /* CONFIG_ISP16_CDI */
 #ifdef CONFIG_SOUND
 	{ "sound=", sound_setup },
-#endif
+#endif /* CONFIG_SOUND */
 #ifdef CONFIG_ISDN_DRV_ICN
 	{ "icn=", icn_setup },
-#endif
+#endif /* CONFIG_ISDN_DRV_ICN */
 #ifdef CONFIG_ISDN_DRV_HISAX
        { "hisax=", HiSax_setup },
        { "HiSax=", HiSax_setup },
-#endif
+#endif /* CONFIG_ISDN_DRV_HISAX */
 #ifdef CONFIG_ISDN_DRV_PCBIT
 	{ "pcbit=", pcbit_setup },
-#endif
+#endif /* CONFIG_ISDN_DRV_PCBIT */
 #ifdef CONFIG_ATARIMOUSE
 	{ "atamouse=", atari_mouse_setup },
-#endif
+#endif /* CONFIG_ATARIMOUSE */
 #ifdef CONFIG_DMASOUND
 	{ "dmasound=", dmasound_setup },
-#endif
+#endif /* CONFIG_DMASOUND */
 #ifdef CONFIG_ATARI_SCSI
 	{ "atascsi=", atari_scsi_setup },
-#endif
+#endif /* CONFIG_ATARI_SCSI */
 #if defined(CONFIG_A3000_SCSI) || defined(CONFIG_A2091_SCSI) \
 	    || defined(CONFIG_GVP11_SCSI)
 	{ "wd33c93=", wd33c93_setup },
-#endif
+#endif /* defined(CONFIG_A3000_SCSI) || defined(CONFIG_A2091_SCSI) || defined(CONFIG_GVP11_SCSI */
 #if defined(CONFIG_GVP11_SCSI)
 	{ "gvp11=", gvp11_setup },
-#endif
+#endif /* defined(CONFIG_GVP11_SCSI) */
 #ifdef CONFIG_CYCLADES
 	{ "cyclades=", cy_setup },
-#endif
+#endif /* CONFIG_CYCLADES */
 #ifdef CONFIG_DIGI
 	{ "digi=", pcxx_setup },
-#endif
+#endif /* CONFIG_DIGI */
 #ifdef CONFIG_RISCOM8
 	{ "riscom8=", riscom8_setup },
-#endif
+#endif /* CONFIG_RISCOM8 */
 #ifdef CONFIG_SPECIALIX
 	{ "specialix=", specialix_setup },
-#endif
+#endif /* CONFIG_SPECIALIX */
 #ifdef CONFIG_BAYCOM
 	{ "baycom=", baycom_setup },
-#endif
+#endif /* CONFIG_BAYCOM */
 #ifdef CONFIG_BLK_CPQ_DA
 #ifdef CONFIG_BLK_CPQ_DA_EISA
        { "smart2=", cpqarray_setup },
-#endif
-#endif
+#endif /* CONFIG_BLK_CPQ_DA_EISA */
+#endif /* CONFIG_BLK_CPQ_DA */
 	{ 0, 0 }
 };
 
@@ -496,22 +496,22 @@
 
 #ifdef CONFIG_PARIDE_PD
        { "pd.", pd_setup },
-#endif
+#endif /* CONFIG_PARIDE_PD */
 #ifdef CONFIG_PARIDE_PCD
        { "pcd.", pcd_setup },
-#endif
+#endif /* CONFIG_PARIDE_PCD */
 #ifdef CONFIG_PARIDE_PF
        { "pf.", pf_setup },
-#endif
+#endif /* CONFIG_PARIDE_PF */
 #ifdef CONFIG_PARIDE_PT
        { "pt.", pt_setup },
-#endif
+#endif /* CONFIG_PARIDE_PT */
 #ifdef CONFIG_PARIDE_PG
        { "pg.", pg_setup },
-#endif
+#endif /* CONFIG_PARIDE_PG */
 #ifdef CONFIG_APM
 	{ "apm=", apm_setup },
-#endif
+#endif /* CONFIG_APM */
        { 0, 0 }
 } ;
 
@@ -541,7 +541,7 @@
 		rd_size = ints[1];
 }
 
-#endif
+#endif /* CONFIG_BLK_DEV_RAM */
 
 static int checksetup(char *line)
 {
@@ -550,15 +550,15 @@
 
 #ifdef CONFIG_BLK_DEV_IDE
 	/* ide driver needs the basic string, rather than pre-processed values */
-	if (!strncmp(line,"ide",3) || (!strncmp(line,"hd",2) && line[2] != '=')) {
+	if (!strncmp(line, "ide", 3) || (!strncmp(line, "hd", 2) && line[2] != '=')) {
 		ide_setup(line);
 		return 1;
 	}
-#endif
+#endif /* CONFIG_BLK_DEV_IDE */
 	while (bootsetups[i].str) {
 		int n = strlen(bootsetups[i].str);
-		if (!strncmp(line,bootsetups[i].str,n)) {
-			bootsetups[i].setup_func(get_options(line+n,ints), ints);
+		if (!strncmp(line, bootsetups[i].str, n)) {
+			bootsetups[i].setup_func(get_options(line+n, ints), ints);
 			return 1;
 		}
 		i++;
@@ -566,7 +566,7 @@
 
         for (i=0; raw_params[i].str; i++) {
                 int n = strlen(raw_params[i].str);
-                if (!strncmp(line,raw_params[i].str,n)) {
+                if (!strncmp(line, raw_params[i].str, n)) {
                         raw_params[i].setup_func(line+n, NULL);
                         return 1;
                 }
@@ -581,7 +581,7 @@
 
 #if defined(__SMP__) && defined(__i386__)
 unsigned long smp_loops_per_tick = 1000000;
-#endif
+#endif /* defined(__SMP__) && defined(__i386__) */
 
 /* This is the number of bits of precision for the loops_per_second.  Each
    bit takes on average 1.5/HZ seconds.  This (like the original) is a little
@@ -608,7 +608,7 @@
 		ticks = jiffies - ticks;
 		if (ticks)
 			break;
-		}
+	}
 
 /* Do a binary approximation to get loops_per_second set to equal one clock
    (up to lps_precision bits) */
@@ -633,7 +633,7 @@
 
 #if defined(__SMP__) && defined(__i386__)
 	smp_loops_per_tick = loops_per_sec / 400;
-#endif
+#endif /* defined(__SMP__) && defined(__i386__) */
 }
 
 static void parse_root_dev(char * line)
@@ -674,23 +674,23 @@
 		{ "sdo",     0x08e0 },
 		{ "sdp",     0x08f0 },
 #ifdef CONFIG_BLK_DEV_DAC960
-		{ "rd/c0d0p",0x3000 },
-		{ "rd/c0d1p",0x3008 },
-		{ "rd/c0d2p",0x3010 },
-		{ "rd/c0d3p",0x3018 },
-		{ "rd/c0d4p",0x3020 },
-		{ "rd/c0d5p",0x3028 },
-		{ "rd/c0d6p",0x3030 },
-		{ "rd/c0d7p",0x3038 },
-		{ "rd/c0d8p",0x3040 },
-		{ "rd/c0d9p",0x3048 },
-		{ "rd/c0d10p",0x3050 },
-		{ "rd/c0d11p",0x3058 },
-		{ "rd/c0d12p",0x3060 },
-		{ "rd/c0d13p",0x3068 },
-		{ "rd/c0d14p",0x3070 },
-		{ "rd/c0d15p",0x3078 },
-#endif
+		{ "rd/c0d0p", 0x3000 },
+		{ "rd/c0d1p", 0x3008 },
+		{ "rd/c0d2p", 0x3010 },
+		{ "rd/c0d3p", 0x3018 },
+		{ "rd/c0d4p", 0x3020 },
+		{ "rd/c0d5p", 0x3028 },
+		{ "rd/c0d6p", 0x3030 },
+		{ "rd/c0d7p", 0x3038 },
+		{ "rd/c0d8p", 0x3040 },
+		{ "rd/c0d9p", 0x3048 },
+		{ "rd/c0d10p", 0x3050 },
+		{ "rd/c0d11p", 0x3058 },
+		{ "rd/c0d12p", 0x3060 },
+		{ "rd/c0d13p", 0x3068 },
+		{ "rd/c0d14p", 0x3070 },
+		{ "rd/c0d15p", 0x3078 },
+#endif /* CONFIG_BLK_DEV_DAC960 */
 		{ "fd",      0x0200 },
 		{ "xda",     0x0d00 },
 		{ "xdb",     0x0d40 },
@@ -704,26 +704,26 @@
 		{ "sbpcd",   0x1900 },
 		{ "sonycd",  0x1800 },
 #ifdef CONFIG_PARIDE_PD
-       		{ "pda",     0x2d00 },
-       		{ "pdb",     0x2d10 },
-       		{ "pdc",     0x2d20 },
-       		{ "pdd",     0x2d30 },
-#endif
+		{ "pda",     0x2d00 },
+		{ "pdb",     0x2d10 },
+		{ "pdc",     0x2d20 },
+		{ "pdd",     0x2d30 },
+#endif /* CONFIG_PARIDE_PD */
 #ifdef CONFIG_PARIDE_PCD
-     	  	{ "pcd",     0x2e00 },
-#endif
+		{ "pcd",     0x2e00 },
+#endif /* CONFIG_PARIDE_PCD */
 #ifdef CONFIG_PARIDE_PF
-	       	{ "pf",      0x2f00 },
-#endif
+		{ "pf",      0x2f00 },
+#endif /* CONFIG_PARIDE_PF */
 		{ NULL, 0 }
 	};
 
-	if (strncmp(line,"/dev/",5) == 0) {
+	if (strncmp(line, "/dev/", 5) == 0) {
 		struct dev_name_struct *dev = devices;
 		line += 5;
 		do {
 			int len = strlen(dev->name);
-			if (strncmp(line,dev->name,len) == 0) {
+			if (strncmp(line, dev->name, len) == 0) {
 				line += len;
 				base = dev->num;
 				break;
@@ -731,7 +731,7 @@
 			dev++;
 		} while (dev->name);
 	}
-	ROOT_DEV = to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));
+	ROOT_DEV = to_kdev_t(base + simple_strtoul(line, NULL, base ? 10 : 16));
 }
 
 /*
@@ -755,12 +755,12 @@
 	envs = 1;	/* TERM is set to 'linux' by default */
 	next = line;
 	while ((line = next) != NULL) {
-		if ((next = strchr(line,' ')) != NULL)
+		if ((next = strchr(line, ' ')) != NULL)
 			*next++ = 0;
 		/*
 		 * check for kernel options first..
 		 */
-		if (!strncmp(line,"root=",5)) {
+		if (!strncmp(line, "root=", 5)) {
 			parse_root_dev(line+5);
 			continue;
 		}
@@ -786,20 +786,20 @@
 			nfs_root_addrs[sizeof(nfs_root_addrs)-1] = '\0';
 			continue;
 		}
-#endif
-		if (!strcmp(line,"ro")) {
+#endif /* CONFIG_ROOT_NFS */
+		if (!strcmp(line, "ro")) {
 			root_mountflags |= MS_RDONLY;
 			continue;
 		}
-		if (!strcmp(line,"rw")) {
+		if (!strcmp(line, "rw")) {
 			root_mountflags &= ~MS_RDONLY;
 			continue;
 		}
-		if (!strcmp(line,"debug")) {
+		if (!strcmp(line, "debug")) {
 			console_loglevel = 10;
 			continue;
 		}
-		if (!strncmp(line,"init=",5)) {
+		if (!strncmp(line, "init=", 5)) {
 			line += 5;
 			execute_command = line;
 			continue;
@@ -810,7 +810,7 @@
 		 * Then check if it's an environment variable or
 		 * an option.
 		 */
-		if (strchr(line,'=')) {
+		if (strchr(line, '=')) {
 			if (envs >= MAX_INIT_ENVS)
 				break;
 			envp_init[++envs] = line;
@@ -833,25 +833,25 @@
 /*
  *	Uniprocessor idle thread
  */
- 
+
 int cpu_idle(void *unused)
 {
 	for(;;)
 		idle();
 }
 
-#else
+#else /* !__SMP__ */
 
 /*
  *	Multiprocessor idle thread is in arch/...
  */
- 
+
 extern int cpu_idle(void * unused);
 
 /*
  *	Activate a secondary processor.
  */
- 
+
 asmlinkage void start_secondary(void)
 {
 	trap_init();
@@ -902,26 +902,26 @@
 		task[i]->next_run = task[i]->prev_run = task[i];
 		sti();
 	}
-}		
+}
 
 /*
  *	The autoprobe routines assume CPU#0 on the i386
  *	so we don't actually set the game in motion until
  *	they are finished.
  */
- 
+
 static void smp_begin(void)
 {
 	smp_threads_ready=1;
 	smp_commence();
 }
-	
-#endif
+
+#endif /* __SMP__ */
 
 /*
  *	Activate the first processor.
  */
- 
+
 asmlinkage void start_kernel(void)
 {
 	char * command_line;
@@ -932,18 +932,18 @@
 
 #ifdef __SMP__
 	static int first_cpu=1;
-	
+
 	if(!first_cpu)
 		start_secondary();
 	first_cpu=0;
-	
-#endif	
+
+#endif /* __SMP__ */
 /*
  * Interrupts are still disabled. Do necessary setups, then
  * enable them
  */
 	setup_arch(&command_line, &memory_start, &memory_end);
-	memory_start = paging_init(memory_start,memory_end);
+	memory_start = paging_init(memory_start, memory_end);
 	trap_init();
 	init_IRQ();
 	sched_init();
@@ -951,15 +951,15 @@
 	parse_options(command_line);
 #ifdef CONFIG_MODULES
 	init_modules();
-#endif
+#endif /* CONFIG_MODULES */
 #ifdef CONFIG_PROFILE
 	if (!prof_shift)
 #ifdef CONFIG_PROFILE_SHIFT
 		prof_shift = CONFIG_PROFILE_SHIFT;
-#else
+#else /* CONFIG_PROFILE_SHIFT */
 		prof_shift = 2;
-#endif
-#endif
+#endif /* !CONFIG_PROFILE_SHIFT */
+#endif /* CONFIG_PROFILE */
 	if (prof_shift) {
 		prof_buffer = (unsigned int *) memory_start;
 		/* only text is profiled */
@@ -968,29 +968,29 @@
 		memory_start += prof_len * sizeof(unsigned int);
 		memset(prof_buffer, 0, prof_len * sizeof(unsigned int));
 	}
-	memory_start = console_init(memory_start,memory_end);
+	memory_start = console_init(memory_start, memory_end);
 #ifdef CONFIG_PCI
-	memory_start = pci_init(memory_start,memory_end);
-#endif
-	memory_start = kmalloc_init(memory_start,memory_end);
+	memory_start = pci_init(memory_start, memory_end);
+#endif /* CONFIG_PCI */
+	memory_start = kmalloc_init(memory_start, memory_end);
 	sti();
 	calibrate_delay();
-	memory_start = inode_init(memory_start,memory_end);
-	memory_start = file_table_init(memory_start,memory_end);
-	memory_start = name_cache_init(memory_start,memory_end);
+	memory_start = inode_init(memory_start, memory_end);
+	memory_start = file_table_init(memory_start, memory_end);
+	memory_start = name_cache_init(memory_start, memory_end);
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start && initrd_start < memory_start) {
 		printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
-		    "disabling it.\n",initrd_start,memory_start);
+		    "disabling it.\n", initrd_start, memory_start);
 		initrd_start = 0;
 	}
-#endif
-	mem_init(memory_start,memory_end);
+#endif /* CONFIG_BLK_DEV_INITRD */
+	mem_init(memory_start, memory_end);
 	buffer_init();
 	sock_init();
 #if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)
 	ipc_init();
-#endif
+#endif /* defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD) */
 	dquot_init();
 	arch_syms_export();
 	sti();
@@ -998,16 +998,16 @@
 
 #if defined(CONFIG_MTRR) && defined(__SMP__)
 	init_mtrr_config();
-#endif
+#endif /* defined(CONFIG_MTRR) && defined(__SMP__) */
 
 
 	printk(linux_banner);
 #ifdef __SMP__
 	smp_init();
-#endif
+#endif /* __SMP__ */
 	sysctl_init();
-	/* 
-	 *	We count on the initial thread going ok 
+	/*
+	 *	We count on the initial thread going ok
 	 *	Like idlers init is an unlocked kernel thread, which will
 	 *	make syscalls (and thus be locked).
 	 */
@@ -1021,7 +1021,7 @@
  *
  * Right now task[0] just does a infinite idle loop.
  */
- 	cpu_idle(NULL);
+	cpu_idle(NULL);
 }
 
 static int printf(const char *fmt, ...)
@@ -1030,7 +1030,7 @@
 	int i;
 
 	va_start(args, fmt);
-	write(1,printbuf,i=vsprintf(printbuf, fmt, args));
+	write(1, printbuf, i=vsprintf(printbuf, fmt, args));
 	va_end(args);
 	return i;
 }
@@ -1038,16 +1038,16 @@
 static int do_rc(void * rc)
 {
 	close(0);
-	if (open(rc,O_RDONLY,0))
+	if (open(rc, O_RDONLY, 0))
 		return -1;
 	return execve("/bin/sh", argv_rc, envp_rc);
 }
 
 static int do_shell(void * shell)
 {
-	close(0);close(1);close(2);
+	close(0); close(1); close(2);
 	setsid();
-	(void) open("/dev/tty1",O_RDWR,0);
+	(void) open("/dev/tty1", O_RDWR, 0);
 	(void) dup(0);
 	(void) dup(0);
 	return execve(shell, argv, envp);
@@ -1060,24 +1060,24 @@
 
 	close(0);close(1);close(2);
 	setsid();
-	(void) open("/dev/tty1",O_RDWR,0);
+	(void) open("/dev/tty1", O_RDWR, 0);
 	(void) dup(0);
 	(void) dup(0);
 	return execve(shell, argv, envp_init);
 }
 
-static void no_initrd(char *s,int *ints)
+static void no_initrd(char *s, int *ints)
 {
 	mount_initrd = 0;
 }
-#endif
+#endif /* CONFIG_BLK_DEV_INITRD */
 
 static int init(void * unused)
 {
-	int pid,i;
+	int pid, i;
 #ifdef CONFIG_BLK_DEV_INITRD
 	int real_root_mountflags;
-#endif
+#endif /* CONFIG_BLK_DEV_INITRD */
 
 	/* Launch bdflush from here, instead of the old syscall way. */
 	kernel_thread(bdflush, NULL, 0);
@@ -1090,7 +1090,7 @@
 	real_root_mountflags = root_mountflags;
 	if (initrd_start && mount_initrd) root_mountflags &= ~MS_RDONLY;
 	else mount_initrd =0;
-#endif
+#endif /* CONFIG_BLK_DEV_INITRD */
 	setup();
 
 #ifdef __SMP__
@@ -1098,11 +1098,11 @@
 	 *	With the devices probed and setup we can
 	 *	now enter SMP mode.
 	 */
-	
+
 	smp_begin();
-#endif	
+#endif /* __SMP__ */
 
-	#ifdef CONFIG_UMSDOS_FS
+#ifdef CONFIG_UMSDOS_FS
 	{
 		/*
 			When mounting a umsdos fs as root, we detect
@@ -1110,47 +1110,47 @@
 			pseudo_root is defined in fs/umsdos/inode.c
 		*/
 		extern struct inode *pseudo_root;
-		if (pseudo_root != NULL){
+		if (pseudo_root != NULL) {
 			current->fs->root = pseudo_root;
 			current->fs->pwd  = pseudo_root;
 		}
 	}
-	#endif
+#endif /* CONFIG_UMSDOS_FS */
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	root_mountflags = real_root_mountflags;
-	if (mount_initrd && ROOT_DEV != real_root_dev && ROOT_DEV == MKDEV(RAMDISK_MAJOR,0)) {
+	if (mount_initrd && ROOT_DEV != real_root_dev && ROOT_DEV == MKDEV(RAMDISK_MAJOR, 0)) {
 		int error;
 
 		pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
 		if (pid>0)
 			while (pid != wait(&i));
 		if (real_root_dev != MKDEV(RAMDISK_MAJOR, 0)) {
-			error = change_root(real_root_dev,"/initrd");
+			error = change_root(real_root_dev, "/initrd");
 			if (error)
 				printk(KERN_ERR "Change root to /initrd: "
-				    "error %d\n",error);
+				    "error %d\n", error);
 		}
 	}
-#endif
-	
+#endif /* CONFIG_BLK_DEV_INITRD */
+
 	/*
 	 *	This keeps serial console MUCH cleaner, but does assume
 	 *	the console driver checks there really is a video device
 	 *	attached (Sparc effectively does).
 	 */
 
-	if ((open("/dev/tty1",O_RDWR,0) < 0) &&
-	    (open("/dev/ttyS0",O_RDWR,0) < 0))
+	if ((open("/dev/tty1", O_RDWR, 0) < 0) &&
+	    (open("/dev/ttyS0", O_RDWR, 0) < 0))
 		printk("Unable to open an initial console.\n");
-			
+
 	(void) dup(0);
 	(void) dup(0);
 
 	if (!execute_command) {
-		execve("/etc/init",argv_init,envp_init);
-		execve("/bin/init",argv_init,envp_init);
-		execve("/sbin/init",argv_init,envp_init);
+		execve("/etc/init", argv_init, envp_init);
+		execve("/bin/init", argv_init, envp_init);
+		execve("/sbin/init", argv_init, envp_init);
 		/* if this fails, fall through to original stuff */
 
 		pid = kernel_thread(do_rc, "/etc/rc", SIGCHLD);
@@ -1170,7 +1170,7 @@
 		while (1)
 			if (pid == wait(&i))
 				break;
-		printf("\n\rchild %d died with code %04x\n\r",pid,i);
+		printf("\n\rchild %d died with code %04x\n\r", pid, i);
 		sync();
 	}
 	return -1;
diff -u --recursive --new-file linux-2.0.39/kernel/printk.c linux-2.0.40/kernel/printk.c
--- linux-2.0.39/kernel/printk.c	Fri Jun  7 10:54:06 1996
+++ linux-2.0.40/kernel/printk.c	Sat Mar  3 16:45:30 2001
@@ -158,7 +158,7 @@
 	save_flags(flags);
 	cli();
 	va_start(args, fmt);
-	i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */
+	i = _vsnprintf(buf + 3, sizeof(buf) - sizeof(buf) / 8 - 3, fmt, args);
 	buf_end = buf + 3 + i;
 	va_end(args);
 	for (p = buf + 3; p < buf_end; p++) {
diff -u --recursive --new-file linux-2.0.39/kernel/sched.c linux-2.0.40/kernel/sched.c
--- linux-2.0.39/kernel/sched.c	Tue Oct  9 02:18:24 2001
+++ linux-2.0.40/kernel/sched.c	Tue Oct  9 02:18:18 2001
@@ -111,7 +111,7 @@
 {
 #ifdef __SMP__
 	int cpu=smp_processor_id();
-#endif	
+#endif
 #if 1	/* sanity tests */
 	if (p->next_run || p->prev_run) {
 		printk("task already on run-queue\n");
@@ -144,7 +144,7 @@
 		int i;
 		for (i=0;i<smp_num_cpus;i++)
 		{
-			if (0==current_set[cpu_logical_map[i]]->pid) 
+			if (0==current_set[cpu_logical_map[i]]->pid)
 			{
 				smp_message_pass(cpu_logical_map[i], MSG_RESCHEDULE, 0L, 0);
 				break;
@@ -241,15 +241,15 @@
 {
 	int weight;
 
-#ifdef __SMP__	
+#ifdef __SMP__
 	/* We are not permitted to run a task someone else is running */
 	if (p->processor != NO_PROC_ID)
 		return -1000;
-#ifdef PAST_2_0		
+#ifdef PAST_2_0
 	/* This process is locked to a processor group */
-	if (p->processor_mask && !(p->processor_mask & (1<<this_cpu))
+	if (p->processor_mask && !(p->processor_mask & (1<<this_cpu)))
 		return -1000;
-#endif		
+#endif
 #endif
 
 	/*
@@ -269,7 +269,7 @@
 	 */
 	weight = p->counter;
 	if (weight) {
-			
+
 #ifdef __SMP__
 		/* Give a largish advantage to the same processor...   */
 		/* (this is equivalent to penalizing other processors) */
@@ -425,11 +425,11 @@
 			}
 		default:
 			del_from_runqueue(prev);
-		case TASK_RUNNING:
+		case TASK_RUNNING:;
 	}
 	p = init_task.next_run;
 	sti();
-	
+
 #ifdef __SMP__
 	/*
 	 *	This is safe as we do not permit re-entry of schedule()
@@ -438,7 +438,7 @@
 #define idle_task (task[cpu_number_map[this_cpu]])
 #else
 #define idle_task (&init_task)
-#endif	
+#endif
 
 /*
  * Note! there may appear new tasks on the run-queue during this, as
@@ -464,11 +464,11 @@
 	/*
 	 *	Allocate process to CPU
 	 */
-	 
+
 	 next->processor = this_cpu;
 	 next->last_processor = this_cpu;
-#endif	 
-#ifdef __SMP_PROF__ 
+#endif
+#ifdef __SMP_PROF__
 	/* mark processor running an idle thread */
 	if (0==next->pid)
 		set_bit(this_cpu,&smp_idle_map);
@@ -591,8 +591,8 @@
  */
 static inline int waking_non_zero(struct semaphore *sem)
 {
-	int	ret ;
-	long	flags ;
+	int ret;
+	unsigned long flags;
 
 	get_buzz_lock(&sem->lock) ;
 	save_flags(flags) ;
@@ -695,12 +695,12 @@
 
 void __down(struct semaphore * sem)
 {
-	__do_down(sem,TASK_UNINTERRUPTIBLE) ; 
+	__do_down(sem, TASK_UNINTERRUPTIBLE);
 }
 
 int __down_interruptible(struct semaphore * sem)
 {
-	return(__do_down(sem,TASK_INTERRUPTIBLE)) ; 
+	return (__do_down(sem, TASK_INTERRUPTIBLE));
 }
 
 
@@ -1114,7 +1114,7 @@
 		time_adjust_step = tickadj;
 	     else if (time_adjust < -tickadj)
 		time_adjust_step = -tickadj;
-	     
+
 	    /* Reduce by this step the amount of time left  */
 	    time_adjust -= time_adjust_step;
 	}
@@ -1208,7 +1208,7 @@
 	do_process_times(p, user, system);
 	do_it_virt(p, user);
 	do_it_prof(p, ticks);
-}	
+}
 
 static void update_process_times(unsigned long ticks, unsigned long system)
 {
@@ -1235,9 +1235,9 @@
 	{
 		int i = cpu_logical_map[j];
 		struct task_struct *p;
-		
+
 #ifdef __SMP_PROF__
-		if (test_bit(i,&smp_idle_map)) 
+		if (test_bit(i,&smp_idle_map))
 			smp_idle_count[i]++;
 #endif
 		p = current_set[i];
@@ -1463,13 +1463,13 @@
 	p = find_process_by_pid(pid);
 	if (!p)
 		return -ESRCH;
-			
+
 	if (policy < 0)
 		policy = p->policy;
 	else if (policy != SCHED_FIFO && policy != SCHED_RR &&
 		 policy != SCHED_OTHER)
 		return -EINVAL;
-	
+
 	/*
 	 * Valid priorities for SCHED_FIFO and SCHED_RR are 1..99, valid
 	 * priority for SCHED_OTHER is 0.
@@ -1495,7 +1495,7 @@
 	return 0;
 }
 
-asmlinkage int sys_sched_setscheduler(pid_t pid, int policy, 
+asmlinkage int sys_sched_setscheduler(pid_t pid, int policy,
 				      struct sched_param *param)
 {
 	return setscheduler(pid, policy, param);
@@ -1516,7 +1516,7 @@
 	p = find_process_by_pid(pid);
 	if (!p)
 		return -ESRCH;
-			
+
 	return p->policy;
 }
 
@@ -1588,7 +1588,7 @@
 	if (error)
 		return error;
 
-	/* Values taken from 2.1.38 */	
+	/* Values taken from 2.1.38 */
 	t.tv_sec = 0;
 	t.tv_nsec = 150000;   /* is this right for non-intel architecture too?*/
 	memcpy_tofs(interval, &t, sizeof(struct timespec));
@@ -1597,7 +1597,7 @@
 }
 
 /*
- * change timeval to jiffies, trying to avoid the 
+ * change timeval to jiffies, trying to avoid the
  * most obvious overflows..
  */
 static unsigned long timespectojiffies(struct timespec *value)
@@ -1783,7 +1783,7 @@
 	 *	process right in SMP mode.
 	 */
 	int cpu=smp_processor_id();
-#ifndef __SMP__	
+#ifndef __SMP__
 	current_set[cpu]=&init_task;
 #else
 	init_task.processor=cpu;
diff -u --recursive --new-file linux-2.0.39/lib/vsprintf.c linux-2.0.40/lib/vsprintf.c
--- linux-2.0.39/lib/vsprintf.c	Tue Aug  1 09:02:48 1995
+++ linux-2.0.40/lib/vsprintf.c	Sat Mar  3 16:45:30 2001
@@ -131,7 +131,7 @@
 	return str;
 }
 
-int vsprintf(char *buf, const char *fmt, va_list args)
+int _vsnprintf(char *buf, int n, const char *fmt, va_list args)
 {
 	int len;
 	unsigned long num;
@@ -146,7 +146,7 @@
 				   number of chars for from string */
 	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
 
-	for (str=buf ; *fmt ; ++fmt) {
+	for (str = buf; *fmt && (n == -1 || str - buf < n); ++fmt) {
 		if (*fmt != '%') {
 			*str++ = *fmt;
 			continue;
@@ -220,6 +220,12 @@
 
 			len = strnlen(s, precision);
 
+			if (n != -1 && len >= n - (str - buf)) {
+				len = n - 1 - (str - buf);
+				if (len <= 0) break;
+				if (len < field_width) field_width = len;
+			}
+
 			if (!(flags & LEFT))
 				while (len < field_width--)
 					*str++ = ' ';
@@ -291,6 +297,11 @@
 	}
 	*str = '\0';
 	return str-buf;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+	return _vsnprintf(buf, -1, fmt, args);
 }
 
 int sprintf(char * buf, const char *fmt, ...)
diff -u --recursive --new-file linux-2.0.39/mm/kmalloc.c linux-2.0.40/mm/kmalloc.c
--- linux-2.0.39/mm/kmalloc.c	Fri Nov  7 18:57:31 1997
+++ linux-2.0.40/mm/kmalloc.c	Mon Oct  8 14:06:31 2001
@@ -21,9 +21,6 @@
 #include <asm/system.h>
 #include <asm/dma.h>
 
-/* Define this if you want slow routines that try to trip errors */
-#undef SADISTIC_KMALLOC
-
 /* Private flags. */
 
 #define MF_USED 0xffaa0055
@@ -295,7 +292,7 @@
 	bucket->nbytesmalloced += size;
 	p->bh_flags = type;	/* As of now this block is officially in use */
 	p->bh_length = size;
-#ifdef SADISTIC_KMALLOC
+#if CONFIG_SADISTIC_KMALLOC
 	memset(p+1, 0xf0, size);
 #endif
 	return p + 1;		/* Pointer arithmetic: increments past header */
@@ -405,7 +402,7 @@
 	if (ptr->bh_flags != MF_USED)
 		goto bad_order;
 	ptr->bh_flags = MF_FREE;	/* As of now this block is officially free */
-#ifdef SADISTIC_KMALLOC
+#if CONFIG_SADISTIC_KMALLOC
 	memset(ptr+1, 0xe0, ptr->bh_length);
 #endif
 	save_flags(flags);
diff -u --recursive --new-file linux-2.0.39/net/core/skbuff.c linux-2.0.40/net/core/skbuff.c
--- linux-2.0.39/net/core/skbuff.c	Sun Nov 15 19:33:21 1998
+++ linux-2.0.40/net/core/skbuff.c	Mon Oct  8 14:06:31 2001
@@ -15,6 +15,8 @@
  *		Alan Cox	:	Added all the changed routines Linus
  *					only put in the headers
  *		Ray VanTassle	:	Fixed --skb->lock in free
+ *	Michael Deutschmann	:	Corrected and expanded
+ *					CONFIG_SKB_CHECK system.
  *
  *	TO FIX:
  *		The __skb_ routines ought to check interrupts are disabled
@@ -81,79 +83,166 @@
 
 #if CONFIG_SKB_CHECK
 
-/*
- *	Debugging paranoia. Can go later when this crud stack works
+/* Verify that an SKB has an appropriate magic number, and note the list 
+ * to which it belongs.
+ *
+ * If (*list) is NULL, it will be overwritten with the list membership of 
+ * this SKB (which might also be null).  Otherwise, an error will be 
+ * reported if the SKB does not belong to the same list.
+ */
+static __inline__ int skb_magiccheck(struct sk_buff *skb,
+				     struct sk_buff_head **list,
+				     int line,
+				     char *file, 
+				     char *direct)
+{
+	struct sk_buff_head *list2;
+
+	if (!skb) {
+		printk("File: %s Line %d, found a null skb pointer (%s)\n",
+			file,line,direct);
+		return -1;
+	}
+
+	if (skb->magic_debug_cookie == SK_HEAD_SKB) { 
+		list2 = (struct sk_buff_head *) skb;
+		goto match_list;
+	}
+
+	if (skb->magic_debug_cookie == SK_GOOD_SKB) {
+		list2 = skb->list;
+	match_list:
+		if (!*list) *list = list2;
+
+		if (*list == list2) 
+			return 0;
+
+		printk("File %s: Line %d, list mismatch on linked skb (%s)\n",
+		       file,line,direct);
+		return -1;
+	}
+
+	if (skb->magic_debug_cookie == SK_FREED_SKB) {
+		printk("File: %s Line %d, found a freed skb (%s)\n",
+		       file,line,direct);
+		printk("skb=%p, real size=%d, free=%d\n",
+		       skb,skb->truesize,skb->free);
+		return -1;
+	}
+
+	printk("File: %s Line %d, found an invalid skb (%s)\n",
+	       file,line,direct);
+
+	return -1;
+}
+
+/* Check that the links on an SKB both point to valid SKBs in the same 
+ * list, and are reciprocal (s->p->n == s == s->n->p) 
  */
+static __inline__ int skb_linkscheck(struct sk_buff *skb,
+				     struct sk_buff_head *list,
+				     int line, 
+				     char *file)
+{
+	if (list->magic_debug_cookie != SK_HEAD_SKB) {
+		printk("File %s: Line %d, skb list is not skb-head\n",
+		       file,line);
+		return -1;
+	}
+
+	if (skb_magiccheck(skb->next,&list,line,file,"next"))
+		return -1;
+
+	if (skb_magiccheck(skb->prev,&list,line,file,"prev"))
+		return -1;
+
+	if (skb->next->prev != skb ||
+	    skb->prev->next != skb) {
+		printk("File %s: Line %d, skb links not reciprocal\n",
+		       file,line);
+		return -1;
+	}
+	return 0;
+}
 
-int skb_check(struct sk_buff *skb, int head, int line, char *file)
+/* Checks specific to sk_buff_head objects.  This actually devolves to 
+ * linkscheck unless whole-queue paranoia is enabled.
+ */
+static __inline__ int skb_headcheck(struct sk_buff_head *list,
+				    int line, char *file)
 {
-	if (head) {
-		if (skb->magic_debug_cookie != SK_HEAD_SKB) {
-			printk("File: %s Line %d, found a bad skb-head\n",
-				file,line);
-			return -1;
-		}
-		if (!skb->next || !skb->prev) {
-			printk("skb_check: head without next or prev\n");
-			return -1;
-		}
-		if (skb->next->magic_debug_cookie != SK_HEAD_SKB
-			&& skb->next->magic_debug_cookie != SK_GOOD_SKB) {
-			printk("File: %s Line %d, bad next head-skb member\n",
-				file,line);
+#if CONFIG_SKB_CHECK_WHOLE_QUEUE	
+	struct sk_buff *skb = (struct sk_buff *) list;
+
+	int qlen = 0;			
+
+	while (skb->next != (struct sk_buff *) list) {	
+		if (skb_magiccheck(skb->next,&list,line,file,"scan")); 
 			return -1;
-		}
-		if (skb->prev->magic_debug_cookie != SK_HEAD_SKB
-			&& skb->prev->magic_debug_cookie != SK_GOOD_SKB) {
-			printk("File: %s Line %d, bad prev head-skb member\n",
-				file,line);
+
+		if (skb->next->prev != skb) {
+			printk("File %s: Line %d, nonreciprocal links"
+			       " in skb queue\n",file,line);
 			return -1;
 		}
-#if 0
-		{
-		struct sk_buff *skb2 = skb->next;
-		int i = 0;
-		while (skb2 != skb && i < 5) {
-			if (skb_check(skb2, 0, line, file) < 0) {
-				printk("bad queue element in whole queue\n");
-				return -1;
-			}
-			i++;
-			skb2 = skb2->next;
-		}
-		}
-#endif
-		return 0;
-	}
-	if (skb->next != NULL && skb->next->magic_debug_cookie != SK_HEAD_SKB
-		&& skb->next->magic_debug_cookie != SK_GOOD_SKB) {
-		printk("File: %s Line %d, bad next skb member\n",
-			file,line);
+
+		qlen++;
+		skb = skb->next;
+	} 
+
+	if (list->prev != skb)
+	{
+		printk("File %s: Line %d, skb-head prev link not"
+		       " consistent\n",file,line);
 		return -1;
 	}
-	if (skb->prev != NULL && skb->prev->magic_debug_cookie != SK_HEAD_SKB
-		&& skb->prev->magic_debug_cookie != SK_GOOD_SKB) {
-		printk("File: %s Line %d, bad prev skb member\n",
-			file,line);
+
+	if (qlen != list->qlen) {
+		printk("File %s: Line %d, skb-head queue length wrong\n",
+		       file,line);
 		return -1;
 	}
+	return 0;
+#else	/* ! CONFIG_SKB_CHECK_WHOLE_QUEUE */
+	return skb_linkscheck( (struct sk_buff *) list, list, line, file);
+#endif	/* ! CONFIG_SKB_CHECK_WHOLE_QUEUE */
+}	
 
 
-	if(skb->magic_debug_cookie==SK_FREED_SKB)
-	{
-		printk("File: %s Line %d, found a freed skb lurking in the undergrowth!\n",
-			file,line);
-		printk("skb=%p, real size=%d, free=%d\n",
-			skb,skb->truesize,skb->free);
+/*
+ *	Debugging paranoia.
+ */
+int skb_check(struct sk_buff *skb, int type, int line, char *file)
+{
+	struct sk_buff_head *list = NULL;
+
+	if (skb_magiccheck(skb,&list,line,file,"self"))
+		return -1;
+
+	if (skb->magic_debug_cookie == SK_HEAD_SKB) {
+		if (type != 0) 
+			return skb_headcheck(list,line,file);
+
+		printk("File %s: Line %d, found skb-head instead of skb\n",
+		       file,line);
 		return -1;
 	}
-	if(skb->magic_debug_cookie!=SK_GOOD_SKB)
-	{
-		printk("File: %s Line %d, passed a non skb!\n", file,line);
-		printk("skb=%p, real size=%d, free=%d\n",
-			skb,skb->truesize,skb->free);
+
+	if (list) {
+		if (type == 3) {
+			printk("File %s: Line %d, skb is already linked\n",
+			       file,line);
+			return -1;
+		}
+		if (skb_linkscheck(skb,list,line,file))
+			return -1;
+	}
+	else if (skb->prev || skb->next) {
+		printk("File %s: Line %d, skb has prev/next field,"
+		       " but no list\n",file,line);
 		return -1;
 	}
+
 	if(skb->head>skb->data)
 	{
 		printk("File: %s Line %d, head > data !\n", file,line);
@@ -182,7 +271,8 @@
 			skb,skb->data,skb->end,skb->len);
 		return -1;
 	}
-	if((unsigned long) skb->end > (unsigned long) skb)
+	if((unsigned long) skb->end > 
+           (unsigned long) (skb->data_skb ? skb->data_skb : skb))
 	{
 		printk("File: %s Line %d, control overrun\n", file,line);
 		printk("skb=%p, end=%p\n",
@@ -217,7 +307,7 @@
 	save_flags(flags);
 	cli();
 
-	IS_SKB(newsk);
+	IS_SKB_UNLINKED(newsk);
 	IS_SKB_HEAD(list);
 	if (newsk->next || newsk->prev)
 		printk("Suspicious queue head: sk_buff on list!\n");
@@ -238,7 +328,7 @@
 	struct sk_buff *list = (struct sk_buff *)list_;
 
 
-	IS_SKB(newsk);
+	IS_SKB_UNLINKED(newsk);
 	IS_SKB_HEAD(list);
 	if (newsk->next || newsk->prev)
 		printk("Suspicious queue head: sk_buff on list!\n");
@@ -266,7 +356,7 @@
 
 	if (newsk->next || newsk->prev)
 		printk("Suspicious queue tail: sk_buff on list!\n");
-	IS_SKB(newsk);
+	IS_SKB_UNLINKED(newsk);
 	IS_SKB_HEAD(list);
 
 	newsk->next = list;
@@ -287,7 +377,7 @@
 
 	if (newsk->next || newsk->prev)
 		printk("Suspicious queue tail: sk_buff on list!\n");
-	IS_SKB(newsk);
+	IS_SKB_UNLINKED(newsk);
 	IS_SKB_HEAD(list);
 
 	newsk->next = list;
@@ -332,7 +422,7 @@
 	
 	restore_flags(flags);
 
-	IS_SKB(result);
+	IS_SKB_UNLINKED(result);
 	return result;
 }
 
@@ -356,7 +446,7 @@
 	list_->qlen--;
 	result->list = NULL;
 	
-	IS_SKB(result);
+	IS_SKB_UNLINKED(result);
 	return result;
 }
 
@@ -367,8 +457,8 @@
 {
 	unsigned long flags;
 
-	IS_SKB(old);
-	IS_SKB(newsk);
+	IS_SKB_LINKED(old);
+	IS_SKB_UNLINKED(newsk);
 
 	if(!old->next || !old->prev)
 		printk("insert before unlisted item!\n");
@@ -395,9 +485,9 @@
 	struct sk_buff * prev, struct sk_buff *next,
 	struct sk_buff_head * list)
 {
-	IS_SKB(prev);
-	IS_SKB(newsk);
-	IS_SKB(next);
+	IS_SKB_LINKED(prev);
+	IS_SKB_UNLINKED(newsk);
+	IS_SKB_LINKED(next);
 
 	if(!prev->next || !prev->prev)
 		printk("insert after unlisted item!\n");
@@ -422,8 +512,8 @@
 {
 	unsigned long flags;
 
-	IS_SKB(old);
-	IS_SKB(newsk);
+	IS_SKB_LINKED(old);
+	IS_SKB_UNLINKED(newsk);
 
 	if(!old->next || !old->prev)
 		printk("append before unlisted item!\n");
@@ -474,10 +564,13 @@
 	restore_flags(flags);
 }
 
-void __skb_unlink(struct sk_buff *skb)
+void __skb_unlink(struct sk_buff *skb,struct sk_buff_head *list)
 {
 	IS_SKB(skb);
 
+        if(skb->list != list)
+		printk("__skb_unlink called with wrong list argument\n");
+
 	if(skb->list)
 	{
 		skb->list->qlen--;
@@ -581,9 +674,9 @@
 			__builtin_return_address(0));
 		return;
   	}
-#if CONFIG_SKB_CHECK
-	IS_SKB(skb);
-#endif
+
+	IS_SKB_UNLINKED(skb);
+
 	/* Check it twice, this is such a rare event and only occurs under
 	 * extremely high load, normal code path should not suffer from the
 	 * overhead of the cli.
diff -u --recursive --new-file linux-2.0.39/net/ipv4/tcp.c linux-2.0.40/net/ipv4/tcp.c
--- linux-2.0.39/net/ipv4/tcp.c	Wed Dec 29 12:33:34 1999
+++ linux-2.0.40/net/ipv4/tcp.c	Mon Oct  8 14:06:31 2001
@@ -206,6 +206,7 @@
  *		David S. Miller	:	New socket lookup architecture for ISS.
  *					This code is dedicated to John Dyson.
  *		Elliot Poger	:	Added support for SO_BINDTODEVICE.
+ *	Michael Deutschmann	:	Added some IS_SKBs in tcp_recvmsg.
  *					
  * To Fix:
  *		Fast path the code. Two things here - fix the window calculation
@@ -1652,9 +1653,11 @@
 
 		current->state = TASK_INTERRUPTIBLE;
 
+		IS_SKB_HEAD((struct sk_buff *)&sk->receive_queue);
 		skb = sk->receive_queue.next;
 		while (skb != (struct sk_buff *)&sk->receive_queue)
 		{
+			IS_SKB_LINKED(skb);
 			if (before(*seq, skb->seq))
 				break;
 			offset = *seq - skb->seq;
diff -u --recursive --new-file linux-2.0.39/net/ipv4/tcp_input.c linux-2.0.40/net/ipv4/tcp_input.c
--- linux-2.0.39/net/ipv4/tcp_input.c	Tue Apr 25 16:16:38 2000
+++ linux-2.0.40/net/ipv4/tcp_input.c	Mon Oct  8 14:06:31 2001
@@ -46,6 +46,7 @@
  *					</RANT>
  *	George Baeslack		:	SIGIO delivery on accept() bug that
  *					affected sun jdk.
+ *	Michael Deutschmann	:	Added IS_SKBs to tcp_insert_skb
  */
 
 #include <linux/config.h>
@@ -1897,6 +1898,8 @@
 	struct sk_buff * prev, * next;
 	u32 seq;
 
+	IS_SKB_UNLINKED(skb);
+
 	/*
 	 * Find where the new skb goes.. (This goes backwards,
 	 * on the assumption that we get the packets in order)
@@ -1904,7 +1907,9 @@
 	seq = skb->seq;
 	prev = list->prev;
 	next = (struct sk_buff *) list;
+	IS_SKB_HEAD(next);
 	for (;;) {
+		IS_SKB_LINKED(prev);
 		if (prev == (struct sk_buff *) list || !after(prev->seq, seq))
 			break;
 		next = prev;
diff -u --recursive --new-file linux-2.0.39/scripts/checkconfig.pl linux-2.0.40/scripts/checkconfig.pl
--- linux-2.0.39/scripts/checkconfig.pl	Sun Nov 15 19:33:23 1998
+++ linux-2.0.40/scripts/checkconfig.pl	Fri Aug 10 18:16:56 2001
@@ -14,6 +14,7 @@
 
     # Initialize variables.
     my $fInComment   = 0;
+    my $fInString    = 0;
     my $fUseConfig   = 0;
     my $iLinuxConfig = 0;
     my %configList   = ();
@@ -25,12 +26,23 @@
 	m+/\*+o && (s+/\*.*?\*/+ +go, (s+/\*.*$+ +o && ($fInComment = 1)));
 
 	# Pick up definitions.
-	if ( m/^#/o )
+	if ( m/^\s*#/o )
 	{
-	    $iLinuxConfig      = $. if m/^#\s*include\s*<linux\/config\.h>/o;
-	    $configList{uc $1} = 1  if m/^#\s*include\s*<config\/(\S*)\.h>/o;
-	    $configList{$1}    = 1  if m/^#\s*define\s+CONFIG_(\w*)/o;
-	    $configList{$1}    = 1  if m/^#\s*undef\s+CONFIG_(\w*)/o;
+	    $iLinuxConfig      = $. if m/^\s*#\s*include\s*"linux\/config\.h"/o;
+	    $configList{uc $1} = 1  if m/^\s*#\s*include\s*"config\/(\S*)\.h"/o;
+	}
+
+	# Strip strings.
+	$fInString && (s+^.*?"+ +o ? ($fInString = 0) : next);
+	m+"+o && (s+".*?"+ +go, (s+".*$+ +o && ($fInString = 1)));
+
+	# Pick up definitions.
+	if ( m/^\s*#/o )
+	{
+	    $iLinuxConfig      = $. if m/^\s*#\s*include\s*<linux\/config\.h>/o;
+	    $configList{uc $1} = 1  if m/^\s*#\s*include\s*<config\/(\S*)\.h>/o;
+	    $configList{$1}    = 1  if m/^\s*#\s*define\s+CONFIG_(\w*)/o;
+	    $configList{$1}    = 1  if m/^\s*#\s*undef\s+CONFIG_(\w*)/o;
 	}
 
 	# Look for usages.
@@ -47,7 +59,7 @@
 
     # Report superfluous includes.
     if ( $iLinuxConfig && ! $fUseConfig )
-	{ print "$file: $iLinuxConfig: <linux/config.h> not needed.\n"; }
+	{ print "$file: $iLinuxConfig: linux/config.h not needed.\n"; }
 
     close(FILE);
 }
diff -u --recursive --new-file linux-2.0.39/scripts/checkhelp.pl linux-2.0.40/scripts/checkhelp.pl
--- linux-2.0.39/scripts/checkhelp.pl	Thu Jan  1 01:00:00 1970
+++ linux-2.0.40/scripts/checkhelp.pl	Fri Aug 10 18:15:58 2001
@@ -0,0 +1,30 @@
+#!/usr/bin/perl
+# checkhelp.pl - finds configuration options that have no
+#                corresponding section in the help file
+#
+# made by Meelis Roos (mroos@tartu.cyber.ee)
+
+# read the help file
+@options=split /\n/, `grep '^CONFIG' Documentation/Configure.help`;
+die "Can't read Documentation/Configure.help\n" if $#options == -1;
+
+#read all the files
+foreach $file (@ARGV)
+{
+	open (FILE, $file) || die "Can't open $file: $!\n";
+	while (<FILE>) {
+		# repeat until no CONFIG_* are left
+		while (/^\s*(bool|tristate|dep_tristate|string|int|hex).*' *(.*)'.*(CONFIG_\w*)/) {
+			$what=$3;
+			$name=$2;
+			s/$3//;
+			@found = grep (/$what$/, @options);
+			if ($#found == -1) {
+				next if $nohelp{$what};
+				print "$name\n$what\n  No help for $what\n\n";
+				$nohelp{$what}=1;
+			}
+		}
+	}
+	close (FILE);
+}
diff -u --recursive --new-file linux-2.0.39/scripts/checkincludes.pl linux-2.0.40/scripts/checkincludes.pl
--- linux-2.0.39/scripts/checkincludes.pl	Thu Jan  1 01:00:00 1970
+++ linux-2.0.40/scripts/checkincludes.pl	Fri Aug 10 18:16:02 2001
@@ -0,0 +1,24 @@
+#!/usr/bin/perl
+#
+# checkincludes: Find files included more than once in (other) files.
+# Copyright abandoned, 2000, Niels Kristian Bech Jensen <nkbj@image.dk>.
+
+foreach $file (@ARGV) {
+	open(FILE, $file) or die "Cannot open $file: $!.\n";
+
+	my %includedfiles = ();
+
+	while (<FILE>) {
+		if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) {
+			++$includedfiles{$1};
+		}
+	}
+	
+	foreach $filename (keys %includedfiles) {
+		if ($includedfiles{$filename} > 1) {
+			print "$file: $filename is included more than once.\n";
+		}
+	}
+
+	close(FILE);
+}
diff -u --recursive --new-file linux-2.0.39/scripts/mkdep.c linux-2.0.40/scripts/mkdep.c
--- linux-2.0.39/scripts/mkdep.c	Tue Oct  8 18:33:56 1996
+++ linux-2.0.40/scripts/mkdep.c	Mon Oct  8 14:06:49 2001
@@ -65,17 +65,17 @@
 #endif
 
 #define GETNEXT { \
+if (next == end) \
+	break; \
 next_byte(__buf); \
 if (!__nrbuf) { \
 	__buf = *(unsigned long *) next; \
 	__nrbuf = sizeof(unsigned long); \
-	if (!__buf) \
-		break; \
 } next++; __nrbuf--; }
 #define CASE(c,label) if (current == c) goto label
 #define NOTCASE(c,label) if (current != c) goto label
 
-static void state_machine(register char *next)
+static void state_machine(register char *next, register char *end)
 {
 	for(;;) {
 	register unsigned long __buf = 0;
@@ -244,7 +244,7 @@
 		return;
 	}
 	close(fd);
-	state_machine(map);
+	state_machine(map, map + st.st_size);
 	munmap(map, mapsize);
 	if (hasdep)
 		puts(command);
