[BACK]Return to kdb-i386 CVS log [TXT][DIR] Up to [Development] / linux-2.4-xfs / split-patches

File: [Development] / linux-2.4-xfs / split-patches / kdb-i386 (download)

Revision 1.2, Mon Aug 9 04:20:28 2004 UTC (13 years, 2 months ago) by nathans
Branch: MAIN
Changes since 1.1: +6206 -6240 lines

Update 2.4 split patches for 2.4.27 merge.

%patch
Index: 2.4.x-xfs/arch/i386/Makefile
===================================================================
--- 2.4.x-xfs.orig/arch/i386/Makefile	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/arch/i386/Makefile	Mon Aug  9 13:54:51 2004
@@ -101,6 +101,12 @@
 CORE_FILES := arch/i386/kernel/kernel.o arch/i386/mm/mm.o $(CORE_FILES)
 LIBS := $(TOPDIR)/arch/i386/lib/lib.a $(LIBS) $(TOPDIR)/arch/i386/lib/lib.a
 
+ifdef CONFIG_KDB
+LIBS := $(LIBS) $(TOPDIR)/arch/i386/kdb/kdba.o
+SUBDIRS := $(SUBDIRS) arch/i386/kdb
+CFLAGS += $(call check_gcc,-fno-optimize-sibling-calls,)
+endif
+
 ifdef CONFIG_MATH_EMULATION
 SUBDIRS += arch/i386/math-emu
 DRIVERS += arch/i386/math-emu/math.o
@@ -112,6 +118,11 @@
 arch/i386/mm: dummy
 	$(MAKE) linuxsubdirs SUBDIRS=arch/i386/mm
 
+ifdef CONFIG_KDB
+arch/i386/kdb: dummy
+	$(MAKE) linuxsubdirs SUBDIRS=arch/i386/kdb
+endif
+
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
 vmlinux: arch/i386/vmlinux.lds
Index: 2.4.x-xfs/arch/i386/config.in
===================================================================
--- 2.4.x-xfs.orig/arch/i386/config.in	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/arch/i386/config.in	Mon Aug  9 13:54:51 2004
@@ -479,6 +479,19 @@
    bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
    bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
    bool '  Compile the kernel with frame pointers' CONFIG_FRAME_POINTER
+   bool '  Built-in Kernel Debugger support' CONFIG_KDB
+   dep_tristate '    KDB modules' CONFIG_KDB_MODULES $CONFIG_KDB
+   if [ "$CONFIG_KDB" = "y" ]; then
+      bool '    KDB off by default' CONFIG_KDB_OFF
+      int  '    KDB continues after catastrophic errors' CONFIG_KDB_CONTINUE_CATASTROPHIC 0
+      if [ "$CONFIG_USB" != "n" ] ; then
+      	bool '    Support for USB Keyboard in KDB' CONFIG_KDB_USB
+      fi
+      comment '  Load all symbols for debugging is required for KDB'
+      define_bool CONFIG_KALLSYMS y
+   else
+      bool '  Load all symbols for debugging' CONFIG_KALLSYMS
+   fi
 fi
 
 int 'Kernel messages buffer length shift (0 = default)' CONFIG_LOG_BUF_SHIFT 0
Index: 2.4.x-xfs/arch/i386/kdb/ChangeLog
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kdb/ChangeLog	Thu Jan  1 10:00:00 1970
+++ 2.4.x-xfs/arch/i386/kdb/ChangeLog	Mon Aug  9 13:54:51 2004
@@ -0,0 +1,209 @@
+2004-02-19 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.4.25-i386-1.
+
+2004-02-11 Keith Owens  <kaos@sgi.com>
+
+	* Adjust for LDT changes in i386 mainline.
+	* kdb v4.3-2.4.25-rc1-i386-1.
+
+2003-12-01 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.4.23-i386-1.
+
+2003-11-11 Keith Owens  <kaos@sgi.com>
+
+	* Do not use USB keyboard if it has not been probed.
+	* kdb v4.3-2.4.23-rc1-i386-1.
+
+2003-08-29 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.4.22-i386-1.
+
+2003-08-05 Keith Owens  <kaos@sgi.com>
+
+	* Remove duplicate setting of trap for machine_check.
+	* Only reset keyboard when CONFIG_VT_CONSOLE is defined.
+
+2003-07-27 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.4.22-pre8-i386-5.
+
+2003-07-20 Keith Owens  <kaos@sgi.com>
+
+	* Remove compile warning on x86 commands.
+	* kdb v4.3-2.4.21-i386-5.
+
+2003-07-08 Keith Owens  <kaos@sgi.com>
+
+	* Add new x86 commands - rdv, gdt, idt, ldt, ldtp, ptex.
+	  Vamsi Krishna S., IBM.
+	* kdb v4.3-2.4.21-i386-4.
+
+2003-07-01 Keith Owens  <kaos@sgi.com>
+
+	* Convert kdba_find_return() to two passes to reduce false positives.
+	* Correct jmp disp8 offset calculation for out of line lock code.
+	* Use NMI for kdb IPI in clustered APIC mode.  Sachin Sant, IBM.
+	* kdb v4.3-2.4.21-i386-3.
+
+2003-06-23 Keith Owens  <kaos@sgi.com>
+
+	* Sync with XFS 2.4.21 tree.
+	* kdb v4.3-2.4.21-i386-2.
+
+2003-06-20 Keith Owens  <kaos@sgi.com>
+
+	* kdb v4.3-2.4.21-i386-1.
+
+2003-06-20 Keith Owens  <kaos@sgi.com>
+
+	* Add CONFIG_KDB_CONTINUE_CATASTROPHIC.
+	* Correct KDB_ENTER() definition.
+	* kdb v4.3-2.4.20-i386-1.
+
+2003-05-02 Keith Owens  <kaos@sgi.com>
+
+	* Add kdba_fp_value().
+	* Limit backtrace size to catch loops.
+	* Add read/write access to user pages.  Vamsi Krishna S., IBM
+	* Clean up USB keyboard support.  Steven Dake.
+	* kdb v4.2-2.4.20-i386-1.
+
+2003-04-04 Keith Owens  <kaos@sgi.com>
+
+	* Workarounds for scheduler bugs.
+	* kdb v4.1-2.4.20-i386-1.
+
+2003-03-16 Keith Owens  <kaos@sgi.com>
+
+	* Each cpu saves its state as it enters kdb or before it enters code
+	  which cannot call kdb, converting kdb from a pull to a push model.
+	* Clean up kdb interaction with CONFIG_SERIAL_CONSOLE.
+	* Removal of special cases for i386 backtrace from common code
+	  simplifies the architecture code.
+	* Add command to dump i386 struct pt_regs.
+	* kdb v4.0-2.4.20-i386-1.
+
+2003-02-03 Keith Owens  <kaos@sgi.com>
+
+	* Register kdb commands early.
+	* Handle KDB_ENTER() when kdb=off.
+	* Optimize __kdba_getarea_size when width is a constant.
+	* Decode oops via kallsyms if it is available.
+	* Update copyright notices to 2003.
+	* Handle call *disp32(%reg) in backtrace.
+	* Correct keyboard freeze.  Ashish Kalra.
+	* Add command history and editing.  Sonic Zhang.
+	* kdb_toggleled is conditional on KDB_BLINK_LED.  Bernhard Fischer.
+	* Allow tab on serial line for symbol completion.
+	* Ignore KDB_ENTER() when kdb is already running.
+	* kdb v3.0-2.4.20-i386-1.
+
+2002-11-29 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.20.
+	* kdb v2.5-2.4.20-i386-1.
+
+2002-11-14 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.20-rc1.
+	* kdb v2.5-2.4.20-rc1-i386-1.
+
+2002-11-14 Keith Owens  <kaos@sgi.com>
+
+	* General clean up of handling for breakpoints and single stepping over
+	  software breakpoints.
+	* Accept ff 1x as well as ff dx for call *(%reg) in backtrace.
+	* kdb v2.5-2.4.19-i386-1.
+
+2002-11-01 Keith Owens  <kaos@sgi.com>
+
+	* Prevent SMP IRQ overwriting KDB_ENTER().
+	* kdb v2.4-2.4.19-i386-2.
+
+2002-10-31 Keith Owens  <kaos@sgi.com>
+
+	* Avoid KDB_VECTOR conflict with DUMP_VECTOR.
+	* Remove kdb_eframe_t.
+	* Sanity check if we have pt_regs.
+	* Remove kdba_getcurrentframe().
+	* Reinstate missing nmi_watchdog/kdb hook.
+	* kdb v2.4-2.4.19-i386-1.
+
+2002-10-17 Keith Owens  <kaos@sgi.com>
+
+	* Correct compile with CONFIG_VT_CONSOLE=n.
+	* kdb v2.3-2.4.19-i386-5.
+
+2002-10-04 Keith Owens  <kaos@sgi.com>
+
+	* Add USB keyboard option.
+	* Minimize differences between patches for 2.4 and 2.5 kernels.
+	* kdb v2.3-2.4.19-i386-4.
+
+2002-08-10 Keith Owens  <kaos@sgi.com>
+
+	* Replace kdb_port with kdb_serial to support memory mapped I/O.
+	  Note: This needs kdb v2.3-2.4.19-common-2 or later.
+	* kdb v2.3-2.4.19-i386-3.
+
+2002-08-09 Keith Owens  <kaos@sgi.com>
+
+	* Use -fno-optimize-sibling-calls for kdb if gcc supports it.
+	* .text.lock does not consume an activation frame.
+	* kdb v2.3-2.4.19-i386-2.
+
+2002-08-07 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.19.
+	* Remove individual SGI copyrights, the general SGI copyright applies.
+	* New .text.lock name.  Hugh Dickins.
+	* Set KERNEL_CS in kdba_getcurrentframe.  Hugh Dickins.
+	* Clean up disassembly layout.  Hugh Dickins, Keith Owens.
+	* Replace hard coded stack size with THREAD_SIZE.  Hugh Dickins.
+	* Better stack layout on bt with no frame pointers.  Hugh Dickins.
+	* Make i386 IO breakpoints (bpha <address> IO) work again.
+	  Martin Wilck, Keith Owens.
+	* Remove fixed KDB_MAX_COMMANDS size.
+	* Add set_fs() around __copy_to_user on kernel addresses.
+	  Randolph Chung.
+	* Position i386 for CONFIG_NUMA_REPLICATE.
+	* kdb v2.3-2.4.19-i386-1.
+
+2002-07-09 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.19-rc1.
+
+2002-06-14 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.19-pre10.
+	* kdb v2.1-2.4.19-pre10-i386-1.
+
+2002-04-09 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.19-pre6.
+	* kdb v2.1-2.4.19-pre6-i386-1.
+
+2002-02-26 Keith Owens  <kaos@sgi.com>
+
+	* Upgrade to 2.4.18.
+	* kdb v2.1-2.4.18-i386-1.
+
+2002-01-18 Keith Owens  <kaos@sgi.com>
+
+	* Use new kdb_get/put functions.
+	* Define kdba_{get,put}area_size functions for i386.
+	* Remove over-engineered dblist callback functions.
+	* Correctly handle failing call disp32 in backtrace.
+	* Remove bp_instvalid flag, redundant code.
+	* Remove dead code.
+	* kdb v2.1-2.4.17-i386-1.
+
+2002-01-04 Keith Owens  <kaos@sgi.com>
+
+	* Sync xfs <-> kdb i386 code.
+
+2001-12-22 Keith Owens  <kaos@sgi.com>
+
+	* Split kdb for i386 as kdb v2.0-2.4.17-i386-1.
Index: 2.4.x-xfs/arch/i386/kdb/Makefile
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kdb/Makefile	Thu Jan  1 10:00:00 1970
+++ 2.4.x-xfs/arch/i386/kdb/Makefile	Mon Aug  9 13:54:51 2004
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+#
+# http://www.sgi.com
+#
+# For further information regarding this notice, see:
+#
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+O_TARGET	:= kdba.o
+obj-y		:= kdba_bt.o kdba_bp.o kdba_id.o kdba_io.o kdbasupport.o i386-dis.o
+
+override CFLAGS := $(CFLAGS:%-pg=% )
+
+EXTRA_CFLAGS += -I $(TOPDIR)/arch/$(ARCH)/kdb
+
+include $(TOPDIR)/Rules.make
Index: 2.4.x-xfs/arch/i386/kdb/ansidecl.h
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kdb/ansidecl.h	Thu Jan  1 10:00:00 1970
+++ 2.4.x-xfs/arch/i386/kdb/ansidecl.h	Mon Aug  9 13:54:51 2004
@@ -0,0 +1,198 @@
+/* ANSI and traditional C compatability macros
+   Copyright 1991, 1992, 1996, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* ANSI and traditional C compatibility macros
+
+   ANSI C is assumed if __STDC__ is #defined.
+
+   Macro	ANSI C definition	Traditional C definition
+   -----	---- - ----------	----------- - ----------
+   PTR		`void *'		`char *'
+   LONG_DOUBLE	`long double'		`double'
+   VOLATILE	`volatile'		`'
+   SIGNED	`signed'		`'
+   PTRCONST	`void *const'		`char *'
+   ANSI_PROTOTYPES  1			not defined
+
+   CONST is also defined, but is obsolete.  Just use const.
+
+   obsolete --     DEFUN (name, arglist, args)
+
+	Defines function NAME.
+
+	ARGLIST lists the arguments, separated by commas and enclosed in
+	parentheses.  ARGLIST becomes the argument list in traditional C.
+
+	ARGS list the arguments with their types.  It becomes a prototype in
+	ANSI C, and the type declarations in traditional C.  Arguments should
+	be separated with `AND'.  For functions with a variable number of
+	arguments, the last thing listed should be `DOTS'.
+
+   obsolete --     DEFUN_VOID (name)
+
+	Defines a function NAME, which takes no arguments.
+
+   obsolete --     EXFUN (name, (prototype))	-- obsolete.
+
+	Replaced by PARAMS.  Do not use; will disappear someday soon.
+	Was used in external function declarations.
+	In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in
+	parentheses).  In traditional C it is `NAME()'.
+	For a function that takes no arguments, PROTOTYPE should be `(void)'.
+
+   obsolete --     PROTO (type, name, (prototype)    -- obsolete.
+
+	This one has also been replaced by PARAMS.  Do not use.
+
+   PARAMS ((args))
+
+	We could use the EXFUN macro to handle prototype declarations, but
+	the name is misleading and the result is ugly.  So we just define a
+	simple macro to handle the parameter lists, as in:
+
+	      static int foo PARAMS ((int, char));
+
+	This produces:  `static int foo();' or `static int foo (int, char);'
+
+	EXFUN would have done it like this:
+
+	      static int EXFUN (foo, (int, char));
+
+	but the function is not external...and it's hard to visually parse
+	the function name out of the mess.   EXFUN should be considered
+	obsolete; new code should be written to use PARAMS.
+
+   DOTS is also obsolete.
+
+   Examples:
+
+	extern int printf PARAMS ((const char *format, ...));
+*/
+
+#ifndef	_ANSIDECL_H
+
+#define	_ANSIDECL_H	1
+
+
+/* Every source file includes this file,
+   so they will all get the switch for lint.  */
+/* LINTLIBRARY */
+
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32)
+/* All known AIX compilers implement these things (but don't always
+   define __STDC__).  The RISC/OS MIPS compiler defines these things
+   in SVR4 mode, but does not define __STDC__.  */
+
+#define	PTR		void *
+#define	PTRCONST	void *CONST
+#define	LONG_DOUBLE	long double
+
+#ifndef IN_GCC
+#define	AND		,
+#define	NOARGS		void
+#define	VOLATILE	volatile
+#define	SIGNED		signed
+#endif /* ! IN_GCC */
+
+#ifndef PARAMS
+#define PARAMS(paramlist)		paramlist
+#endif
+#define ANSI_PROTOTYPES			1
+
+#define VPARAMS(ARGS)			ARGS
+#define VA_START(va_list,var)		va_start(va_list,var)
+
+/* These are obsolete.  Do not use.  */
+#ifndef IN_GCC
+#define CONST				const
+#define DOTS				, ...
+#define PROTO(type, name, arglist)	type name arglist
+#define EXFUN(name, proto)		name proto
+#define DEFUN(name, arglist, args)	name(args)
+#define DEFUN_VOID(name)		name(void)
+#endif /* ! IN_GCC */
+
+#else	/* Not ANSI C.  */
+
+#define	PTR		char *
+#define	PTRCONST	PTR
+#define	LONG_DOUBLE	double
+
+#ifndef IN_GCC
+#define	AND		;
+#define	NOARGS
+#define	VOLATILE
+#define	SIGNED
+#endif /* !IN_GCC */
+
+#ifndef const /* some systems define it in header files for non-ansi mode */
+#define	const
+#endif
+
+#define PARAMS(paramlist)		()
+
+#define VPARAMS(ARGS)			(va_alist) va_dcl
+#define VA_START(va_list,var)		va_start(va_list)
+
+/* These are obsolete.  Do not use.  */
+#ifndef IN_GCC
+#define CONST
+#define DOTS
+#define PROTO(type, name, arglist)	type name ()
+#define EXFUN(name, proto)		name()
+#define DEFUN(name, arglist, args)	name arglist args;
+#define DEFUN_VOID(name)		name()
+#endif /* ! IN_GCC */
+
+#endif	/* ANSI C.  */
+
+/* Define macros for some gcc attributes.  This permits us to use the
+   macros freely, and know that they will come into play for the
+   version of gcc in which they are supported.  */
+
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __attribute__(x)
+#endif
+
+#ifndef ATTRIBUTE_UNUSED_LABEL
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 93)
+#  define ATTRIBUTE_UNUSED_LABEL
+# else
+#  define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
+# endif /* GNUC < 2.93 */
+#endif /* ATTRIBUTE_UNUSED_LABEL */
+
+#ifndef ATTRIBUTE_UNUSED
+#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif /* ATTRIBUTE_UNUSED */
+
+#ifndef ATTRIBUTE_NORETURN
+#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+#endif /* ATTRIBUTE_NORETURN */
+
+#ifndef ATTRIBUTE_PRINTF
+#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((format (__printf__, m, n)))
+#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
+#define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3)
+#define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4)
+#define ATTRIBUTE_PRINTF_4 ATTRIBUTE_PRINTF(4, 5)
+#define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6)
+#endif /* ATTRIBUTE_PRINTF */
+
+#endif	/* ansidecl.h	*/
Index: 2.4.x-xfs/arch/i386/kdb/bfd.h
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kdb/bfd.h	Thu Jan  1 10:00:00 1970
+++ 2.4.x-xfs/arch/i386/kdb/bfd.h	Mon Aug  9 13:54:51 2004
@@ -0,0 +1,3102 @@
+/* Main header file for the bfd library -- portable access to object files.
+   Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+   Free Software Foundation, Inc.
+   Contributed by Cygnus Support.
+
+** NOTE: bfd.h and bfd-in2.h are GENERATED files.  Don't change them;
+** instead, change bfd-in.h or the other BFD source files processed to
+** generate these files.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* bfd.h -- The only header file required by users of the bfd library 
+
+The bfd.h file is generated from bfd-in.h and various .c files; if you
+change it, your changes will probably be lost.
+
+All the prototypes and definitions following the comment "THE FOLLOWING
+IS EXTRACTED FROM THE SOURCE" are extracted from the source files for
+BFD.  If you change it, someone oneday will extract it from the source
+again, and your changes will be lost.  To save yourself from this bind,
+change the definitions in the source in the bfd directory.  Type "make
+docs" and then "make headers" in that directory, and magically this file
+will change to reflect your changes.
+
+If you don't have the tools to perform the extraction, then you are
+safe from someone on your system trampling over your header files.
+You should still maintain the equivalence between the source and this
+file though; every change you make to the .c file should be reflected
+here.  */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ansidecl.h"
+
+/* These two lines get substitutions done by commands in Makefile.in.  */
+#define BFD_VERSION  "2.9.5.0.22"
+#define BFD_ARCH_SIZE 32
+#define BFD_HOST_64BIT_LONG 0
+#if 0
+#define BFD_HOST_64_BIT 
+#define BFD_HOST_U_64_BIT 
+#endif
+
+#if BFD_ARCH_SIZE >= 64
+#define BFD64
+#endif
+
+#ifndef INLINE
+#if __GNUC__ >= 2
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+#endif
+
+/* forward declaration */
+typedef struct _bfd bfd;
+
+/* To squelch erroneous compiler warnings ("illegal pointer
+   combination") from the SVR3 compiler, we would like to typedef
+   boolean to int (it doesn't like functions which return boolean.
+   Making sure they are never implicitly declared to return int
+   doesn't seem to help).  But this file is not configured based on
+   the host.  */
+/* General rules: functions which are boolean return true on success
+   and false on failure (unless they're a predicate).   -- bfd.doc */
+/* I'm sure this is going to break something and someone is going to
+   force me to change it. */
+/* typedef enum boolean {false, true} boolean; */
+/* Yup, SVR4 has a "typedef enum boolean" in <sys/types.h>  -fnf */
+/* It gets worse if the host also defines a true/false enum... -sts */
+/* And even worse if your compiler has built-in boolean types... -law */
+#if defined (__GNUG__) && (__GNUC_MINOR__ > 5)
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif
+#ifdef MPW
+/* Pre-emptive strike - get the file with the enum. */
+#include <Types.h>
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif /* MPW */
+#ifndef TRUE_FALSE_ALREADY_DEFINED
+typedef enum bfd_boolean {false, true} boolean;
+#define BFD_TRUE_FALSE
+#else
+/* Use enum names that will appear nowhere else.  */
+typedef enum bfd_boolean {bfd_fffalse, bfd_tttrue} boolean;
+#endif
+
+/* A pointer to a position in a file.  */
+/* FIXME:  This should be using off_t from <sys/types.h>.
+   For now, try to avoid breaking stuff by not including <sys/types.h> here.
+   This will break on systems with 64-bit file offsets (e.g. 4.4BSD).
+   Probably the best long-term answer is to avoid using file_ptr AND off_t 
+   in this header file, and to handle this in the BFD implementation
+   rather than in its interface.  */
+/* typedef off_t	file_ptr; */
+typedef long int file_ptr;
+
+/* Support for different sizes of target format ints and addresses.
+   If the type `long' is at least 64 bits, BFD_HOST_64BIT_LONG will be
+   set to 1 above.  Otherwise, if gcc is being used, this code will
+   use gcc's "long long" type.  Otherwise, BFD_HOST_64_BIT must be
+   defined above.  */
+
+#ifndef BFD_HOST_64_BIT
+# if BFD_HOST_64BIT_LONG
+#  define BFD_HOST_64_BIT long
+#  define BFD_HOST_U_64_BIT unsigned long
+# else
+#  ifdef __GNUC__
+#   if __GNUC__ >= 2
+#    define BFD_HOST_64_BIT long long
+#    define BFD_HOST_U_64_BIT unsigned long long
+#   endif /* __GNUC__ >= 2 */
+#  endif /* ! defined (__GNUC__) */
+# endif /* ! BFD_HOST_64BIT_LONG */
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+#ifdef BFD64
+
+#ifndef BFD_HOST_64_BIT
+ #error No 64 bit integer type available
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+typedef BFD_HOST_U_64_BIT bfd_vma;
+typedef BFD_HOST_64_BIT bfd_signed_vma;
+typedef BFD_HOST_U_64_BIT bfd_size_type;
+typedef BFD_HOST_U_64_BIT symvalue;
+
+#ifndef fprintf_vma
+#if BFD_HOST_64BIT_LONG
+#define sprintf_vma(s,x) sprintf (s, "%016lx", x)
+#define fprintf_vma(f,x) fprintf (f, "%016lx", x)
+#else
+#define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
+#define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
+#define fprintf_vma(s,x) \
+  fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#define sprintf_vma(s,x) \
+  sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#endif
+#endif
+
+#else /* not BFD64  */
+
+/* Represent a target address.  Also used as a generic unsigned type
+   which is guaranteed to be big enough to hold any arithmetic types
+   we need to deal with.  */
+typedef unsigned long bfd_vma;
+
+/* A generic signed type which is guaranteed to be big enough to hold any
+   arithmetic types we need to deal with.  Can be assumed to be compatible
+   with bfd_vma in the same way that signed and unsigned ints are compatible
+   (as parameters, in assignment, etc).  */
+typedef long bfd_signed_vma;
+
+typedef unsigned long symvalue;
+typedef unsigned long bfd_size_type;
+
+/* Print a bfd_vma x on stream s.  */
+#define fprintf_vma(s,x) fprintf(s, "%08lx", x)
+#define sprintf_vma(s,x) sprintf(s, "%08lx", x)
+
+#endif /* not BFD64  */
+
+#define printf_vma(x) fprintf_vma(stdout,x)
+
+typedef unsigned int flagword;	/* 32 bits of flags */
+typedef unsigned char bfd_byte;
+
+/** File formats */
+
+typedef enum bfd_format {
+	      bfd_unknown = 0,	/* file format is unknown */
+	      bfd_object,	/* linker/assember/compiler output */
+	      bfd_archive,	/* object archive file */
+	      bfd_core,		/* core dump */
+	      bfd_type_end}	/* marks the end; don't use it! */
+         bfd_format;
+
+/* Values that may appear in the flags field of a BFD.  These also
+   appear in the object_flags field of the bfd_target structure, where
+   they indicate the set of flags used by that backend (not all flags
+   are meaningful for all object file formats) (FIXME: at the moment,
+   the object_flags values have mostly just been copied from backend
+   to another, and are not necessarily correct).  */
+
+/* No flags.  */
+#define BFD_NO_FLAGS   	0x00
+
+/* BFD contains relocation entries.  */
+#define HAS_RELOC   	0x01
+
+/* BFD is directly executable.  */
+#define EXEC_P      	0x02
+
+/* BFD has line number information (basically used for F_LNNO in a
+   COFF header).  */
+#define HAS_LINENO  	0x04
+
+/* BFD has debugging information.  */
+#define HAS_DEBUG   	0x08
+
+/* BFD has symbols.  */
+#define HAS_SYMS    	0x10
+
+/* BFD has local symbols (basically used for F_LSYMS in a COFF
+   header).  */
+#define HAS_LOCALS  	0x20
+
+/* BFD is a dynamic object.  */
+#define DYNAMIC     	0x40
+
+/* Text section is write protected (if D_PAGED is not set, this is
+   like an a.out NMAGIC file) (the linker sets this by default, but
+   clears it for -r or -N).  */
+#define WP_TEXT     	0x80
+
+/* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the
+   linker sets this by default, but clears it for -r or -n or -N).  */
+#define D_PAGED     	0x100
+
+/* BFD is relaxable (this means that bfd_relax_section may be able to
+   do something) (sometimes bfd_relax_section can do something even if
+   this is not set).  */
+#define BFD_IS_RELAXABLE 0x200
+
+/* This may be set before writing out a BFD to request using a
+   traditional format.  For example, this is used to request that when
+   writing out an a.out object the symbols not be hashed to eliminate
+   duplicates.  */
+#define BFD_TRADITIONAL_FORMAT 0x400
+
+/* This flag indicates that the BFD contents are actually cached in
+   memory.  If this is set, iostream points to a bfd_in_memory struct.  */
+#define BFD_IN_MEMORY 0x800
+
+/* symbols and relocation */
+
+/* A count of carsyms (canonical archive symbols).  */
+typedef unsigned long symindex;
+
+/* How to perform a relocation.  */
+typedef const struct reloc_howto_struct reloc_howto_type;
+
+#define BFD_NO_MORE_SYMBOLS ((symindex) ~0)
+
+/* General purpose part of a symbol X;
+   target specific parts are in libcoff.h, libaout.h, etc.  */
+
+#define bfd_get_section(x) ((x)->section)
+#define bfd_get_output_section(x) ((x)->section->output_section)
+#define bfd_set_section(x,y) ((x)->section) = (y)
+#define bfd_asymbol_base(x) ((x)->section->vma)
+#define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value)
+#define bfd_asymbol_name(x) ((x)->name)
+/*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/
+#define bfd_asymbol_bfd(x) ((x)->the_bfd)
+#define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour)
+
+/* A canonical archive symbol.  */
+/* This is a type pun with struct ranlib on purpose! */
+typedef struct carsym {
+  char *name;
+  file_ptr file_offset;		/* look here to find the file */
+} carsym;			/* to make these you call a carsymogen */
+
+  
+/* Used in generating armaps (archive tables of contents).
+   Perhaps just a forward definition would do? */
+struct orl {			/* output ranlib */
+  char **name;			/* symbol name */ 
+  file_ptr pos;			/* bfd* or file position */
+  int namidx;			/* index into string table */
+};
+
+
+/* Linenumber stuff */
+typedef struct lineno_cache_entry {
+  unsigned int line_number;	/* Linenumber from start of function*/  
+  union {
+    struct symbol_cache_entry *sym; /* Function name */
+    unsigned long offset;	/* Offset into section */
+  } u;
+} alent;
+
+/* object and core file sections */
+
+#define	align_power(addr, align)	\
+	( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+
+typedef struct sec *sec_ptr;
+
+#define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0)
+#define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0)
+#define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0)
+#define bfd_section_name(bfd, ptr) ((ptr)->name)
+#define bfd_section_size(bfd, ptr) (bfd_get_section_size_before_reloc(ptr))
+#define bfd_section_vma(bfd, ptr) ((ptr)->vma)
+#define bfd_section_lma(bfd, ptr) ((ptr)->lma)
+#define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power)
+#define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0)
+#define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata)
+
+#define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0)
+
+#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma= (val)), ((ptr)->user_set_vma = (boolean)true), true)
+#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),true)
+#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),true)
+
+typedef struct stat stat_type; 
+
+typedef enum bfd_print_symbol
+{ 
+  bfd_print_symbol_name,
+  bfd_print_symbol_more,
+  bfd_print_symbol_all
+} bfd_print_symbol_type;
+    
+/* Information about a symbol that nm needs.  */
+
+typedef struct _symbol_info
+{
+  symvalue value;
+  char type;
+  CONST char *name;            /* Symbol name.  */
+  unsigned char stab_type;     /* Stab type.  */
+  char stab_other;             /* Stab other. */
+  short stab_desc;             /* Stab desc.  */
+  CONST char *stab_name;       /* String for stab type.  */
+} symbol_info;
+
+/* Get the name of a stabs type code.  */
+
+extern const char *bfd_get_stab_name PARAMS ((int));
+
+/* Hash table routines.  There is no way to free up a hash table.  */
+
+/* An element in the hash table.  Most uses will actually use a larger
+   structure, and an instance of this will be the first field.  */
+
+struct bfd_hash_entry
+{
+  /* Next entry for this hash code.  */
+  struct bfd_hash_entry *next;
+  /* String being hashed.  */
+  const char *string;
+  /* Hash code.  This is the full hash code, not the index into the
+     table.  */
+  unsigned long hash;
+};
+
+/* A hash table.  */
+
+struct bfd_hash_table
+{
+  /* The hash array.  */
+  struct bfd_hash_entry **table;
+  /* The number of slots in the hash table.  */
+  unsigned int size;
+  /* A function used to create new elements in the hash table.  The
+     first entry is itself a pointer to an element.  When this
+     function is first invoked, this pointer will be NULL.  However,
+     having the pointer permits a hierarchy of method functions to be
+     built each of which calls the function in the superclass.  Thus
+     each function should be written to allocate a new block of memory
+     only if the argument is NULL.  */
+  struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+					     struct bfd_hash_table *,
+					     const char *));
+   /* An objalloc for this hash table.  This is a struct objalloc *,
+     but we use PTR to avoid requiring the inclusion of objalloc.h.  */
+  PTR memory;
+};
+
+/* Initialize a hash table.  */
+extern boolean bfd_hash_table_init
+  PARAMS ((struct bfd_hash_table *,
+	   struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+				       struct bfd_hash_table *,
+				       const char *)));
+
+/* Initialize a hash table specifying a size.  */
+extern boolean bfd_hash_table_init_n
+  PARAMS ((struct bfd_hash_table *,
+	   struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+				       struct bfd_hash_table *,
+				       const char *),
+	   unsigned int size));
+
+/* Free up a hash table.  */
+extern void bfd_hash_table_free PARAMS ((struct bfd_hash_table *));
+
+/* Look up a string in a hash table.  If CREATE is true, a new entry
+   will be created for this string if one does not already exist.  The
+   COPY argument must be true if this routine should copy the string
+   into newly allocated memory when adding an entry.  */
+extern struct bfd_hash_entry *bfd_hash_lookup
+  PARAMS ((struct bfd_hash_table *, const char *, boolean create,
+	   boolean copy));
+
+/* Replace an entry in a hash table.  */
+extern void bfd_hash_replace
+  PARAMS ((struct bfd_hash_table *, struct bfd_hash_entry *old,
+	   struct bfd_hash_entry *nw));
+
+/* Base method for creating a hash table entry.  */
+extern struct bfd_hash_entry *bfd_hash_newfunc
+  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+	   const char *));
+
+/* Grab some space for a hash table entry.  */
+extern PTR bfd_hash_allocate PARAMS ((struct bfd_hash_table *,
+				      unsigned int));
+
+/* Traverse a hash table in a random order, calling a function on each
+   element.  If the function returns false, the traversal stops.  The
+   INFO argument is passed to the function.  */
+extern void bfd_hash_traverse PARAMS ((struct bfd_hash_table *,
+				       boolean (*) (struct bfd_hash_entry *,
+						    PTR),
+				       PTR info));
+
+/* Semi-portable string concatenation in cpp.
+   The CAT4 hack is to avoid a problem with some strict ANSI C preprocessors.
+   The problem is, "32_" is not a valid preprocessing token, and we don't
+   want extra underscores (e.g., "nlm_32_").  The XCAT2 macro will cause the
+   inner CAT macros to be evaluated first, producing still-valid pp-tokens.
+   Then the final concatenation can be done.  (Sigh.)  */
+#ifndef CAT
+#ifdef SABER
+#define CAT(a,b)	a##b
+#define CAT3(a,b,c)	a##b##c
+#define CAT4(a,b,c,d)	a##b##c##d
+#else
+#if defined(__STDC__) || defined(ALMOST_STDC)
+#define CAT(a,b) a##b
+#define CAT3(a,b,c) a##b##c
+#define XCAT2(a,b)	CAT(a,b)
+#define CAT4(a,b,c,d)	XCAT2(CAT(a,b),CAT(c,d))
+#else
+#define CAT(a,b) a/**/b
+#define CAT3(a,b,c) a/**/b/**/c
+#define CAT4(a,b,c,d)	a/**/b/**/c/**/d
+#endif
+#endif
+#endif
+
+#define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table
+
+/* User program access to BFD facilities */
+
+/* Direct I/O routines, for programs which know more about the object
+   file than BFD does.  Use higher level routines if possible.  */
+
+extern bfd_size_type bfd_read
+  PARAMS ((PTR, bfd_size_type size, bfd_size_type nitems, bfd *abfd));
+extern bfd_size_type bfd_write
+  PARAMS ((const PTR, bfd_size_type size, bfd_size_type nitems, bfd *abfd));
+extern int bfd_seek PARAMS ((bfd *abfd, file_ptr fp, int direction));
+extern long bfd_tell PARAMS ((bfd *abfd));
+extern int bfd_flush PARAMS ((bfd *abfd));
+extern int bfd_stat PARAMS ((bfd *abfd, struct stat *));
+
+
+/* Cast from const char * to char * so that caller can assign to
+   a char * without a warning.  */
+#define bfd_get_filename(abfd) ((char *) (abfd)->filename)
+#define bfd_get_cacheable(abfd) ((abfd)->cacheable)
+#define bfd_get_format(abfd) ((abfd)->format)
+#define bfd_get_target(abfd) ((abfd)->xvec->name)
+#define bfd_get_flavour(abfd) ((abfd)->xvec->flavour)
+#define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG)
+#define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_header_big_endian(abfd) \
+  ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG)
+#define bfd_header_little_endian(abfd) \
+  ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_get_file_flags(abfd) ((abfd)->flags)
+#define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags)
+#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
+#define bfd_my_archive(abfd) ((abfd)->my_archive)
+#define bfd_has_map(abfd) ((abfd)->has_armap)
+
+#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
+#define bfd_usrdata(abfd) ((abfd)->usrdata)
+
+#define bfd_get_start_address(abfd) ((abfd)->start_address)
+#define bfd_get_symcount(abfd) ((abfd)->symcount)
+#define bfd_get_outsymbols(abfd) ((abfd)->outsymbols)
+#define bfd_count_sections(abfd) ((abfd)->section_count)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = (boolean)(bool)), true)
+
+extern boolean bfd_record_phdr
+  PARAMS ((bfd *, unsigned long, boolean, flagword, boolean, bfd_vma,
+	   boolean, boolean, unsigned int, struct sec **));
+
+/* Byte swapping routines.  */
+
+bfd_vma		bfd_getb64	   PARAMS ((const unsigned char *));
+bfd_vma 	bfd_getl64	   PARAMS ((const unsigned char *));
+bfd_signed_vma	bfd_getb_signed_64 PARAMS ((const unsigned char *));
+bfd_signed_vma	bfd_getl_signed_64 PARAMS ((const unsigned char *));
+bfd_vma		bfd_getb32	   PARAMS ((const unsigned char *));
+bfd_vma		bfd_getl32	   PARAMS ((const unsigned char *));
+bfd_signed_vma	bfd_getb_signed_32 PARAMS ((const unsigned char *));
+bfd_signed_vma	bfd_getl_signed_32 PARAMS ((const unsigned char *));
+bfd_vma		bfd_getb16	   PARAMS ((const unsigned char *));
+bfd_vma		bfd_getl16	   PARAMS ((const unsigned char *));
+bfd_signed_vma	bfd_getb_signed_16 PARAMS ((const unsigned char *));
+bfd_signed_vma	bfd_getl_signed_16 PARAMS ((const unsigned char *));
+void		bfd_putb64	   PARAMS ((bfd_vma, unsigned char *));
+void		bfd_putl64	   PARAMS ((bfd_vma, unsigned char *));
+void		bfd_putb32	   PARAMS ((bfd_vma, unsigned char *));
+void		bfd_putl32	   PARAMS ((bfd_vma, unsigned char *));
+void		bfd_putb16	   PARAMS ((bfd_vma, unsigned char *));
+void		bfd_putl16	   PARAMS ((bfd_vma, unsigned char *));
+
+/* Externally visible ECOFF routines.  */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct ecoff_debug_info;
+struct ecoff_debug_swap;
+struct ecoff_extr;
+struct symbol_cache_entry;
+struct bfd_link_info;
+struct bfd_link_hash_entry;
+struct bfd_elf_version_tree;
+#endif
+extern bfd_vma bfd_ecoff_get_gp_value PARAMS ((bfd * abfd));
+extern boolean bfd_ecoff_set_gp_value PARAMS ((bfd *abfd, bfd_vma gp_value));
+extern boolean bfd_ecoff_set_regmasks
+  PARAMS ((bfd *abfd, unsigned long gprmask, unsigned long fprmask,
+	   unsigned long *cprmask));
+extern PTR bfd_ecoff_debug_init
+  PARAMS ((bfd *output_bfd, struct ecoff_debug_info *output_debug,
+	   const struct ecoff_debug_swap *output_swap,
+	   struct bfd_link_info *));
+extern void bfd_ecoff_debug_free
+  PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+	   const struct ecoff_debug_swap *output_swap,
+	   struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate
+  PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+	   const struct ecoff_debug_swap *output_swap,
+	   bfd *input_bfd, struct ecoff_debug_info *input_debug,
+	   const struct ecoff_debug_swap *input_swap,
+	   struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate_other
+  PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+	   const struct ecoff_debug_swap *output_swap, bfd *input_bfd,
+	   struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_externals
+  PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+	   const struct ecoff_debug_swap *swap,
+	   boolean relocateable,
+	   boolean (*get_extr) (struct symbol_cache_entry *,
+				struct ecoff_extr *),
+	   void (*set_index) (struct symbol_cache_entry *,
+			      bfd_size_type)));
+extern boolean bfd_ecoff_debug_one_external
+  PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+	   const struct ecoff_debug_swap *swap,
+	   const char *name, struct ecoff_extr *esym));
+extern bfd_size_type bfd_ecoff_debug_size
+  PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+	   const struct ecoff_debug_swap *swap));
+extern boolean bfd_ecoff_write_debug
+  PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+	   const struct ecoff_debug_swap *swap, file_ptr where));
+extern boolean bfd_ecoff_write_accumulated_debug
+  PARAMS ((PTR handle, bfd *abfd, struct ecoff_debug_info *debug,
+	   const struct ecoff_debug_swap *swap,
+	   struct bfd_link_info *info, file_ptr where));
+extern boolean bfd_mips_ecoff_create_embedded_relocs
+  PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+	   char **));
+
+/* Externally visible ELF routines.  */
+
+struct bfd_link_needed_list
+{
+  struct bfd_link_needed_list *next;
+  bfd *by;
+  const char *name;
+};
+
+extern boolean bfd_elf32_record_link_assignment
+  PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern boolean bfd_elf64_record_link_assignment
+  PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+  PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf_get_bfd_needed_list
+  PARAMS ((bfd *, struct bfd_link_needed_list **));
+extern boolean bfd_elf32_size_dynamic_sections
+  PARAMS ((bfd *, const char *, const char *, boolean, const char *,
+	   const char * const *, struct bfd_link_info *, struct sec **,
+	   struct bfd_elf_version_tree *));
+extern boolean bfd_elf64_size_dynamic_sections
+  PARAMS ((bfd *, const char *, const char *, boolean, const char *,
+	   const char * const *, struct bfd_link_info *, struct sec **,
+	   struct bfd_elf_version_tree *));
+extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
+
+/* SunOS shared library support routines for the linker.  */
+
+extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+  PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sunos_record_link_assignment
+  PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_sunos_size_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *, struct sec **, struct sec **,
+	   struct sec **));
+
+/* Linux shared library support routines for the linker.  */
+
+extern boolean bfd_i386linux_size_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_m68klinux_size_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sparclinux_size_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+
+/* mmap hacks */
+
+struct _bfd_window_internal;
+typedef struct _bfd_window_internal bfd_window_internal;
+
+typedef struct _bfd_window {
+  /* What the user asked for.  */
+  PTR data;
+  bfd_size_type size;
+  /* The actual window used by BFD.  Small user-requested read-only
+     regions sharing a page may share a single window into the object
+     file.  Read-write versions shouldn't until I've fixed things to
+     keep track of which portions have been claimed by the
+     application; don't want to give the same region back when the
+     application wants two writable copies!  */
+  struct _bfd_window_internal *i;
+} bfd_window;
+
+extern void bfd_init_window PARAMS ((bfd_window *));
+extern void bfd_free_window PARAMS ((bfd_window *));
+extern boolean bfd_get_file_window
+  PARAMS ((bfd *, file_ptr, bfd_size_type, bfd_window *, boolean));
+
+/* XCOFF support routines for the linker.  */
+
+extern boolean bfd_xcoff_link_record_set
+  PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+	   bfd_size_type));
+extern boolean bfd_xcoff_import_symbol
+  PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+	   bfd_vma, const char *, const char *, const char *));
+extern boolean bfd_xcoff_export_symbol
+  PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+	   boolean));
+extern boolean bfd_xcoff_link_count_reloc
+  PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_record_link_assignment
+  PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_size_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
+	   unsigned long, unsigned long, unsigned long, boolean,
+	   int, boolean, boolean, struct sec **));
+
+/* Externally visible COFF routines.  */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct internal_syment;
+union internal_auxent;
+#endif
+
+extern boolean bfd_coff_get_syment
+  PARAMS ((bfd *, struct symbol_cache_entry *, struct internal_syment *));
+
+extern boolean bfd_coff_get_auxent
+  PARAMS ((bfd *, struct symbol_cache_entry *, int, union internal_auxent *));
+
+extern boolean bfd_coff_set_symbol_class
+  PARAMS ((bfd *, struct symbol_cache_entry *, unsigned int));
+
+/* ARM Interworking support.  Called from linker.  */
+extern boolean bfd_arm_allocate_interworking_sections
+  PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_process_before_allocation
+  PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_get_bfd_for_interworking
+  PARAMS ((bfd *, struct bfd_link_info *));
+
+/* ELF ARM Interworking support.  Called from linker.  */
+extern boolean bfd_elf32_arm_allocate_interworking_sections
+  PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_elf32_arm_process_before_allocation
+  PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_elf32_arm_get_bfd_for_interworking
+  PARAMS ((bfd *, struct bfd_link_info *));
+
+/* And more from the source.  */
+void 
+bfd_init PARAMS ((void));
+
+bfd *
+bfd_openr PARAMS ((CONST char *filename, CONST char *target));
+
+bfd *
+bfd_fdopenr PARAMS ((CONST char *filename, CONST char *target, int fd));
+
+bfd *
+bfd_openstreamr PARAMS ((const char *, const char *, PTR));
+
+bfd *
+bfd_openw PARAMS ((CONST char *filename, CONST char *target));
+
+boolean 
+bfd_close PARAMS ((bfd *abfd));
+
+boolean 
+bfd_close_all_done PARAMS ((bfd *));
+
+bfd *
+bfd_create PARAMS ((CONST char *filename, bfd *templ));
+
+boolean 
+bfd_make_writable PARAMS ((bfd *abfd));
+
+boolean 
+bfd_make_readable PARAMS ((bfd *abfd));
+
+
+ /* Byte swapping macros for user section data.  */
+
+#define bfd_put_8(abfd, val, ptr) \
+                ((void) (*((unsigned char *)(ptr)) = (unsigned char)(val)))
+#define bfd_put_signed_8 \
+               bfd_put_8
+#define bfd_get_8(abfd, ptr) \
+                (*(unsigned char *)(ptr))
+#define bfd_get_signed_8(abfd, ptr) \
+               ((*(unsigned char *)(ptr) ^ 0x80) - 0x80)
+
+#define bfd_put_16(abfd, val, ptr) \
+                BFD_SEND(abfd, bfd_putx16, ((val),(ptr)))
+#define bfd_put_signed_16 \
+                bfd_put_16
+#define bfd_get_16(abfd, ptr) \
+                BFD_SEND(abfd, bfd_getx16, (ptr))
+#define bfd_get_signed_16(abfd, ptr) \
+                BFD_SEND (abfd, bfd_getx_signed_16, (ptr))
+
+#define bfd_put_32(abfd, val, ptr) \
+                BFD_SEND(abfd, bfd_putx32, ((val),(ptr)))
+#define bfd_put_signed_32 \
+                bfd_put_32
+#define bfd_get_32(abfd, ptr) \
+                BFD_SEND(abfd, bfd_getx32, (ptr))
+#define bfd_get_signed_32(abfd, ptr) \
+                BFD_SEND(abfd, bfd_getx_signed_32, (ptr))
+
+#define bfd_put_64(abfd, val, ptr) \
+                BFD_SEND(abfd, bfd_putx64, ((val), (ptr)))
+#define bfd_put_signed_64 \
+                bfd_put_64
+#define bfd_get_64(abfd, ptr) \
+                BFD_SEND(abfd, bfd_getx64, (ptr))
+#define bfd_get_signed_64(abfd, ptr) \
+                BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
+
+#define bfd_get(bits, abfd, ptr)                               \
+                ((bits) == 8 ? bfd_get_8 (abfd, ptr)           \
+                : (bits) == 16 ? bfd_get_16 (abfd, ptr)        \
+                : (bits) == 32 ? bfd_get_32 (abfd, ptr)        \
+                : (bits) == 64 ? bfd_get_64 (abfd, ptr)        \
+                : (abort (), (bfd_vma) - 1))
+
+#define bfd_put(bits, abfd, val, ptr)                          \
+                ((bits) == 8 ? bfd_put_8 (abfd, val, ptr)      \
+                : (bits) == 16 ? bfd_put_16 (abfd, val, ptr)   \
+                : (bits) == 32 ? bfd_put_32 (abfd, val, ptr)   \
+                : (bits) == 64 ? bfd_put_64 (abfd, val, ptr)   \
+                : (abort (), (void) 0))
+
+
+ /* Byte swapping macros for file header data.  */
+
+#define bfd_h_put_8(abfd, val, ptr) \
+               bfd_put_8 (abfd, val, ptr)
+#define bfd_h_put_signed_8(abfd, val, ptr) \
+               bfd_put_8 (abfd, val, ptr)
+#define bfd_h_get_8(abfd, ptr) \
+               bfd_get_8 (abfd, ptr)
+#define bfd_h_get_signed_8(abfd, ptr) \
+               bfd_get_signed_8 (abfd, ptr)
+
+#define bfd_h_put_16(abfd, val, ptr) \
+                BFD_SEND(abfd, bfd_h_putx16,(val,ptr))
+#define bfd_h_put_signed_16 \
+                bfd_h_put_16
+#define bfd_h_get_16(abfd, ptr) \
+                BFD_SEND(abfd, bfd_h_getx16,(ptr))
+#define bfd_h_get_signed_16(abfd, ptr) \
+                BFD_SEND(abfd, bfd_h_getx_signed_16, (ptr))
+
+#define bfd_h_put_32(abfd, val, ptr) \
+                BFD_SEND(abfd, bfd_h_putx32,(val,ptr))
+#define bfd_h_put_signed_32 \
+                bfd_h_put_32
+#define bfd_h_get_32(abfd, ptr) \
+                BFD_SEND(abfd, bfd_h_getx32,(ptr))
+#define bfd_h_get_signed_32(abfd, ptr) \
+                BFD_SEND(abfd, bfd_h_getx_signed_32, (ptr))
+
+#define bfd_h_put_64(abfd, val, ptr) \
+                BFD_SEND(abfd, bfd_h_putx64,(val, ptr))
+#define bfd_h_put_signed_64 \
+                bfd_h_put_64
+#define bfd_h_get_64(abfd, ptr) \
+                BFD_SEND(abfd, bfd_h_getx64,(ptr))
+#define bfd_h_get_signed_64(abfd, ptr) \
+                BFD_SEND(abfd, bfd_h_getx_signed_64, (ptr))
+
+  /* This structure is used for a comdat section, as in PE.  A comdat
+    section is associated with a particular symbol.  When the linker
+    sees a comdat section, it keeps only one of the sections with a
+    given name and associated with a given symbol. */
+
+struct bfd_comdat_info
+{
+   /* The name of the symbol associated with a comdat section.  */
+  const char *name;
+
+   /* The local symbol table index of the symbol associated with a
+     comdat section.  This is only meaningful to the object file format
+     specific code; it is not an index into the list returned by
+     bfd_canonicalize_symtab.  */
+  long symbol;
+
+   /* If this section is being discarded, the linker uses this field
+     to point to the input section which is being kept.  */
+  struct sec *sec;
+};
+
+typedef struct sec
+{
+         /* The name of the section; the name isn't a copy, the pointer is
+        the same as that passed to bfd_make_section. */
+
+    CONST char *name;
+
+         /* Which section is it; 0..nth.      */
+
+   int index;
+
+         /* The next section in the list belonging to the BFD, or NULL. */
+
+    struct sec *next;
+
+         /* The field flags contains attributes of the section. Some
+           flags are read in from the object file, and some are
+           synthesized from other information.  */
+
+    flagword flags;
+
+#define SEC_NO_FLAGS   0x000
+
+         /* Tells the OS to allocate space for this section when loading.
+           This is clear for a section containing debug information
+           only. */
+#define SEC_ALLOC      0x001
+
+         /* Tells the OS to load the section from the file when loading.
+           This is clear for a .bss section. */
+#define SEC_LOAD       0x002
+
+         /* The section contains data still to be relocated, so there is
+           some relocation information too. */
+#define SEC_RELOC      0x004
+
+#if 0    /* Obsolete ? */
+#define SEC_BALIGN     0x008
+#endif
+
+         /* A signal to the OS that the section contains read only
+          data. */
+#define SEC_READONLY   0x010
+
+         /* The section contains code only. */
+#define SEC_CODE       0x020
+
+         /* The section contains data only. */
+#define SEC_DATA       0x040
+
+         /* The section will reside in ROM. */
+#define SEC_ROM        0x080
+
+         /* The section contains constructor information. This section
+           type is used by the linker to create lists of constructors and
+           destructors used by <<g++>>. When a back end sees a symbol
+           which should be used in a constructor list, it creates a new
+           section for the type of name (e.g., <<__CTOR_LIST__>>), attaches
+           the symbol to it, and builds a relocation. To build the lists
+           of constructors, all the linker has to do is catenate all the
+           sections called <<__CTOR_LIST__>> and relocate the data
+           contained within - exactly the operations it would peform on
+           standard data. */
+#define SEC_CONSTRUCTOR 0x100
+
+         /* The section is a constructor, and should be placed at the
+          end of the text, data, or bss section(?). */
+#define SEC_CONSTRUCTOR_TEXT 0x1100
+#define SEC_CONSTRUCTOR_DATA 0x2100
+#define SEC_CONSTRUCTOR_BSS  0x3100
+
+         /* The section has contents - a data section could be
+           <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
+           <<SEC_HAS_CONTENTS>> */
+#define SEC_HAS_CONTENTS 0x200
+
+         /* An instruction to the linker to not output the section
+           even if it has information which would normally be written. */
+#define SEC_NEVER_LOAD 0x400
+
+         /* The section is a COFF shared library section.  This flag is
+           only for the linker.  If this type of section appears in
+           the input file, the linker must copy it to the output file
+           without changing the vma or size.  FIXME: Although this
+           was originally intended to be general, it really is COFF
+           specific (and the flag was renamed to indicate this).  It
+           might be cleaner to have some more general mechanism to
+           allow the back end to control what the linker does with
+           sections. */
+#define SEC_COFF_SHARED_LIBRARY 0x800
+
+         /* The section contains common symbols (symbols may be defined
+           multiple times, the value of a symbol is the amount of
+           space it requires, and the largest symbol value is the one
+           used).  Most targets have exactly one of these (which we
+           translate to bfd_com_section_ptr), but ECOFF has two. */
+#define SEC_IS_COMMON 0x8000
+
+         /* The section contains only debugging information.  For
+           example, this is set for ELF .debug and .stab sections.
+           strip tests this flag to see if a section can be
+           discarded. */
+#define SEC_DEBUGGING 0x10000
+
+         /* The contents of this section are held in memory pointed to
+           by the contents field.  This is checked by
+           bfd_get_section_contents, and the data is retrieved from
+           memory if appropriate.  */
+#define SEC_IN_MEMORY 0x20000
+
+         /* The contents of this section are to be excluded by the
+           linker for executable and shared objects unless those
+           objects are to be further relocated.  */
+#define SEC_EXCLUDE 0x40000
+
+        /* The contents of this section are to be sorted by the
+          based on the address specified in the associated symbol
+          table.  */
+#define SEC_SORT_ENTRIES 0x80000
+
+        /* When linking, duplicate sections of the same name should be
+          discarded, rather than being combined into a single section as
+          is usually done.  This is similar to how common symbols are
+          handled.  See SEC_LINK_DUPLICATES below.  */
+#define SEC_LINK_ONCE 0x100000
+
+        /* If SEC_LINK_ONCE is set, this bitfield describes how the linker
+          should handle duplicate sections.  */
+#define SEC_LINK_DUPLICATES 0x600000
+
+        /* This value for SEC_LINK_DUPLICATES means that duplicate
+          sections with the same name should simply be discarded. */
+#define SEC_LINK_DUPLICATES_DISCARD 0x0
+
+        /* This value for SEC_LINK_DUPLICATES means that the linker
+          should warn if there are any duplicate sections, although
+          it should still only link one copy.  */
+#define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000
+
+        /* This value for SEC_LINK_DUPLICATES means that the linker
+          should warn if any duplicate sections are a different size.  */
+#define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000
+
+        /* This value for SEC_LINK_DUPLICATES means that the linker
+          should warn if any duplicate sections contain different
+          contents.  */
+#define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000
+
+        /* This section was created by the linker as part of dynamic
+          relocation or other arcane processing.  It is skipped when
+          going through the first-pass output, trusting that someone
+          else up the line will take care of it later.  */
+#define SEC_LINKER_CREATED 0x800000
+
+        /* This section should not be subject to garbage collection.  */
+#define SEC_KEEP 0x1000000
+
+        /* This section contains "short" data, and should be placed
+          "near" the GP.  */
+#define SEC_SMALL_DATA 0x2000000
+
+        /* This section contains data which may be shared with other
+          executables or shared objects.  */
+#define SEC_SHARED 0x4000000
+
+        /*  End of section flags.  */
+
+        /* Some internal packed boolean fields.  */
+
+        /* See the vma field.  */
+       unsigned int user_set_vma : 1;
+
+        /* Whether relocations have been processed.  */
+       unsigned int reloc_done : 1;
+
+        /* A mark flag used by some of the linker backends.  */
+       unsigned int linker_mark : 1;
+
+        /* A mark flag used by some linker backends for garbage collection.  */
+       unsigned int gc_mark : 1;
+
+        /* End of internal packed boolean fields.  */
+
+        /*  The virtual memory address of the section - where it will be
+           at run time.  The symbols are relocated against this.  The
+           user_set_vma flag is maintained by bfd; if it's not set, the
+           backend can assign addresses (for example, in <<a.out>>, where
+           the default address for <<.data>> is dependent on the specific
+           target and various flags).  */
+
+   bfd_vma vma;
+
+        /*  The load address of the section - where it would be in a
+           rom image; really only used for writing section header
+           information. */
+
+   bfd_vma lma;
+
+         /* The size of the section in bytes, as it will be output.
+           contains a value even if the section has no contents (e.g., the
+           size of <<.bss>>). This will be filled in after relocation */
+
+   bfd_size_type _cooked_size;
+
+         /* The original size on disk of the section, in bytes.  Normally this
+           value is the same as the size, but if some relaxing has
+           been done, then this value will be bigger.  */
+
+   bfd_size_type _raw_size;
+
+         /* If this section is going to be output, then this value is the
+           offset into the output section of the first byte in the input
+           section. E.g., if this was going to start at the 100th byte in
+           the output section, this value would be 100. */
+
+   bfd_vma output_offset;
+
+         /* The output section through which to map on output. */
+
+   struct sec *output_section;
+
+         /* The alignment requirement of the section, as an exponent of 2 -
+           e.g., 3 aligns to 2^3 (or 8). */
+
+   unsigned int alignment_power;
+
+         /* If an input section, a pointer to a vector of relocation
+           records for the data in this section. */
+
+   struct reloc_cache_entry *relocation;
+
+         /* If an output section, a pointer to a vector of pointers to
+           relocation records for the data in this section. */
+
+   struct reloc_cache_entry **orelocation;
+
+         /* The number of relocation records in one of the above  */
+
+   unsigned reloc_count;
+
+         /* Information below is back end specific - and not always used
+           or updated.  */
+
+         /* File position of section data    */
+
+   file_ptr filepos;
+
+         /* File position of relocation info */
+
+   file_ptr rel_filepos;
+
+         /* File position of line data       */
+
+   file_ptr line_filepos;
+
+         /* Pointer to data for applications */
+
+   PTR userdata;
+
+         /* If the SEC_IN_MEMORY flag is set, this points to the actual
+           contents.  */
+   unsigned char *contents;
+
+         /* Attached line number information */
+
+   alent *lineno;
+
+         /* Number of line number records   */
+
+   unsigned int lineno_count;
+
+         /* Optional information about a COMDAT entry; NULL if not COMDAT */
+
+   struct bfd_comdat_info *comdat;
+
+         /* When a section is being output, this value changes as more
+           linenumbers are written out */
+
+   file_ptr moving_line_filepos;
+
+         /* What the section number is in the target world  */
+
+   int target_index;
+
+   PTR used_by_bfd;
+
+         /* If this is a constructor section then here is a list of the
+           relocations created to relocate items within it. */
+
+   struct relent_chain *constructor_chain;
+
+         /* The BFD which owns the section. */
+
+   bfd *owner;
+
+         /* A symbol which points at this section only */
+   struct symbol_cache_entry *symbol;
+   struct symbol_cache_entry **symbol_ptr_ptr;
+
+   struct bfd_link_order *link_order_head;
+   struct bfd_link_order *link_order_tail;
+} asection ;
+
+     /* These sections are global, and are managed by BFD.  The application
+       and target back end are not permitted to change the values in
+       these sections.  New code should use the section_ptr macros rather
+       than referring directly to the const sections.  The const sections
+       may eventually vanish.  */
+#define BFD_ABS_SECTION_NAME "*ABS*"
+#define BFD_UND_SECTION_NAME "*UND*"
+#define BFD_COM_SECTION_NAME "*COM*"
+#define BFD_IND_SECTION_NAME "*IND*"
+
+     /* the absolute section */
+extern const asection bfd_abs_section;
+#define bfd_abs_section_ptr ((asection *) &bfd_abs_section)
+#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr)
+     /* Pointer to the undefined section */
+extern const asection bfd_und_section;
+#define bfd_und_section_ptr ((asection *) &bfd_und_section)
+#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr)
+     /* Pointer to the common section */
+extern const asection bfd_com_section;
+#define bfd_com_section_ptr ((asection *) &bfd_com_section)
+     /* Pointer to the indirect section */
+extern const asection bfd_ind_section;
+#define bfd_ind_section_ptr ((asection *) &bfd_ind_section)
+#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
+
+extern const struct symbol_cache_entry * const bfd_abs_symbol;
+extern const struct symbol_cache_entry * const bfd_com_symbol;
+extern const struct symbol_cache_entry * const bfd_und_symbol;
+extern const struct symbol_cache_entry * const bfd_ind_symbol;
+#define bfd_get_section_size_before_reloc(section) \
+     (section->reloc_done ? (abort(),1): (section)->_raw_size)
+#define bfd_get_section_size_after_reloc(section) \
+     ((section->reloc_done) ? (section)->_cooked_size: (abort(),1))
+asection *
+bfd_get_section_by_name PARAMS ((bfd *abfd, CONST char *name));
+
+asection *
+bfd_make_section_old_way PARAMS ((bfd *abfd, CONST char *name));
+
+asection *
+bfd_make_section_anyway PARAMS ((bfd *abfd, CONST char *name));
+
+asection *
+bfd_make_section PARAMS ((bfd *, CONST char *name));
+
+boolean 
+bfd_set_section_flags PARAMS ((bfd *abfd, asection *sec, flagword flags));
+
+void 
+bfd_map_over_sections PARAMS ((bfd *abfd,
+    void (*func)(bfd *abfd,
+    asection *sect,
+    PTR obj),
+    PTR obj));
+
+boolean 
+bfd_set_section_size PARAMS ((bfd *abfd, asection *sec, bfd_size_type val));
+
+boolean 
+bfd_set_section_contents
+ PARAMS ((bfd *abfd,
+    asection *section,
+    PTR data,
+    file_ptr offset,
+    bfd_size_type count));
+
+boolean 
+bfd_get_section_contents
+ PARAMS ((bfd *abfd, asection *section, PTR location,
+    file_ptr offset, bfd_size_type count));
+
+boolean 
+bfd_copy_private_section_data PARAMS ((bfd *ibfd, asection *isec, bfd *obfd, asection *osec));
+
+#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \
+     BFD_SEND (obfd, _bfd_copy_private_section_data, \
+               (ibfd, isection, obfd, osection))
+void 
+_bfd_strip_section_from_output
+ PARAMS ((asection *section));
+
+enum bfd_architecture 
+{
+  bfd_arch_unknown,    /* File arch not known */
+  bfd_arch_obscure,    /* Arch known, not one of these */
+  bfd_arch_m68k,       /* Motorola 68xxx */
+#define bfd_mach_m68000 1
+#define bfd_mach_m68008 2
+#define bfd_mach_m68010 3
+#define bfd_mach_m68020 4
+#define bfd_mach_m68030 5
+#define bfd_mach_m68040 6
+#define bfd_mach_m68060 7
+#define bfd_mach_cpu32  8
+  bfd_arch_vax,        /* DEC Vax */   
+  bfd_arch_i960,       /* Intel 960 */
+     /* The order of the following is important.
+       lower number indicates a machine type that 
+       only accepts a subset of the instructions
+       available to machines with higher numbers.
+       The exception is the "ca", which is
+       incompatible with all other machines except 
+       "core". */
+
+#define bfd_mach_i960_core      1
+#define bfd_mach_i960_ka_sa     2
+#define bfd_mach_i960_kb_sb     3
+#define bfd_mach_i960_mc        4
+#define bfd_mach_i960_xa        5
+#define bfd_mach_i960_ca        6
+#define bfd_mach_i960_jx        7
+#define bfd_mach_i960_hx        8
+
+  bfd_arch_a29k,       /* AMD 29000 */
+  bfd_arch_sparc,      /* SPARC */
+#define bfd_mach_sparc                 1
+ /* The difference between v8plus and v9 is that v9 is a true 64 bit env.  */
+#define bfd_mach_sparc_sparclet        2
+#define bfd_mach_sparc_sparclite       3
+#define bfd_mach_sparc_v8plus          4
+#define bfd_mach_sparc_v8plusa         5  /* with ultrasparc add'ns */
+#define bfd_mach_sparc_sparclite_le    6
+#define bfd_mach_sparc_v9              7
+#define bfd_mach_sparc_v9a             8  /* with ultrasparc add'ns */
+ /* Nonzero if MACH has the v9 instruction set.  */
+#define bfd_mach_sparc_v9_p(mach) \
+  ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9a)
+  bfd_arch_mips,       /* MIPS Rxxxx */
+#define bfd_mach_mips3000              3000
+#define bfd_mach_mips3900              3900
+#define bfd_mach_mips4000              4000
+#define bfd_mach_mips4010              4010
+#define bfd_mach_mips4100              4100
+#define bfd_mach_mips4111              4111
+#define bfd_mach_mips4300              4300
+#define bfd_mach_mips4400              4400
+#define bfd_mach_mips4600              4600
+#define bfd_mach_mips4650              4650
+#define bfd_mach_mips5000              5000
+#define bfd_mach_mips6000              6000
+#define bfd_mach_mips8000              8000
+#define bfd_mach_mips10000             10000
+#define bfd_mach_mips16                16
+  bfd_arch_i386,       /* Intel 386 */
+#define bfd_mach_i386_i386 0
+#define bfd_mach_i386_i8086 1
+#define bfd_mach_i386_i386_intel_syntax 2
+  bfd_arch_we32k,      /* AT&T WE32xxx */
+  bfd_arch_tahoe,      /* CCI/Harris Tahoe */
+  bfd_arch_i860,       /* Intel 860 */
+  bfd_arch_i370,       /* IBM 360/370 Mainframes */
+  bfd_arch_romp,       /* IBM ROMP PC/RT */
+  bfd_arch_alliant,    /* Alliant */
+  bfd_arch_convex,     /* Convex */
+  bfd_arch_m88k,       /* Motorola 88xxx */
+  bfd_arch_pyramid,    /* Pyramid Technology */
+  bfd_arch_h8300,      /* Hitachi H8/300 */
+#define bfd_mach_h8300   1
+#define bfd_mach_h8300h  2
+#define bfd_mach_h8300s  3
+  bfd_arch_powerpc,    /* PowerPC */
+  bfd_arch_rs6000,     /* IBM RS/6000 */
+  bfd_arch_hppa,       /* HP PA RISC */
+  bfd_arch_d10v,       /* Mitsubishi D10V */
+#define bfd_mach_d10v          0
+#define bfd_mach_d10v_ts2      2
+#define bfd_mach_d10v_ts3      3
+  bfd_arch_d30v,       /* Mitsubishi D30V */
+  bfd_arch_z8k,        /* Zilog Z8000 */
+#define bfd_mach_z8001         1
+#define bfd_mach_z8002         2
+  bfd_arch_h8500,      /* Hitachi H8/500 */
+  bfd_arch_sh,         /* Hitachi SH */
+#define bfd_mach_sh            0
+#define bfd_mach_sh3        0x30
+#define bfd_mach_sh3e       0x3e
+  bfd_arch_alpha,      /* Dec Alpha */
+#define bfd_mach_alpha_ev4  0x10
+#define bfd_mach_alpha_ev5  0x20
+#define bfd_mach_alpha_ev6  0x30
+  bfd_arch_arm,        /* Advanced Risc Machines ARM */
+#define bfd_mach_arm_2         1
+#define bfd_mach_arm_2a        2
+#define bfd_mach_arm_3         3
+#define bfd_mach_arm_3M        4
+#define bfd_mach_arm_4         5
+#define bfd_mach_arm_4T        6
+#define bfd_mach_arm_5         7
+#define bfd_mach_arm_5T        8
+  bfd_arch_ns32k,      /* National Semiconductors ns32000 */
+  bfd_arch_w65,        /* WDC 65816 */
+  bfd_arch_tic30,      /* Texas Instruments TMS320C30 */
+  bfd_arch_tic80,      /* TI TMS320c80 (MVP) */
+  bfd_arch_v850,       /* NEC V850 */
+#define bfd_mach_v850          0
+#define bfd_mach_v850e         'E'
+#define bfd_mach_v850ea        'A'
+  bfd_arch_arc,        /* Argonaut RISC Core */
+#define bfd_mach_arc_base 0
+  bfd_arch_m32r,       /* Mitsubishi M32R/D */
+#define bfd_mach_m32r          0  /* backwards compatibility */
+#define bfd_mach_m32rx         'x'
+  bfd_arch_mn10200,    /* Matsushita MN10200 */
+  bfd_arch_mn10300,    /* Matsushita MN10300 */
+#define bfd_mach_mn10300               300
+#define bfd_mach_am33          330
+  bfd_arch_fr30,
+#define bfd_mach_fr30          0x46523330
+  bfd_arch_mcore,
+  bfd_arch_pj,
+  bfd_arch_last
+  };
+
+typedef struct bfd_arch_info 
+{
+  int bits_per_word;
+  int bits_per_address;
+  int bits_per_byte;
+  enum bfd_architecture arch;
+  unsigned long mach;
+  const char *arch_name;
+  const char *printable_name;
+  unsigned int section_align_power;
+  /* true if this is the default machine for the architecture */
+  boolean the_default; 
+  const struct bfd_arch_info * (*compatible)
+       PARAMS ((const struct bfd_arch_info *a,
+                const struct bfd_arch_info *b));
+
+  boolean (*scan) PARAMS ((const struct bfd_arch_info *, const char *));
+
+  const struct bfd_arch_info *next;
+} bfd_arch_info_type;
+const char *
+bfd_printable_name PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_scan_arch PARAMS ((const char *string));
+
+const char **
+bfd_arch_list PARAMS ((void));
+
+const bfd_arch_info_type *
+bfd_arch_get_compatible PARAMS ((
+    const bfd *abfd,
+    const bfd *bbfd));
+
+void 
+bfd_set_arch_info PARAMS ((bfd *abfd, const bfd_arch_info_type *arg));
+
+enum bfd_architecture 
+bfd_get_arch PARAMS ((bfd *abfd));
+
+unsigned long 
+bfd_get_mach PARAMS ((bfd *abfd));
+
+unsigned int 
+bfd_arch_bits_per_byte PARAMS ((bfd *abfd));
+
+unsigned int 
+bfd_arch_bits_per_address PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type * 
+bfd_get_arch_info PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_lookup_arch
+ PARAMS ((enum bfd_architecture
+    arch,
+    unsigned long machine));
+
+const char *
+bfd_printable_arch_mach
+ PARAMS ((enum bfd_architecture arch, unsigned long machine));
+
+typedef enum bfd_reloc_status
+{
+        /* No errors detected */
+  bfd_reloc_ok,
+
+        /* The relocation was performed, but there was an overflow. */
+  bfd_reloc_overflow,
+
+        /* The address to relocate was not within the section supplied. */
+  bfd_reloc_outofrange,
+
+        /* Used by special functions */
+  bfd_reloc_continue,
+
+        /* Unsupported relocation size requested. */
+  bfd_reloc_notsupported,
+
+        /* Unused */
+  bfd_reloc_other,
+
+        /* The symbol to relocate against was undefined. */
+  bfd_reloc_undefined,
+
+        /* The relocation was performed, but may not be ok - presently
+          generated only when linking i960 coff files with i960 b.out
+          symbols.  If this type is returned, the error_message argument
+          to bfd_perform_relocation will be set.  */
+  bfd_reloc_dangerous
+ }
+ bfd_reloc_status_type;
+
+
+typedef struct reloc_cache_entry
+{
+        /* A pointer into the canonical table of pointers  */
+  struct symbol_cache_entry **sym_ptr_ptr;
+
+        /* offset in section */
+  bfd_size_type address;
+
+        /* addend for relocation value */
+  bfd_vma addend;
+
+        /* Pointer to how to perform the required relocation */
+  reloc_howto_type *howto;
+
+} arelent;
+enum complain_overflow
+{
+        /* Do not complain on overflow. */
+  complain_overflow_dont,
+
+        /* Complain if the bitfield overflows, whether it is considered
+          as signed or unsigned. */
+  complain_overflow_bitfield,
+
+        /* Complain if the value overflows when considered as signed
+          number. */
+  complain_overflow_signed,
+
+        /* Complain if the value overflows when considered as an
+          unsigned number. */
+  complain_overflow_unsigned
+};
+
+struct reloc_howto_struct
+{
+        /*  The type field has mainly a documentary use - the back end can
+           do what it wants with it, though normally the back end's
+           external idea of what a reloc number is stored
+           in this field. For example, a PC relative word relocation
+           in a coff environment has the type 023 - because that's
+           what the outside world calls a R_PCRWORD reloc. */
+  unsigned int type;
+
+        /*  The value the final relocation is shifted right by. This drops
+           unwanted data from the relocation.  */
+  unsigned int rightshift;
+
+        /*  The size of the item to be relocated.  This is *not* a
+           power-of-two measure.  To get the number of bytes operated
+           on by a type of relocation, use bfd_get_reloc_size.  */
+  int size;
+
+        /*  The number of bits in the item to be relocated.  This is used
+           when doing overflow checking.  */
+  unsigned int bitsize;
+
+        /*  Notes that the relocation is relative to the location in the
+           data section of the addend. The relocation function will
+           subtract from the relocation value the address of the location
+           being relocated. */
+  boolean pc_relative;
+
+        /*  The bit position of the reloc value in the destination.
+           The relocated value is left shifted by this amount. */
+  unsigned int bitpos;
+
+        /* What type of overflow error should be checked for when
+          relocating. */
+  enum complain_overflow complain_on_overflow;
+
+        /* If this field is non null, then the supplied function is
+          called rather than the normal function. This allows really
+          strange relocation methods to be accomodated (e.g., i960 callj
+          instructions). */
+  bfd_reloc_status_type (*special_function)
+                                   PARAMS ((bfd *abfd,
+                                            arelent *reloc_entry,
+                                            struct symbol_cache_entry *symbol,
+                                            PTR data,
+                                            asection *input_section,
+                                            bfd *output_bfd,
+                                            char **error_message));
+
+        /* The textual name of the relocation type. */
+  char *name;
+
+        /* When performing a partial link, some formats must modify the
+          relocations rather than the data - this flag signals this.*/
+  boolean partial_inplace;
+
+        /* The src_mask selects which parts of the read in data
+          are to be used in the relocation sum.  E.g., if this was an 8 bit
+          bit of data which we read and relocated, this would be
+          0x000000ff. When we have relocs which have an addend, such as
+          sun4 extended relocs, the value in the offset part of a
+          relocating field is garbage so we never use it. In this case
+          the mask would be 0x00000000. */
+  bfd_vma src_mask;
+
+        /* The dst_mask selects which parts of the instruction are replaced
+          into the instruction. In most cases src_mask == dst_mask,
+          except in the above special case, where dst_mask would be
+          0x000000ff, and src_mask would be 0x00000000.   */
+  bfd_vma dst_mask;
+
+        /* When some formats create PC relative instructions, they leave
+          the value of the pc of the place being relocated in the offset
+          slot of the instruction, so that a PC relative relocation can
+          be made just by adding in an ordinary offset (e.g., sun3 a.out).
+          Some formats leave the displacement part of an instruction
+          empty (e.g., m88k bcs); this flag signals the fact.*/
+  boolean pcrel_offset;
+
+};
+#define HOWTO(C, R,S,B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
+  {(unsigned)C,R,S,B, P, BI, O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC}
+#define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,complain_overflow_dont,FUNCTION, NAME,false,0,0,IN)
+
+#define EMPTY_HOWTO(C) \
+  HOWTO((C),0,0,0,false,0,complain_overflow_dont,NULL,NULL,false,0,0,false)
+
+#define HOWTO_PREPARE(relocation, symbol)      \
+  {                                            \
+  if (symbol != (asymbol *)NULL) {             \
+    if (bfd_is_com_section (symbol->section)) { \
+      relocation = 0;                          \
+    }                                          \
+    else {                                     \
+      relocation = symbol->value;              \
+    }                                          \
+  }                                            \
+}
+unsigned int 
+bfd_get_reloc_size  PARAMS ((reloc_howto_type *));
+
+typedef struct relent_chain {
+  arelent relent;
+  struct   relent_chain *next;
+} arelent_chain;
+bfd_reloc_status_type
+
+bfd_check_overflow
+ PARAMS ((enum complain_overflow how,
+    unsigned int bitsize,
+    unsigned int rightshift,
+    unsigned int addrsize,
+    bfd_vma relocation));
+
+bfd_reloc_status_type
+
+bfd_perform_relocation
+ PARAMS ((bfd *abfd,
+    arelent *reloc_entry,
+    PTR data,
+    asection *input_section,
+    bfd *output_bfd,
+    char **error_message));
+
+bfd_reloc_status_type
+
+bfd_install_relocation
+ PARAMS ((bfd *abfd,
+    arelent *reloc_entry,
+    PTR data, bfd_vma data_start,
+    asection *input_section,
+    char **error_message));
+
+enum bfd_reloc_code_real {
+  _dummy_first_bfd_reloc_code_real,
+
+
+/* Basic absolute relocations of N bits. */
+  BFD_RELOC_64,
+  BFD_RELOC_32,
+  BFD_RELOC_26,
+  BFD_RELOC_24,
+  BFD_RELOC_16,
+  BFD_RELOC_14,
+  BFD_RELOC_8,
+
+/* PC-relative relocations.  Sometimes these are relative to the address
+of the relocation itself; sometimes they are relative to the start of
+the section containing the relocation.  It depends on the specific target.
+
+The 24-bit relocation is used in some Intel 960 configurations. */
+  BFD_RELOC_64_PCREL,
+  BFD_RELOC_32_PCREL,
+  BFD_RELOC_24_PCREL,
+  BFD_RELOC_16_PCREL,
+  BFD_RELOC_12_PCREL,
+  BFD_RELOC_8_PCREL,
+
+/* For ELF. */
+  BFD_RELOC_32_GOT_PCREL,
+  BFD_RELOC_16_GOT_PCREL,
+  BFD_RELOC_8_GOT_PCREL,
+  BFD_RELOC_32_GOTOFF,
+  BFD_RELOC_16_GOTOFF,
+  BFD_RELOC_LO16_GOTOFF,
+  BFD_RELOC_HI16_GOTOFF,
+  BFD_RELOC_HI16_S_GOTOFF,
+  BFD_RELOC_8_GOTOFF,
+  BFD_RELOC_32_PLT_PCREL,
+  BFD_RELOC_24_PLT_PCREL,
+  BFD_RELOC_16_PLT_PCREL,
+  BFD_RELOC_8_PLT_PCREL,
+  BFD_RELOC_32_PLTOFF,
+  BFD_RELOC_16_PLTOFF,
+  BFD_RELOC_LO16_PLTOFF,
+  BFD_RELOC_HI16_PLTOFF,
+  BFD_RELOC_HI16_S_PLTOFF,
+  BFD_RELOC_8_PLTOFF,
+
+/* Relocations used by 68K ELF. */
+  BFD_RELOC_68K_GLOB_DAT,
+  BFD_RELOC_68K_JMP_SLOT,
+  BFD_RELOC_68K_RELATIVE,
+
+/* Linkage-table relative. */
+  BFD_RELOC_32_BASEREL,
+  BFD_RELOC_16_BASEREL,
+  BFD_RELOC_LO16_BASEREL,
+  BFD_RELOC_HI16_BASEREL,
+  BFD_RELOC_HI16_S_BASEREL,
+  BFD_RELOC_8_BASEREL,
+  BFD_RELOC_RVA,
+
+/* Absolute 8-bit relocation, but used to form an address like 0xFFnn. */
+  BFD_RELOC_8_FFnn,
+
+/* These PC-relative relocations are stored as word displacements --
+i.e., byte displacements shifted right two bits.  The 30-bit word
+displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the
+SPARC.  (SPARC tools generally refer to this as <<WDISP30>>.)  The
+signed 16-bit displacement is used on the MIPS, and the 23-bit
+displacement is used on the Alpha. */
+  BFD_RELOC_32_PCREL_S2,
+  BFD_RELOC_16_PCREL_S2,
+  BFD_RELOC_23_PCREL_S2,
+
+/* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of
+the target word.  These are used on the SPARC. */
+  BFD_RELOC_HI22,
+  BFD_RELOC_LO10,
+
+/* For systems that allocate a Global Pointer register, these are
+displacements off that register.  These relocation types are
+handled specially, because the value the register will have is
+decided relatively late. */
+  BFD_RELOC_GPREL16,
+  BFD_RELOC_GPREL32,
+
+/* Reloc types used for i960/b.out. */
+  BFD_RELOC_I960_CALLJ,
+
+/* SPARC ELF relocations.  There is probably some overlap with other
+relocation types already defined. */
+  BFD_RELOC_NONE,
+  BFD_RELOC_SPARC_WDISP22,
+  BFD_RELOC_SPARC22,
+  BFD_RELOC_SPARC13,
+  BFD_RELOC_SPARC_GOT10,
+  BFD_RELOC_SPARC_GOT13,
+  BFD_RELOC_SPARC_GOT22,
+  BFD_RELOC_SPARC_PC10,
+  BFD_RELOC_SPARC_PC22,
+  BFD_RELOC_SPARC_WPLT30,
+  BFD_RELOC_SPARC_COPY,
+  BFD_RELOC_SPARC_GLOB_DAT,
+  BFD_RELOC_SPARC_JMP_SLOT,
+  BFD_RELOC_SPARC_RELATIVE,
+  BFD_RELOC_SPARC_UA32,
+
+/* I think these are specific to SPARC a.out (e.g., Sun 4). */
+  BFD_RELOC_SPARC_BASE13,
+  BFD_RELOC_SPARC_BASE22,
+
+/* SPARC64 relocations */
+#define BFD_RELOC_SPARC_64 BFD_RELOC_64
+  BFD_RELOC_SPARC_10,
+  BFD_RELOC_SPARC_11,
+  BFD_RELOC_SPARC_OLO10,
+  BFD_RELOC_SPARC_HH22,
+  BFD_RELOC_SPARC_HM10,
+  BFD_RELOC_SPARC_LM22,
+  BFD_RELOC_SPARC_PC_HH22,
+  BFD_RELOC_SPARC_PC_HM10,
+  BFD_RELOC_SPARC_PC_LM22,
+  BFD_RELOC_SPARC_WDISP16,
+  BFD_RELOC_SPARC_WDISP19,
+  BFD_RELOC_SPARC_7,
+  BFD_RELOC_SPARC_6,
+  BFD_RELOC_SPARC_5,
+#define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL
+  BFD_RELOC_SPARC_PLT64,
+  BFD_RELOC_SPARC_HIX22,
+  BFD_RELOC_SPARC_LOX10,
+  BFD_RELOC_SPARC_H44,
+  BFD_RELOC_SPARC_M44,
+  BFD_RELOC_SPARC_L44,
+  BFD_RELOC_SPARC_REGISTER,
+
+/* SPARC little endian relocation */
+  BFD_RELOC_SPARC_REV32,
+
+/* Alpha ECOFF and ELF relocations.  Some of these treat the symbol or
+"addend" in some special way.
+For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when
+writing; when reading, it will be the absolute section symbol.  The
+addend is the displacement in bytes of the "lda" instruction from
+the "ldah" instruction (which is at the address of this reloc). */
+  BFD_RELOC_ALPHA_GPDISP_HI16,
+
+/* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as
+with GPDISP_HI16 relocs.  The addend is ignored when writing the
+relocations out, and is filled in with the file's GP value on
+reading, for convenience. */
+  BFD_RELOC_ALPHA_GPDISP_LO16,
+
+/* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16
+relocation except that there is no accompanying GPDISP_LO16
+relocation. */
+  BFD_RELOC_ALPHA_GPDISP,
+
+/* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference;
+the assembler turns it into a LDQ instruction to load the address of
+the symbol, and then fills in a register in the real instruction.
+
+The LITERAL reloc, at the LDQ instruction, refers to the .lita
+section symbol.  The addend is ignored when writing, but is filled
+in with the file's GP value on reading, for convenience, as with the
+GPDISP_LO16 reloc.
+
+The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16.
+It should refer to the symbol to be referenced, as with 16_GOTOFF,
+but it generates output not based on the position within the .got
+section, but relative to the GP value chosen for the file during the
+final link stage.
+
+The LITUSE reloc, on the instruction using the loaded address, gives
+information to the linker that it might be able to use to optimize
+away some literal section references.  The symbol is ignored (read
+as the absolute section symbol), and the "addend" indicates the type
+of instruction using the register:
+1 - "memory" fmt insn
+2 - byte-manipulation (byte offset reg)
+3 - jsr (target of branch)
+
+The GNU linker currently doesn't do any of this optimizing. */
+  BFD_RELOC_ALPHA_LITERAL,
+  BFD_RELOC_ALPHA_ELF_LITERAL,
+  BFD_RELOC_ALPHA_LITUSE,
+
+/* The BFD_RELOC_ALPHA_USER_* relocations are used by the assembler to
+process the explicit !<reloc>!sequence relocations, and are mapped
+into the normal relocations at the end of processing. */
+  BFD_RELOC_ALPHA_USER_LITERAL,
+  BFD_RELOC_ALPHA_USER_LITUSE_BASE,
+  BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF,
+  BFD_RELOC_ALPHA_USER_LITUSE_JSR,
+  BFD_RELOC_ALPHA_USER_GPDISP,
+  BFD_RELOC_ALPHA_USER_GPRELHIGH,
+  BFD_RELOC_ALPHA_USER_GPRELLOW,
+
+/* The HINT relocation indicates a value that should be filled into the
+"hint" field of a jmp/jsr/ret instruction, for possible branch-
+prediction logic which may be provided on some processors. */
+  BFD_RELOC_ALPHA_HINT,
+
+/* The LINKAGE relocation outputs a linkage pair in the object file,
+which is filled by the linker. */
+  BFD_RELOC_ALPHA_LINKAGE,
+
+/* The CODEADDR relocation outputs a STO_CA in the object file,
+which is filled by the linker. */
+  BFD_RELOC_ALPHA_CODEADDR,
+
+/* Bits 27..2 of the relocation address shifted right 2 bits;
+simple reloc otherwise. */
+  BFD_RELOC_MIPS_JMP,
+
+/* The MIPS16 jump instruction. */
+  BFD_RELOC_MIPS16_JMP,
+
+/* MIPS16 GP relative reloc. */
+  BFD_RELOC_MIPS16_GPREL,
+
+/* High 16 bits of 32-bit value; simple reloc. */
+  BFD_RELOC_HI16,
+
+/* High 16 bits of 32-bit value but the low 16 bits will be sign
+extended and added to form the final result.  If the low 16
+bits form a negative number, we need to add one to the high value
+to compensate for the borrow when the low bits are added. */
+  BFD_RELOC_HI16_S,
+
+/* Low 16 bits. */
+  BFD_RELOC_LO16,
+
+/* Like BFD_RELOC_HI16_S, but PC relative. */
+  BFD_RELOC_PCREL_HI16_S,
+
+/* Like BFD_RELOC_LO16, but PC relative. */
+  BFD_RELOC_PCREL_LO16,
+
+/* Relocation relative to the global pointer. */
+#define BFD_RELOC_MIPS_GPREL BFD_RELOC_GPREL16
+
+/* Relocation against a MIPS literal section. */
+  BFD_RELOC_MIPS_LITERAL,
+
+/* MIPS ELF relocations. */
+  BFD_RELOC_MIPS_GOT16,
+  BFD_RELOC_MIPS_CALL16,
+#define BFD_RELOC_MIPS_GPREL32 BFD_RELOC_GPREL32
+  BFD_RELOC_MIPS_GOT_HI16,
+  BFD_RELOC_MIPS_GOT_LO16,
+  BFD_RELOC_MIPS_CALL_HI16,
+  BFD_RELOC_MIPS_CALL_LO16,
+  BFD_RELOC_MIPS_SUB,
+  BFD_RELOC_MIPS_GOT_PAGE,
+  BFD_RELOC_MIPS_GOT_OFST,
+  BFD_RELOC_MIPS_GOT_DISP,
+
+
+/* i386/elf relocations */
+  BFD_RELOC_386_GOT32,
+  BFD_RELOC_386_PLT32,
+  BFD_RELOC_386_COPY,
+  BFD_RELOC_386_GLOB_DAT,
+  BFD_RELOC_386_JUMP_SLOT,
+  BFD_RELOC_386_RELATIVE,
+  BFD_RELOC_386_GOTOFF,
+  BFD_RELOC_386_GOTPC,
+
+/* ns32k relocations */
+  BFD_RELOC_NS32K_IMM_8,
+  BFD_RELOC_NS32K_IMM_16,
+  BFD_RELOC_NS32K_IMM_32,
+  BFD_RELOC_NS32K_IMM_8_PCREL,
+  BFD_RELOC_NS32K_IMM_16_PCREL,
+  BFD_RELOC_NS32K_IMM_32_PCREL,
+  BFD_RELOC_NS32K_DISP_8,
+  BFD_RELOC_NS32K_DISP_16,
+  BFD_RELOC_NS32K_DISP_32,
+  BFD_RELOC_NS32K_DISP_8_PCREL,
+  BFD_RELOC_NS32K_DISP_16_PCREL,
+  BFD_RELOC_NS32K_DISP_32_PCREL,
+
+/* Picojava relocs.  Not all of these appear in object files. */
+  BFD_RELOC_PJ_CODE_HI16,
+  BFD_RELOC_PJ_CODE_LO16,
+  BFD_RELOC_PJ_CODE_DIR16,
+  BFD_RELOC_PJ_CODE_DIR32,
+  BFD_RELOC_PJ_CODE_REL16,
+  BFD_RELOC_PJ_CODE_REL32,
+
+/* Power(rs6000) and PowerPC relocations. */
+  BFD_RELOC_PPC_B26,
+  BFD_RELOC_PPC_BA26,
+  BFD_RELOC_PPC_TOC16,
+  BFD_RELOC_PPC_B16,
+  BFD_RELOC_PPC_B16_BRTAKEN,
+  BFD_RELOC_PPC_B16_BRNTAKEN,
+  BFD_RELOC_PPC_BA16,
+  BFD_RELOC_PPC_BA16_BRTAKEN,
+  BFD_RELOC_PPC_BA16_BRNTAKEN,
+  BFD_RELOC_PPC_COPY,
+  BFD_RELOC_PPC_GLOB_DAT,
+  BFD_RELOC_PPC_JMP_SLOT,
+  BFD_RELOC_PPC_RELATIVE,
+  BFD_RELOC_PPC_LOCAL24PC,
+  BFD_RELOC_PPC_EMB_NADDR32,
+  BFD_RELOC_PPC_EMB_NADDR16,
+  BFD_RELOC_PPC_EMB_NADDR16_LO,
+  BFD_RELOC_PPC_EMB_NADDR16_HI,
+  BFD_RELOC_PPC_EMB_NADDR16_HA,
+  BFD_RELOC_PPC_EMB_SDAI16,
+  BFD_RELOC_PPC_EMB_SDA2I16,
+  BFD_RELOC_PPC_EMB_SDA2REL,
+  BFD_RELOC_PPC_EMB_SDA21,
+  BFD_RELOC_PPC_EMB_MRKREF,
+  BFD_RELOC_PPC_EMB_RELSEC16,
+  BFD_RELOC_PPC_EMB_RELST_LO,
+  BFD_RELOC_PPC_EMB_RELST_HI,
+  BFD_RELOC_PPC_EMB_RELST_HA,
+  BFD_RELOC_PPC_EMB_BIT_FLD,
+  BFD_RELOC_PPC_EMB_RELSDA,
+
+/* Instruction 370/390 relocations */
+  BFD_RELOC_I370_D12,
+
+/* The type of reloc used to build a contructor table - at the moment
+probably a 32 bit wide absolute relocation, but the target can choose.
+It generally does map to one of the other relocation types. */
+  BFD_RELOC_CTOR,
+
+/* ARM 26 bit pc-relative branch.  The lowest two bits must be zero and are
+not stored in the instruction. */
+  BFD_RELOC_ARM_PCREL_BRANCH,
+
+/* These relocs are only used within the ARM assembler.  They are not
+(at present) written to any object files. */
+  BFD_RELOC_ARM_IMMEDIATE,
+  BFD_RELOC_ARM_ADRL_IMMEDIATE,
+  BFD_RELOC_ARM_OFFSET_IMM,
+  BFD_RELOC_ARM_SHIFT_IMM,
+  BFD_RELOC_ARM_SWI,
+  BFD_RELOC_ARM_MULTI,
+  BFD_RELOC_ARM_CP_OFF_IMM,
+  BFD_RELOC_ARM_ADR_IMM,
+  BFD_RELOC_ARM_LDR_IMM,
+  BFD_RELOC_ARM_LITERAL,
+  BFD_RELOC_ARM_IN_POOL,
+  BFD_RELOC_ARM_OFFSET_IMM8,
+  BFD_RELOC_ARM_HWLITERAL,
+  BFD_RELOC_ARM_THUMB_ADD,
+  BFD_RELOC_ARM_THUMB_IMM,
+  BFD_RELOC_ARM_THUMB_SHIFT,
+  BFD_RELOC_ARM_THUMB_OFFSET,
+  BFD_RELOC_ARM_GOT12,
+  BFD_RELOC_ARM_GOT32,
+  BFD_RELOC_ARM_JUMP_SLOT,
+  BFD_RELOC_ARM_COPY,
+  BFD_RELOC_ARM_GLOB_DAT,
+  BFD_RELOC_ARM_PLT32,
+  BFD_RELOC_ARM_RELATIVE,
+  BFD_RELOC_ARM_GOTOFF,
+  BFD_RELOC_ARM_GOTPC,
+
+/* Hitachi SH relocs.  Not all of these appear in object files. */
+  BFD_RELOC_SH_PCDISP8BY2,
+  BFD_RELOC_SH_PCDISP12BY2,
+  BFD_RELOC_SH_IMM4,
+  BFD_RELOC_SH_IMM4BY2,
+  BFD_RELOC_SH_IMM4BY4,
+  BFD_RELOC_SH_IMM8,
+  BFD_RELOC_SH_IMM8BY2,
+  BFD_RELOC_SH_IMM8BY4,
+  BFD_RELOC_SH_PCRELIMM8BY2,
+  BFD_RELOC_SH_PCRELIMM8BY4,
+  BFD_RELOC_SH_SWITCH16,
+  BFD_RELOC_SH_SWITCH32,
+  BFD_RELOC_SH_USES,
+  BFD_RELOC_SH_COUNT,
+  BFD_RELOC_SH_ALIGN,
+  BFD_RELOC_SH_CODE,
+  BFD_RELOC_SH_DATA,
+  BFD_RELOC_SH_LABEL,
+
+/* Thumb 23-, 12- and 9-bit pc-relative branches.  The lowest bit must
+be zero and is not stored in the instruction. */
+  BFD_RELOC_THUMB_PCREL_BRANCH9,
+  BFD_RELOC_THUMB_PCREL_BRANCH12,
+  BFD_RELOC_THUMB_PCREL_BRANCH23,
+
+/* Argonaut RISC Core (ARC) relocs.
+ARC 22 bit pc-relative branch.  The lowest two bits must be zero and are
+not stored in the instruction.  The high 20 bits are installed in bits 26
+through 7 of the instruction. */
+  BFD_RELOC_ARC_B22_PCREL,
+
+/* ARC 26 bit absolute branch.  The lowest two bits must be zero and are not
+stored in the instruction.  The high 24 bits are installed in bits 23
+through 0. */
+  BFD_RELOC_ARC_B26,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. */
+  BFD_RELOC_D10V_10_PCREL_R,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0.  This is the same as the previous reloc
+except it is in the left container, i.e.,
+shifted left 15 bits. */
+  BFD_RELOC_D10V_10_PCREL_L,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+  BFD_RELOC_D10V_18,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+  BFD_RELOC_D10V_18_PCREL,
+
+/* Mitsubishi D30V relocs.
+This is a 6-bit absolute reloc. */
+  BFD_RELOC_D30V_6,
+
+/* This is a 6-bit pc-relative reloc with 
+the right 3 bits assumed to be 0. */
+  BFD_RELOC_D30V_9_PCREL,
+
+/* This is a 6-bit pc-relative reloc with 
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+  BFD_RELOC_D30V_9_PCREL_R,
+
+/* This is a 12-bit absolute reloc with the 
+right 3 bitsassumed to be 0. */
+  BFD_RELOC_D30V_15,
+
+/* This is a 12-bit pc-relative reloc with 
+the right 3 bits assumed to be 0. */
+  BFD_RELOC_D30V_15_PCREL,
+
+/* This is a 12-bit pc-relative reloc with 
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+  BFD_RELOC_D30V_15_PCREL_R,
+
+/* This is an 18-bit absolute reloc with 
+the right 3 bits assumed to be 0. */
+  BFD_RELOC_D30V_21,
+
+/* This is an 18-bit pc-relative reloc with 
+the right 3 bits assumed to be 0. */
+  BFD_RELOC_D30V_21_PCREL,
+
+/* This is an 18-bit pc-relative reloc with 
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+  BFD_RELOC_D30V_21_PCREL_R,
+
+/* This is a 32-bit absolute reloc. */
+  BFD_RELOC_D30V_32,
+
+/* This is a 32-bit pc-relative reloc. */
+  BFD_RELOC_D30V_32_PCREL,
+
+/* Mitsubishi M32R relocs.
+This is a 24 bit absolute address. */
+  BFD_RELOC_M32R_24,
+
+/* This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. */
+  BFD_RELOC_M32R_10_PCREL,
+
+/* This is an 18-bit reloc with the right 2 bits assumed to be 0. */
+  BFD_RELOC_M32R_18_PCREL,
+
+/* This is a 26-bit reloc with the right 2 bits assumed to be 0. */
+  BFD_RELOC_M32R_26_PCREL,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as unsigned. */
+  BFD_RELOC_M32R_HI16_ULO,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as signed. */
+  BFD_RELOC_M32R_HI16_SLO,
+
+/* This is a 16-bit reloc containing the lower 16 bits of an address. */
+  BFD_RELOC_M32R_LO16,
+
+/* This is a 16-bit reloc containing the small data area offset for use in
+add3, load, and store instructions. */
+  BFD_RELOC_M32R_SDA16,
+
+/* This is a 9-bit reloc */
+  BFD_RELOC_V850_9_PCREL,
+
+/* This is a 22-bit reloc */
+  BFD_RELOC_V850_22_PCREL,
+
+/* This is a 16 bit offset from the short data area pointer. */
+  BFD_RELOC_V850_SDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+short data area pointer. */
+  BFD_RELOC_V850_SDA_15_16_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer. */
+  BFD_RELOC_V850_ZDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+zero data area pointer. */
+  BFD_RELOC_V850_ZDA_15_16_OFFSET,
+
+/* This is an 8 bit offset (of which only 6 bits are used) from the
+tiny data area pointer. */
+  BFD_RELOC_V850_TDA_6_8_OFFSET,
+
+/* This is an 8bit offset (of which only 7 bits are used) from the tiny
+data area pointer. */
+  BFD_RELOC_V850_TDA_7_8_OFFSET,
+
+/* This is a 7 bit offset from the tiny data area pointer. */
+  BFD_RELOC_V850_TDA_7_7_OFFSET,
+
+/* This is a 16 bit offset from the tiny data area pointer. */
+  BFD_RELOC_V850_TDA_16_16_OFFSET,
+
+/* This is a 5 bit offset (of which only 4 bits are used) from the tiny
+data area pointer. */
+  BFD_RELOC_V850_TDA_4_5_OFFSET,
+
+/* This is a 4 bit offset from the tiny data area pointer. */
+  BFD_RELOC_V850_TDA_4_4_OFFSET,
+
+/* This is a 16 bit offset from the short data area pointer, with the
+bits placed non-contigously in the instruction. */
+  BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer, with the
+bits placed non-contigously in the instruction. */
+  BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET,
+
+/* This is a 6 bit offset from the call table base pointer. */
+  BFD_RELOC_V850_CALLT_6_7_OFFSET,
+
+/* This is a 16 bit offset from the call table base pointer. */
+  BFD_RELOC_V850_CALLT_16_16_OFFSET,
+
+
+/* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+  BFD_RELOC_MN10300_32_PCREL,
+
+/* This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+  BFD_RELOC_MN10300_16_PCREL,
+
+/* This is a 8bit DP reloc for the tms320c30, where the most
+significant 8 bits of a 24 bit word are placed into the least
+significant 8 bits of the opcode. */
+  BFD_RELOC_TIC30_LDP,
+
+/* This is a 48 bit reloc for the FR30 that stores 32 bits. */
+  BFD_RELOC_FR30_48,
+
+/* This is a 32 bit reloc for the FR30 that stores 20 bits split up into
+two sections. */
+  BFD_RELOC_FR30_20,
+
+/* This is a 16 bit reloc for the FR30 that stores a 6 bit word offset in
+4 bits. */
+  BFD_RELOC_FR30_6_IN_4,
+
+/* This is a 16 bit reloc for the FR30 that stores an 8 bit byte offset
+into 8 bits. */
+  BFD_RELOC_FR30_8_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit short offset
+into 8 bits. */
+  BFD_RELOC_FR30_9_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 10 bit word offset
+into 8 bits. */
+  BFD_RELOC_FR30_10_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit pc relative
+short offset into 8 bits. */
+  BFD_RELOC_FR30_9_PCREL,
+
+/* This is a 16 bit reloc for the FR30 that stores a 12 bit pc relative
+short offset into 11 bits. */
+  BFD_RELOC_FR30_12_PCREL,
+
+/* Motorola Mcore relocations. */
+  BFD_RELOC_MCORE_PCREL_IMM8BY4,
+  BFD_RELOC_MCORE_PCREL_IMM11BY2,
+  BFD_RELOC_MCORE_PCREL_IMM4BY2,
+  BFD_RELOC_MCORE_PCREL_32,
+  BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2,
+  BFD_RELOC_MCORE_RVA,
+
+/* These two relocations are used by the linker to determine which of 
+the entries in a C++ virtual function table are actually used.  When
+the --gc-sections option is given, the linker will zero out the entries
+that are not used, so that the code for those functions need not be
+included in the output.
+
+VTABLE_INHERIT is a zero-space relocation used to describe to the
+linker the inheritence tree of a C++ virtual function table.  The
+relocation's symbol should be the parent class' vtable, and the
+relocation should be located at the child vtable.
+
+VTABLE_ENTRY is a zero-space relocation that describes the use of a
+virtual function table entry.  The reloc's symbol should refer to the
+table of the class mentioned in the code.  Off of that base, an offset
+describes the entry that is being used.  For Rela hosts, this offset 
+is stored in the reloc's addend.  For Rel hosts, we are forced to put
+this offset in the reloc's section offset. */
+  BFD_RELOC_VTABLE_INHERIT,
+  BFD_RELOC_VTABLE_ENTRY,
+  BFD_RELOC_UNUSED };
+typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+reloc_howto_type *
+
+bfd_reloc_type_lookup  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+
+const char *
+bfd_get_reloc_code_name  PARAMS ((bfd_reloc_code_real_type code));
+
+
+typedef struct symbol_cache_entry
+{
+        /* A pointer to the BFD which owns the symbol. This information
+          is necessary so that a back end can work out what additional
+          information (invisible to the application writer) is carried
+          with the symbol.
+
+          This field is *almost* redundant, since you can use section->owner
+          instead, except that some symbols point to the global sections
+          bfd_{abs,com,und}_section.  This could be fixed by making
+          these globals be per-bfd (or per-target-flavor).  FIXME. */
+
+  struct _bfd *the_bfd;  /* Use bfd_asymbol_bfd(sym) to access this field. */
+
+        /* The text of the symbol. The name is left alone, and not copied; the
+          application may not alter it. */
+  CONST char *name;
+
+        /* The value of the symbol.  This really should be a union of a
+          numeric value with a pointer, since some flags indicate that
+          a pointer to another symbol is stored here.  */
+  symvalue value;
+
+        /* Attributes of a symbol: */
+
+#define BSF_NO_FLAGS    0x00
+
+        /* The symbol has local scope; <<static>> in <<C>>. The value
+          is the offset into the section of the data. */
+#define BSF_LOCAL      0x01
+
+        /* The symbol has global scope; initialized data in <<C>>. The
+          value is the offset into the section of the data. */
+#define BSF_GLOBAL     0x02
+
+        /* The symbol has global scope and is exported. The value is
+          the offset into the section of the data. */
+#define BSF_EXPORT     BSF_GLOBAL  /* no real difference */
+
+        /* A normal C symbol would be one of:
+          <<BSF_LOCAL>>, <<BSF_FORT_COMM>>,  <<BSF_UNDEFINED>> or
+          <<BSF_GLOBAL>> */
+
+        /* The symbol is a debugging record. The value has an arbitary
+          meaning, unless BSF_DEBUGGING_RELOC is also set.  */
+#define BSF_DEBUGGING  0x08
+
+        /* The symbol denotes a function entry point.  Used in ELF,
+          perhaps others someday.  */
+#define BSF_FUNCTION    0x10
+
+        /* Used by the linker. */
+#define BSF_KEEP        0x20
+#define BSF_KEEP_G      0x40
+
+        /* A weak global symbol, overridable without warnings by
+          a regular global symbol of the same name.  */
+#define BSF_WEAK        0x80
+
+        /* This symbol was created to point to a section, e.g. ELF's
+          STT_SECTION symbols.  */
+#define BSF_SECTION_SYM 0x100
+
+        /* The symbol used to be a common symbol, but now it is
+          allocated. */
+#define BSF_OLD_COMMON  0x200
+
+        /* The default value for common data. */
+#define BFD_FORT_COMM_DEFAULT_VALUE 0
+
+        /* In some files the type of a symbol sometimes alters its
+          location in an output file - ie in coff a <<ISFCN>> symbol
+          which is also <<C_EXT>> symbol appears where it was
+          declared and not at the end of a section.  This bit is set
+          by the target BFD part to convey this information. */
+
+#define BSF_NOT_AT_END    0x400
+
+        /* Signal that the symbol is the label of constructor section. */
+#define BSF_CONSTRUCTOR   0x800
+
+        /* Signal that the symbol is a warning symbol.  The name is a
+          warning.  The name of the next symbol is the one to warn about;
+          if a reference is made to a symbol with the same name as the next
+          symbol, a warning is issued by the linker. */
+#define BSF_WARNING       0x1000
+
+        /* Signal that the symbol is indirect.  This symbol is an indirect
+          pointer to the symbol with the same name as the next symbol. */
+#define BSF_INDIRECT      0x2000
+
+        /* BSF_FILE marks symbols that contain a file name.  This is used
+          for ELF STT_FILE symbols.  */
+#define BSF_FILE          0x4000
+
+        /* Symbol is from dynamic linking information.  */
+#define BSF_DYNAMIC       0x8000
+
+        /* The symbol denotes a data object.  Used in ELF, and perhaps
+          others someday.  */
+#define BSF_OBJECT        0x10000
+
+        /* This symbol is a debugging symbol.  The value is the offset
+          into the section of the data.  BSF_DEBUGGING should be set
+          as well.  */
+#define BSF_DEBUGGING_RELOC 0x20000
+
+  flagword flags;
+
+        /* A pointer to the section to which this symbol is
+          relative.  This will always be non NULL, there are special
+          sections for undefined and absolute symbols.  */
+  struct sec *section;
+
+        /* Back end special data.  */
+  union
+    {
+      PTR p;
+      bfd_vma i;
+    } udata;
+
+} asymbol;
+#define bfd_get_symtab_upper_bound(abfd) \
+     BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd))
+boolean 
+bfd_is_local_label PARAMS ((bfd *abfd, asymbol *sym));
+
+boolean 
+bfd_is_local_label_name PARAMS ((bfd *abfd, const char *name));
+
+#define bfd_is_local_label_name(abfd, name) \
+     BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name))
+#define bfd_canonicalize_symtab(abfd, location) \
+     BFD_SEND (abfd, _bfd_canonicalize_symtab,\
+                  (abfd, location))
+boolean 
+bfd_set_symtab  PARAMS ((bfd *abfd, asymbol **location, unsigned int count));
+
+void 
+bfd_print_symbol_vandf PARAMS ((PTR file, asymbol *symbol));
+
+#define bfd_make_empty_symbol(abfd) \
+     BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+#define bfd_make_debug_symbol(abfd,ptr,size) \
+        BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+int 
+bfd_decode_symclass PARAMS ((asymbol *symbol));
+
+void 
+bfd_symbol_info PARAMS ((asymbol *symbol, symbol_info *ret));
+
+boolean 
+bfd_copy_private_symbol_data PARAMS ((bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym));
+
+#define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \
+     BFD_SEND (obfd, _bfd_copy_private_symbol_data, \
+               (ibfd, isymbol, obfd, osymbol))
+struct _bfd 
+{
+     /* The filename the application opened the BFD with.  */
+    CONST char *filename;                
+
+     /* A pointer to the target jump table.             */
+    const struct bfd_target *xvec;
+
+     /* To avoid dragging too many header files into every file that
+       includes `<<bfd.h>>', IOSTREAM has been declared as a "char
+       *", and MTIME as a "long".  Their correct types, to which they
+       are cast when used, are "FILE *" and "time_t".    The iostream
+       is the result of an fopen on the filename.  However, if the
+       BFD_IN_MEMORY flag is set, then iostream is actually a pointer
+       to a bfd_in_memory struct.  */
+    PTR iostream;
+
+     /* Is the file descriptor being cached?  That is, can it be closed as
+       needed, and re-opened when accessed later?  */
+
+    boolean cacheable;
+
+     /* Marks whether there was a default target specified when the
+       BFD was opened. This is used to select which matching algorithm
+       to use to choose the back end. */
+
+    boolean target_defaulted;
+
+     /* The caching routines use these to maintain a
+       least-recently-used list of BFDs */
+
+    struct _bfd *lru_prev, *lru_next;
+
+     /* When a file is closed by the caching routines, BFD retains
+       state information on the file here: */
+
+    file_ptr where;              
+
+     /* and here: (``once'' means at least once) */
+
+    boolean opened_once;
+
+     /* Set if we have a locally maintained mtime value, rather than
+       getting it from the file each time: */
+
+    boolean mtime_set;
+
+     /* File modified time, if mtime_set is true: */
+
+    long mtime;          
+
+     /* Reserved for an unimplemented file locking extension.*/
+
+    int ifd;
+
+     /* The format which belongs to the BFD. (object, core, etc.) */
+
+    bfd_format format;
+
+     /* The direction the BFD was opened with*/
+
+    enum bfd_direction {no_direction = 0,
+                        read_direction = 1,
+                        write_direction = 2,
+                        both_direction = 3} direction;
+
+     /* Format_specific flags*/
+
+    flagword flags;              
+
+     /* Currently my_archive is tested before adding origin to
+       anything. I believe that this can become always an add of
+       origin, with origin set to 0 for non archive files.   */
+
+    file_ptr origin;             
+
+     /* Remember when output has begun, to stop strange things
+       from happening. */
+    boolean output_has_begun;
+
+     /* Pointer to linked list of sections*/
+    struct sec  *sections;
+
+     /* The number of sections */
+    unsigned int section_count;
+
+     /* Stuff only useful for object files: 
+       The start address. */
+    bfd_vma start_address;
+
+     /* Used for input and output*/
+    unsigned int symcount;
+
+     /* Symbol table for output BFD (with symcount entries) */
+    struct symbol_cache_entry  **outsymbols;             
+
+     /* Pointer to structure which contains architecture information*/
+    const struct bfd_arch_info *arch_info;
+
+     /* Stuff only useful for archives:*/
+    PTR arelt_data;              
+    struct _bfd *my_archive;      /* The containing archive BFD.  */
+    struct _bfd *next;            /* The next BFD in the archive.  */
+    struct _bfd *archive_head;    /* The first BFD in the archive.  */
+    boolean has_armap;           
+
+     /* A chain of BFD structures involved in a link.  */
+    struct _bfd *link_next;
+
+     /* A field used by _bfd_generic_link_add_archive_symbols.  This will
+       be used only for archive elements.  */
+    int archive_pass;
+
+     /* Used by the back end to hold private data. */
+
+    union 
+      {
+      struct aout_data_struct *aout_data;
+      struct artdata *aout_ar_data;
+      struct _oasys_data *oasys_obj_data;
+      struct _oasys_ar_data *oasys_ar_data;
+      struct coff_tdata *coff_obj_data;
+      struct pe_tdata *pe_obj_data;
+      struct xcoff_tdata *xcoff_obj_data;
+      struct ecoff_tdata *ecoff_obj_data;
+      struct ieee_data_struct *ieee_data;
+      struct ieee_ar_data_struct *ieee_ar_data;
+      struct srec_data_struct *srec_data;
+      struct ihex_data_struct *ihex_data;
+      struct tekhex_data_struct *tekhex_data;
+      struct elf_obj_tdata *elf_obj_data;
+      struct nlm_obj_tdata *nlm_obj_data;
+      struct bout_data_struct *bout_data;
+      struct sun_core_struct *sun_core_data;
+      struct sco5_core_struct *sco5_core_data;
+      struct trad_core_struct *trad_core_data;
+      struct som_data_struct *som_data;
+      struct hpux_core_struct *hpux_core_data;
+      struct hppabsd_core_struct *hppabsd_core_data;
+      struct sgi_core_struct *sgi_core_data;
+      struct lynx_core_struct *lynx_core_data;
+      struct osf_core_struct *osf_core_data;
+      struct cisco_core_struct *cisco_core_data;
+      struct versados_data_struct *versados_data;
+      struct netbsd_core_struct *netbsd_core_data;
+      PTR any;
+      } tdata;
+  
+     /* Used by the application to hold private data*/
+    PTR usrdata;
+
+   /* Where all the allocated stuff under this BFD goes.  This is a
+     struct objalloc *, but we use PTR to avoid requiring the inclusion of
+     objalloc.h.  */
+    PTR memory;
+};
+
+typedef enum bfd_error
+{
+  bfd_error_no_error = 0,
+  bfd_error_system_call,
+  bfd_error_invalid_target,
+  bfd_error_wrong_format,
+  bfd_error_invalid_operation,
+  bfd_error_no_memory,
+  bfd_error_no_symbols,
+  bfd_error_no_armap,
+  bfd_error_no_more_archived_files,
+  bfd_error_malformed_archive,
+  bfd_error_file_not_recognized,
+  bfd_error_file_ambiguously_recognized,
+  bfd_error_no_contents,
+  bfd_error_nonrepresentable_section,
+  bfd_error_no_debug_section,
+  bfd_error_bad_value,
+  bfd_error_file_truncated,
+  bfd_error_file_too_big,
+  bfd_error_invalid_error_code
+} bfd_error_type;
+
+bfd_error_type 
+bfd_get_error  PARAMS ((void));
+
+void 
+bfd_set_error  PARAMS ((bfd_error_type error_tag));
+
+CONST char *
+bfd_errmsg  PARAMS ((bfd_error_type error_tag));
+
+void 
+bfd_perror  PARAMS ((CONST char *message));
+
+typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...));
+
+bfd_error_handler_type 
+bfd_set_error_handler  PARAMS ((bfd_error_handler_type));
+
+void 
+bfd_set_error_program_name  PARAMS ((const char *));
+
+bfd_error_handler_type 
+bfd_get_error_handler  PARAMS ((void));
+
+long 
+bfd_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect));
+
+long 
+bfd_canonicalize_reloc
+ PARAMS ((bfd *abfd,
+    asection *sec,
+    arelent **loc,
+    asymbol **syms));
+
+void 
+bfd_set_reloc
+ PARAMS ((bfd *abfd, asection *sec, arelent **rel, unsigned int count)
+    
+    );
+
+boolean 
+bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags));
+
+boolean 
+bfd_set_start_address PARAMS ((bfd *abfd, bfd_vma vma));
+
+long 
+bfd_get_mtime PARAMS ((bfd *abfd));
+
+long 
+bfd_get_size PARAMS ((bfd *abfd));
+
+int 
+bfd_get_gp_size PARAMS ((bfd *abfd));
+
+void 
+bfd_set_gp_size PARAMS ((bfd *abfd, int i));
+
+bfd_vma 
+bfd_scan_vma PARAMS ((CONST char *string, CONST char **end, int base));
+
+boolean 
+bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_copy_private_bfd_data(ibfd, obfd) \
+     BFD_SEND (obfd, _bfd_copy_private_bfd_data, \
+               (ibfd, obfd))
+boolean 
+bfd_merge_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_merge_private_bfd_data(ibfd, obfd) \
+     BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
+               (ibfd, obfd))
+boolean 
+bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
+
+#define bfd_set_private_flags(abfd, flags) \
+     BFD_SEND (abfd, _bfd_set_private_flags, \
+               (abfd, flags))
+#define bfd_sizeof_headers(abfd, reloc) \
+     BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+
+#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
+     BFD_SEND (abfd, _bfd_find_nearest_line,  (abfd, sec, syms, off, file, func, line))
+
+        /* Do these three do anything useful at all, for any back end?  */
+#define bfd_debug_info_start(abfd) \
+        BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+
+#define bfd_debug_info_end(abfd) \
+        BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+
+#define bfd_debug_info_accumulate(abfd, section) \
+        BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+
+
+#define bfd_stat_arch_elt(abfd, stat) \
+        BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+
+#define bfd_update_armap_timestamp(abfd) \
+        BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
+
+#define bfd_set_arch_mach(abfd, arch, mach)\
+        BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+
+#define bfd_relax_section(abfd, section, link_info, again) \
+       BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
+
+#define bfd_gc_sections(abfd, link_info) \
+       BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
+
+#define bfd_link_hash_table_create(abfd) \
+       BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
+
+#define bfd_link_add_symbols(abfd, info) \
+       BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
+
+#define bfd_final_link(abfd, info) \
+       BFD_SEND (abfd, _bfd_final_link, (abfd, info))
+
+#define bfd_free_cached_info(abfd) \
+       BFD_SEND (abfd, _bfd_free_cached_info, (abfd))
+
+#define bfd_get_dynamic_symtab_upper_bound(abfd) \
+       BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd))
+
+#define bfd_print_private_bfd_data(abfd, file)\
+       BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file))
+
+#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \
+       BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols))
+
+#define bfd_get_dynamic_reloc_upper_bound(abfd) \
+       BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd))
+
+#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \
+       BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms))
+
+extern bfd_byte *bfd_get_relocated_section_contents
+       PARAMS ((bfd *, struct bfd_link_info *,
+                 struct bfd_link_order *, bfd_byte *,
+                 boolean, asymbol **));
+
+symindex 
+bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym));
+
+boolean 
+bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head));
+
+bfd *
+bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous));
+
+CONST char *
+bfd_core_file_failing_command PARAMS ((bfd *abfd));
+
+int 
+bfd_core_file_failing_signal PARAMS ((bfd *abfd));
+
+boolean 
+core_file_matches_executable_p
+ PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+#define BFD_SEND(bfd, message, arglist) \
+               ((*((bfd)->xvec->message)) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND
+#define BFD_SEND(bfd, message, arglist) \
+  (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+    ((*((bfd)->xvec->message)) arglist) : \
+    (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+#define BFD_SEND_FMT(bfd, message, arglist) \
+            (((bfd)->xvec->message[(int)((bfd)->format)]) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND_FMT
+#define BFD_SEND_FMT(bfd, message, arglist) \
+  (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+   (((bfd)->xvec->message[(int)((bfd)->format)]) arglist) : \
+   (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+enum bfd_flavour {
+  bfd_target_unknown_flavour,
+  bfd_target_aout_flavour,
+  bfd_target_coff_flavour,
+  bfd_target_ecoff_flavour,
+  bfd_target_elf_flavour,
+  bfd_target_ieee_flavour,
+  bfd_target_nlm_flavour,
+  bfd_target_oasys_flavour,
+  bfd_target_tekhex_flavour,
+  bfd_target_srec_flavour,
+  bfd_target_ihex_flavour,
+  bfd_target_som_flavour,
+  bfd_target_os9k_flavour,
+  bfd_target_versados_flavour,
+  bfd_target_msdos_flavour,
+  bfd_target_ovax_flavour,
+  bfd_target_evax_flavour
+};
+
+enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
+
+ /* Forward declaration.  */
+typedef struct bfd_link_info _bfd_link_info;
+
+typedef struct bfd_target
+{
+  char *name;
+  enum bfd_flavour flavour;
+  enum bfd_endian byteorder;
+  enum bfd_endian header_byteorder;
+  flagword object_flags;       
+  flagword section_flags;
+  char symbol_leading_char;
+  char ar_pad_char;            
+  unsigned short ar_max_namelen;
+  bfd_vma      (*bfd_getx64) PARAMS ((const bfd_byte *));
+  bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *));
+  void         (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *));
+  bfd_vma      (*bfd_getx32) PARAMS ((const bfd_byte *));
+  bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *));
+  void         (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *));
+  bfd_vma      (*bfd_getx16) PARAMS ((const bfd_byte *));
+  bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *));
+  void         (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *));
+  bfd_vma      (*bfd_h_getx64) PARAMS ((const bfd_byte *));
+  bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *));
+  void         (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *));
+  bfd_vma      (*bfd_h_getx32) PARAMS ((const bfd_byte *));
+  bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *));
+  void         (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *));
+  bfd_vma      (*bfd_h_getx16) PARAMS ((const bfd_byte *));
+  bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *));
+  void         (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *));
+  const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *));
+  boolean             (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *));
+  boolean             (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *));
+
+   /* Generic entry points.  */
+#define BFD_JUMP_TABLE_GENERIC(NAME)\
+CAT(NAME,_close_and_cleanup),\
+CAT(NAME,_bfd_free_cached_info),\
+CAT(NAME,_new_section_hook),\
+CAT(NAME,_get_section_contents),\
+CAT(NAME,_get_section_contents_in_window)
+
+   /* Called when the BFD is being closed to do any necessary cleanup.  */
+  boolean       (*_close_and_cleanup) PARAMS ((bfd *));
+   /* Ask the BFD to free all cached information.  */
+  boolean (*_bfd_free_cached_info) PARAMS ((bfd *));
+   /* Called when a new section is created.  */
+  boolean       (*_new_section_hook) PARAMS ((bfd *, sec_ptr));
+   /* Read the contents of a section.  */
+  boolean       (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR, 
+                                            file_ptr, bfd_size_type));
+  boolean       (*_bfd_get_section_contents_in_window)
+                          PARAMS ((bfd *, sec_ptr, bfd_window *,
+                                   file_ptr, bfd_size_type));
+
+   /* Entry points to copy private data.  */
+#define BFD_JUMP_TABLE_COPY(NAME)\
+CAT(NAME,_bfd_copy_private_bfd_data),\
+CAT(NAME,_bfd_merge_private_bfd_data),\
+CAT(NAME,_bfd_copy_private_section_data),\
+CAT(NAME,_bfd_copy_private_symbol_data),\
+CAT(NAME,_bfd_set_private_flags),\
+CAT(NAME,_bfd_print_private_bfd_data)\
+   /* Called to copy BFD general private data from one object file
+     to another.  */
+  boolean       (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *));
+   /* Called to merge BFD general private data from one object file
+     to a common output file when linking.  */
+  boolean       (*_bfd_merge_private_bfd_data) PARAMS ((bfd *, bfd *));
+   /* Called to copy BFD private section data from one object file
+     to another.  */
+  boolean       (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr,
+                                                       bfd *, sec_ptr));
+   /* Called to copy BFD private symbol data from one symbol 
+     to another.  */
+  boolean       (*_bfd_copy_private_symbol_data) PARAMS ((bfd *, asymbol *,
+                                                          bfd *, asymbol *));
+   /* Called to set private backend flags */
+  boolean       (*_bfd_set_private_flags) PARAMS ((bfd *, flagword));
+
+   /* Called to print private BFD data */
+  boolean       (*_bfd_print_private_bfd_data) PARAMS ((bfd *, PTR));
+
+   /* Core file entry points.  */
+#define BFD_JUMP_TABLE_CORE(NAME)\
+CAT(NAME,_core_file_failing_command),\
+CAT(NAME,_core_file_failing_signal),\
+CAT(NAME,_core_file_matches_executable_p)
+  char *   (*_core_file_failing_command) PARAMS ((bfd *));
+  int      (*_core_file_failing_signal) PARAMS ((bfd *));
+  boolean  (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *));
+
+   /* Archive entry points.  */
+#define BFD_JUMP_TABLE_ARCHIVE(NAME)\
+CAT(NAME,_slurp_armap),\
+CAT(NAME,_slurp_extended_name_table),\
+CAT(NAME,_construct_extended_name_table),\
+CAT(NAME,_truncate_arname),\
+CAT(NAME,_write_armap),\
+CAT(NAME,_read_ar_hdr),\
+CAT(NAME,_openr_next_archived_file),\
+CAT(NAME,_get_elt_at_index),\
+CAT(NAME,_generic_stat_arch_elt),\
+CAT(NAME,_update_armap_timestamp)
+  boolean  (*_bfd_slurp_armap) PARAMS ((bfd *));
+  boolean  (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
+  boolean  (*_bfd_construct_extended_name_table)
+             PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+  void     (*_bfd_truncate_arname) PARAMS ((bfd *, CONST char *, char *));
+  boolean  (*write_armap) PARAMS ((bfd *arch, 
+                              unsigned int elength,
+                              struct orl *map,
+                              unsigned int orl_count, 
+                              int stridx));
+  PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
+  bfd *    (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev));
+#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
+  bfd *    (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
+  int      (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
+  boolean  (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
+
+   /* Entry points used for symbols.  */
+#define BFD_JUMP_TABLE_SYMBOLS(NAME)\
+CAT(NAME,_get_symtab_upper_bound),\
+CAT(NAME,_get_symtab),\
+CAT(NAME,_make_empty_symbol),\
+CAT(NAME,_print_symbol),\
+CAT(NAME,_get_symbol_info),\
+CAT(NAME,_bfd_is_local_label_name),\
+CAT(NAME,_get_lineno),\
+CAT(NAME,_find_nearest_line),\
+CAT(NAME,_bfd_make_debug_symbol),\
+CAT(NAME,_read_minisymbols),\
+CAT(NAME,_minisymbol_to_symbol)
+  long  (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *));
+  long  (*_bfd_canonicalize_symtab) PARAMS ((bfd *,
+                                             struct symbol_cache_entry **));
+  struct symbol_cache_entry  *
+                (*_bfd_make_empty_symbol) PARAMS ((bfd *));
+  void          (*_bfd_print_symbol) PARAMS ((bfd *, PTR,
+                                      struct symbol_cache_entry *,
+                                      bfd_print_symbol_type));
+#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
+  void          (*_bfd_get_symbol_info) PARAMS ((bfd *,
+                                      struct symbol_cache_entry *,
+                                      symbol_info *));
+#define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e))
+  boolean       (*_bfd_is_local_label_name) PARAMS ((bfd *, const char *));
+
+  alent *    (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *));
+  boolean    (*_bfd_find_nearest_line) PARAMS ((bfd *abfd,
+                    struct sec *section, struct symbol_cache_entry **symbols,
+                    bfd_vma offset, CONST char **file, CONST char **func,
+                    unsigned int *line));
+  /* Back-door to allow format-aware applications to create debug symbols
+    while using BFD for everything else.  Currently used by the assembler
+    when creating COFF files.  */
+  asymbol *  (*_bfd_make_debug_symbol) PARAMS ((
+       bfd *abfd,
+       void *ptr,
+       unsigned long size));
+#define bfd_read_minisymbols(b, d, m, s) \
+  BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+  long  (*_read_minisymbols) PARAMS ((bfd *, boolean, PTR *,
+                                      unsigned int *));
+#define bfd_minisymbol_to_symbol(b, d, m, f) \
+  BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f))
+  asymbol *(*_minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR,
+                                             asymbol *));
+
+   /* Routines for relocs.  */
+#define BFD_JUMP_TABLE_RELOCS(NAME)\
+CAT(NAME,_get_reloc_upper_bound),\
+CAT(NAME,_canonicalize_reloc),\
+CAT(NAME,_bfd_reloc_type_lookup)
+  long  (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr));
+  long  (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **,
+                                            struct symbol_cache_entry **));
+   /* See documentation on reloc types.  */
+  reloc_howto_type *
+       (*reloc_type_lookup) PARAMS ((bfd *abfd,
+                                     bfd_reloc_code_real_type code));
+
+   /* Routines used when writing an object file.  */
+#define BFD_JUMP_TABLE_WRITE(NAME)\
+CAT(NAME,_set_arch_mach),\
+CAT(NAME,_set_section_contents)
+  boolean    (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture,
+                    unsigned long));
+  boolean       (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+                                            file_ptr, bfd_size_type));
+
+   /* Routines used by the linker.  */
+#define BFD_JUMP_TABLE_LINK(NAME)\
+CAT(NAME,_sizeof_headers),\
+CAT(NAME,_bfd_get_relocated_section_contents),\
+CAT(NAME,_bfd_relax_section),\
+CAT(NAME,_bfd_link_hash_table_create),\
+CAT(NAME,_bfd_link_add_symbols),\
+CAT(NAME,_bfd_final_link),\
+CAT(NAME,_bfd_link_split_section),\
+CAT(NAME,_bfd_gc_sections)
+  int        (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
+  bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *,
+                    struct bfd_link_info *, struct bfd_link_order *,
+                    bfd_byte *data, boolean relocateable,
+                    struct symbol_cache_entry **));
+
+  boolean    (*_bfd_relax_section) PARAMS ((bfd *, struct sec *,
+                    struct bfd_link_info *, boolean *again));
+
+   /* Create a hash table for the linker.  Different backends store
+     different information in this table.  */
+  struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *));
+
+   /* Add symbols from this object file into the hash table.  */
+  boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *));
+
+   /* Do a link based on the link_order structures attached to each
+     section of the BFD.  */
+  boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *));
+
+   /* Should this section be split up into smaller pieces during linking.  */
+  boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *));
+
+   /* Remove sections that are not referenced from the output.  */
+  boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+   /* Routines to handle dynamic symbols and relocs.  */
+#define BFD_JUMP_TABLE_DYNAMIC(NAME)\
+CAT(NAME,_get_dynamic_symtab_upper_bound),\
+CAT(NAME,_canonicalize_dynamic_symtab),\
+CAT(NAME,_get_dynamic_reloc_upper_bound),\
+CAT(NAME,_canonicalize_dynamic_reloc)
+   /* Get the amount of memory required to hold the dynamic symbols. */
+  long  (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *));
+   /* Read in the dynamic symbols.  */
+  long  (*_bfd_canonicalize_dynamic_symtab)
+    PARAMS ((bfd *, struct symbol_cache_entry **));
+   /* Get the amount of memory required to hold the dynamic relocs.  */
+  long  (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *));
+   /* Read in the dynamic relocs.  */
+  long  (*_bfd_canonicalize_dynamic_reloc)
+    PARAMS ((bfd *, arelent **, struct symbol_cache_entry **));
+
+  /* Opposite endian version of this target.  */  
+ const struct bfd_target * alternative_target;
+ 
+ PTR backend_data;
+ 
+} bfd_target;
+boolean 
+bfd_set_default_target  PARAMS ((const char *name));
+
+const bfd_target *
+bfd_find_target PARAMS ((CONST char *target_name, bfd *abfd));
+
+const char **
+bfd_target_list PARAMS ((void));
+
+const bfd_target * 
+bfd_search_for_target  PARAMS ((int (* search_func)(const bfd_target *, void *), void *));
+
+boolean 
+bfd_check_format PARAMS ((bfd *abfd, bfd_format format));
+
+boolean 
+bfd_check_format_matches PARAMS ((bfd *abfd, bfd_format format, char ***matching));
+
+boolean 
+bfd_set_format PARAMS ((bfd *abfd, bfd_format format));
+
+CONST char *
+bfd_format_string PARAMS ((bfd_format format));
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: 2.4.x-xfs/arch/i386/kdb/i386-dis.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kdb/i386-dis.c	Thu Jan  1 10:00:00 1970
+++ 2.4.x-xfs/arch/i386/kdb/i386-dis.c	Mon Aug  9 13:54:51 2004
@@ -0,0 +1,3781 @@
+/* Print i386 instructions for GDB, the GNU debugger.
+   Copyright (C) 1988, 89, 91, 93, 94, 95, 96, 97, 98, 1999
+   Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/*
+ * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ *  modified by John Hassey (hassey@dg-rtp.dg.com)
+ */
+
+/* Extracted from cygnus CVS and modified for kdb use.
+ * Keith Owens <kaos@sgi.com> 30 Oct 2000
+ */
+
+/*
+ * The main tables describing the instructions is essentially a copy
+ * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
+ * Programmers Manual.  Usually, there is a capital letter, followed
+ * by a small letter.  The capital letter tell the addressing mode,
+ * and the small letter tells about the operand size.  Refer to
+ * the Intel manual for details.
+ */
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/dis-asm.h>
+#include <linux/kdb.h>
+#else
+#include "dis-asm.h"
+#include "sysdep.h"
+#include "opintl.h"
+#endif
+
+#define MAXLEN 20
+
+#ifndef __KERNEL__
+#include <setjmp.h>
+#endif
+
+#ifndef UNIXWARE_COMPAT
+/* Set non-zero for broken, compatible instructions.  Set to zero for
+   non-broken opcodes.  */
+#define UNIXWARE_COMPAT 1
+#endif
+
+static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
+
+struct dis_private
+{
+  /* Points to first byte not fetched.  */
+  bfd_byte *max_fetched;
+  bfd_byte the_buffer[MAXLEN];
+  bfd_vma insn_start;
+#ifndef __KERNEL__
+  jmp_buf bailout;
+#endif
+};
+
+/* The opcode for the fwait instruction, which we treat as a prefix
+   when we can.  */
+#define FWAIT_OPCODE (0x9b)
+
+/* Flags for the prefixes for the current instruction.  See below.  */
+static int prefixes;
+
+/* Flags for prefixes which we somehow handled when printing the
+   current instruction.  */
+static int used_prefixes;
+
+/* Flags stored in PREFIXES.  */
+#define PREFIX_REPZ 1
+#define PREFIX_REPNZ 2
+#define PREFIX_LOCK 4
+#define PREFIX_CS 8
+#define PREFIX_SS 0x10
+#define PREFIX_DS 0x20
+#define PREFIX_ES 0x40
+#define PREFIX_FS 0x80
+#define PREFIX_GS 0x100
+#define PREFIX_DATA 0x200
+#define PREFIX_ADDR 0x400
+#define PREFIX_FWAIT 0x800
+
+/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
+   to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
+   on error.  */
+#define FETCH_DATA(info, addr) \
+  ((addr) <= ((struct dis_private *)(info->private_data))->max_fetched \
+   ? 1 : fetch_data ((info), (addr)))
+
+static int
+fetch_data (info, addr)
+     struct disassemble_info *info;
+     bfd_byte *addr;
+{
+  int status;
+  struct dis_private *priv = (struct dis_private *)info->private_data;
+  bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
+
+  status = (*info->read_memory_func) (start,
+				      priv->max_fetched,
+				      addr - priv->max_fetched,
+				      info);
+  if (status != 0)
+    {
+      /* If we did manage to read at least one byte, then
+         print_insn_i386 will do something sensible.  Otherwise, print
+         an error.  We do that here because this is where we know
+         STATUS.  */
+      if (priv->max_fetched == priv->the_buffer)
+	(*info->memory_error_func) (status, start, info);
+#ifndef __KERNEL__
+      longjmp (priv->bailout, 1);
+#else
+	/* XXX - what to do? */
+	kdb_printf("Hmm. longjmp.\n");
+#endif
+    }
+  else
+    priv->max_fetched = addr;
+  return 1;
+}
+
+#define XX NULL, 0
+
+#define Eb OP_E, b_mode
+#define indirEb OP_indirE, b_mode
+#define Gb OP_G, b_mode
+#define Ev OP_E, v_mode
+#define Ed OP_E, d_mode
+#define indirEv OP_indirE, v_mode
+#define Ew OP_E, w_mode
+#define Ma OP_E, v_mode
+#define M OP_E, 0		/* lea */
+#define Mp OP_E, 0		/* 32 or 48 bit memory operand for LDS, LES etc */
+#define Gv OP_G, v_mode
+#define Gw OP_G, w_mode
+#define Rd OP_Rd, d_mode
+#define Ib OP_I, b_mode
+#define sIb OP_sI, b_mode	/* sign extened byte */
+#define Iv OP_I, v_mode
+#define Iw OP_I, w_mode
+#define Jb OP_J, b_mode
+#define Jv OP_J, v_mode
+#define Cd OP_C, d_mode
+#define Dd OP_D, d_mode
+#define Td OP_T, d_mode
+
+#define eAX OP_REG, eAX_reg
+#define eBX OP_REG, eBX_reg
+#define eCX OP_REG, eCX_reg
+#define eDX OP_REG, eDX_reg
+#define eSP OP_REG, eSP_reg
+#define eBP OP_REG, eBP_reg
+#define eSI OP_REG, eSI_reg
+#define eDI OP_REG, eDI_reg
+#define AL OP_REG, al_reg
+#define CL OP_REG, cl_reg
+#define DL OP_REG, dl_reg
+#define BL OP_REG, bl_reg
+#define AH OP_REG, ah_reg
+#define CH OP_REG, ch_reg
+#define DH OP_REG, dh_reg
+#define BH OP_REG, bh_reg
+#define AX OP_REG, ax_reg
+#define DX OP_REG, dx_reg
+#define indirDX OP_REG, indir_dx_reg
+
+#define Sw OP_SEG, w_mode
+#define Ap OP_DIR, 0
+#define Ob OP_OFF, b_mode
+#define Ov OP_OFF, v_mode
+#define Xb OP_DSreg, eSI_reg
+#define Xv OP_DSreg, eSI_reg
+#define Yb OP_ESreg, eDI_reg
+#define Yv OP_ESreg, eDI_reg
+#define DSBX OP_DSreg, eBX_reg
+
+#define es OP_REG, es_reg
+#define ss OP_REG, ss_reg
+#define cs OP_REG, cs_reg
+#define ds OP_REG, ds_reg
+#define fs OP_REG, fs_reg
+#define gs OP_REG, gs_reg
+
+#define MX OP_MMX, 0
+#define XM OP_XMM, 0
+#define EM OP_EM, v_mode
+#define EX OP_EX, v_mode
+#define MS OP_MS, v_mode
+#define None OP_E, 0
+#define OPSUF OP_3DNowSuffix, 0
+#define OPSIMD OP_SIMD_Suffix, 0
+
+/* bits in sizeflag */
+#if 0 /* leave undefined until someone adds the extra flag to objdump */
+#define SUFFIX_ALWAYS 4
+#endif
+#define AFLAG 2
+#define DFLAG 1
+
+typedef void (*op_rtn) PARAMS ((int bytemode, int sizeflag));
+
+static void OP_E PARAMS ((int, int));
+static void OP_G PARAMS ((int, int));
+static void OP_I PARAMS ((int, int));
+static void OP_indirE PARAMS ((int, int));
+static void OP_sI PARAMS ((int, int));
+static void OP_REG PARAMS ((int, int));
+static void OP_J PARAMS ((int, int));
+static void OP_DIR PARAMS ((int, int));
+static void OP_OFF PARAMS ((int, int));
+static void OP_ESreg PARAMS ((int, int));
+static void OP_DSreg PARAMS ((int, int));
+static void OP_SEG PARAMS ((int, int));
+static void OP_C PARAMS ((int, int));
+static void OP_D PARAMS ((int, int));
+static void OP_T PARAMS ((int, int));
+static void OP_Rd PARAMS ((int, int));
+static void OP_ST PARAMS ((int, int));
+static void OP_STi  PARAMS ((int, int));
+static void OP_MMX PARAMS ((int, int));
+static void OP_XMM PARAMS ((int, int));
+static void OP_EM PARAMS ((int, int));
+static void OP_EX PARAMS ((int, int));
+static void OP_MS PARAMS ((int, int));
+static void OP_3DNowSuffix PARAMS ((int, int));
+static void OP_SIMD_Suffix PARAMS ((int, int));
+static void SIMD_Fixup PARAMS ((int, int));
+
+static void append_seg PARAMS ((void));
+static void set_op PARAMS ((unsigned int op));
+static void putop PARAMS ((const char *template, int sizeflag));
+static void dofloat PARAMS ((int sizeflag));
+static int get16 PARAMS ((void));
+static int get32 PARAMS ((void));
+static void ckprefix PARAMS ((void));
+static const char *prefix_name PARAMS ((int, int));
+static void ptr_reg PARAMS ((int, int));
+static void BadOp PARAMS ((void));
+
+#define b_mode 1
+#define v_mode 2
+#define w_mode 3
+#define d_mode 4
+#define x_mode 5
+
+#define es_reg 100
+#define cs_reg 101
+#define ss_reg 102
+#define ds_reg 103
+#define fs_reg 104
+#define gs_reg 105
+
+#define eAX_reg 108
+#define eCX_reg 109
+#define eDX_reg 110
+#define eBX_reg 111
+#define eSP_reg 112
+#define eBP_reg 113
+#define eSI_reg 114
+#define eDI_reg 115
+
+#define al_reg 116
+#define cl_reg 117
+#define dl_reg 118
+#define bl_reg 119
+#define ah_reg 120
+#define ch_reg 121
+#define dh_reg 122
+#define bh_reg 123
+
+#define ax_reg 124
+#define cx_reg 125
+#define dx_reg 126
+#define bx_reg 127
+#define sp_reg 128
+#define bp_reg 129
+#define si_reg 130
+#define di_reg 131
+
+#define indir_dx_reg 150
+
+#define USE_GROUPS 1
+#define USE_PREFIX_USER_TABLE 2
+
+#define GRP1b NULL, NULL, 0, NULL, USE_GROUPS, NULL, 0
+#define GRP1S NULL, NULL, 1, NULL, USE_GROUPS, NULL, 0
+#define GRP1Ss NULL, NULL, 2, NULL, USE_GROUPS, NULL, 0
+#define GRP2b NULL, NULL, 3, NULL, USE_GROUPS, NULL, 0
+#define GRP2S NULL, NULL, 4, NULL, USE_GROUPS, NULL, 0
+#define GRP2b_one NULL, NULL, 5, NULL, USE_GROUPS, NULL, 0
+#define GRP2S_one NULL, NULL, 6, NULL, USE_GROUPS, NULL, 0
+#define GRP2b_cl NULL, NULL, 7, NULL, USE_GROUPS, NULL, 0
+#define GRP2S_cl NULL, NULL, 8, NULL, USE_GROUPS, NULL, 0
+#define GRP3b NULL, NULL, 9, NULL, USE_GROUPS, NULL, 0
+#define GRP3S NULL, NULL, 10, NULL, USE_GROUPS, NULL, 0
+#define GRP4  NULL, NULL, 11, NULL, USE_GROUPS, NULL, 0
+#define GRP5  NULL, NULL, 12, NULL, USE_GROUPS, NULL, 0
+#define GRP6  NULL, NULL, 13, NULL, USE_GROUPS, NULL, 0
+#define GRP7 NULL, NULL, 14, NULL, USE_GROUPS, NULL, 0
+#define GRP8 NULL, NULL, 15, NULL, USE_GROUPS, NULL, 0
+#define GRP9 NULL, NULL, 16, NULL, USE_GROUPS, NULL, 0
+#define GRP10 NULL, NULL, 17, NULL, USE_GROUPS, NULL, 0
+#define GRP11 NULL, NULL, 18, NULL, USE_GROUPS, NULL, 0
+#define GRP12 NULL, NULL, 19, NULL, USE_GROUPS, NULL, 0
+#define GRP13 NULL, NULL, 20, NULL, USE_GROUPS, NULL, 0
+#define GRP14 NULL, NULL, 21, NULL, USE_GROUPS, NULL, 0
+#define GRPAMD NULL, NULL, 22, NULL, USE_GROUPS, NULL, 0
+
+#define PREGRP0 NULL, NULL, 0, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP1 NULL, NULL, 1, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP2 NULL, NULL, 2, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP3 NULL, NULL, 3, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP4 NULL, NULL, 4, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP5 NULL, NULL, 5, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP6 NULL, NULL, 6, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP7 NULL, NULL, 7, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP8 NULL, NULL, 8, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP9 NULL, NULL, 9, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP10 NULL, NULL, 10, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP11 NULL, NULL, 11, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP12 NULL, NULL, 12, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP13 NULL, NULL, 13, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+#define PREGRP14 NULL, NULL, 14, NULL, USE_PREFIX_USER_TABLE, NULL, 0
+
+#define FLOATCODE 50
+#define FLOAT NULL, NULL, FLOATCODE, NULL, 0, NULL, 0
+
+struct dis386 {
+  const char *name;
+  op_rtn op1;
+  int bytemode1;
+  op_rtn op2;
+  int bytemode2;
+  op_rtn op3;
+  int bytemode3;
+};
+
+/* Upper case letters in the instruction names here are macros.
+   'A' => print 'b' if no register operands or suffix_always is true
+   'B' => print 'b' if suffix_always is true
+   'E' => print 'e' if 32-bit form of jcxz
+   'L' => print 'l' if suffix_always is true
+   'N' => print 'n' if instruction has no wait "prefix"
+   'P' => print 'w' or 'l' if instruction has an operand size prefix,
+                              or suffix_always is true
+   'Q' => print 'w' or 'l' if no register operands or suffix_always is true
+   'R' => print 'w' or 'l' ("wd" or "dq" in intel mode)
+   'S' => print 'w' or 'l' if suffix_always is true
+   'W' => print 'b' or 'w' ("w" or "de" in intel mode)
+*/
+
+static const struct dis386 dis386_att[] = {
+  /* 00 */
+  { "addB",	Eb, Gb, XX },
+  { "addS",	Ev, Gv, XX },
+  { "addB",	Gb, Eb, XX },
+  { "addS",	Gv, Ev, XX },
+  { "addB",	AL, Ib, XX },
+  { "addS",	eAX, Iv, XX },
+  { "pushP",	es, XX, XX },
+  { "popP",	es, XX, XX },
+  /* 08 */
+  { "orB",	Eb, Gb, XX },
+  { "orS",	Ev, Gv, XX },
+  { "orB",	Gb, Eb, XX },
+  { "orS",	Gv, Ev, XX },
+  { "orB",	AL, Ib, XX },
+  { "orS",	eAX, Iv, XX },
+  { "pushP",	cs, XX, XX },
+  { "(bad)",	XX, XX, XX },	/* 0x0f extended opcode escape */
+  /* 10 */
+  { "adcB",	Eb, Gb, XX },
+  { "adcS",	Ev, Gv, XX },
+  { "adcB",	Gb, Eb, XX },
+  { "adcS",	Gv, Ev, XX },
+  { "adcB",	AL, Ib, XX },
+  { "adcS",	eAX, Iv, XX },
+  { "pushP",	ss, XX, XX },
+  { "popP",	ss, XX, XX },
+  /* 18 */
+  { "sbbB",	Eb, Gb, XX },
+  { "sbbS",	Ev, Gv, XX },
+  { "sbbB",	Gb, Eb, XX },
+  { "sbbS",	Gv, Ev, XX },
+  { "sbbB",	AL, Ib, XX },
+  { "sbbS",	eAX, Iv, XX },
+  { "pushP",	ds, XX, XX },
+  { "popP",	ds, XX, XX },
+  /* 20 */
+  { "andB",	Eb, Gb, XX },
+  { "andS",	Ev, Gv, XX },
+  { "andB",	Gb, Eb, XX },
+  { "andS",	Gv, Ev, XX },
+  { "andB",	AL, Ib, XX },
+  { "andS",	eAX, Iv, XX },
+  { "(bad)",	XX, XX, XX },			/* SEG ES prefix */
+  { "daa",	XX, XX, XX },
+  /* 28 */
+  { "subB",	Eb, Gb, XX },
+  { "subS",	Ev, Gv, XX },
+  { "subB",	Gb, Eb, XX },
+  { "subS",	Gv, Ev, XX },
+  { "subB",	AL, Ib, XX },
+  { "subS",	eAX, Iv, XX },
+  { "(bad)",	XX, XX, XX },			/* SEG CS prefix */
+  { "das",	XX, XX, XX },
+  /* 30 */
+  { "xorB",	Eb, Gb, XX },
+  { "xorS",	Ev, Gv, XX },
+  { "xorB",	Gb, Eb, XX },
+  { "xorS",	Gv, Ev, XX },
+  { "xorB",	AL, Ib, XX },
+  { "xorS",	eAX, Iv, XX },
+  { "(bad)",	XX, XX, XX },			/* SEG SS prefix */
+  { "aaa",	XX, XX, XX },
+  /* 38 */
+  { "cmpB",	Eb, Gb, XX },
+  { "cmpS",	Ev, Gv, XX },
+  { "cmpB",	Gb, Eb, XX },
+  { "cmpS",	Gv, Ev, XX },
+  { "cmpB",	AL, Ib, XX },
+  { "cmpS",	eAX, Iv, XX },
+  { "(bad)",	XX, XX, XX },			/* SEG DS prefix */
+  { "aas",	XX, XX, XX },
+  /* 40 */
+  { "incS",	eAX, XX, XX },
+  { "incS",	eCX, XX, XX },
+  { "incS",	eDX, XX, XX },
+  { "incS",	eBX, XX, XX },
+  { "incS",	eSP, XX, XX },
+  { "incS",	eBP, XX, XX },
+  { "incS",	eSI, XX, XX },
+  { "incS",	eDI, XX, XX },
+  /* 48 */
+  { "decS",	eAX, XX, XX },
+  { "decS",	eCX, XX, XX },
+  { "decS",	eDX, XX, XX },
+  { "decS",	eBX, XX, XX },
+  { "decS",	eSP, XX, XX },
+  { "decS",	eBP, XX, XX },
+  { "decS",	eSI, XX, XX },
+  { "decS",	eDI, XX, XX },
+  /* 50 */
+  { "pushS",	eAX, XX, XX },
+  { "pushS",	eCX, XX, XX },
+  { "pushS",	eDX, XX, XX },
+  { "pushS",	eBX, XX, XX },
+  { "pushS",	eSP, XX, XX },
+  { "pushS",	eBP, XX, XX },
+  { "pushS",	eSI, XX, XX },
+  { "pushS",	eDI, XX, XX },
+  /* 58 */
+  { "popS",	eAX, XX, XX },
+  { "popS",	eCX, XX, XX },
+  { "popS",	eDX, XX, XX },
+  { "popS",	eBX, XX, XX },
+  { "popS",	eSP, XX, XX },
+  { "popS",	eBP, XX, XX },
+  { "popS",	eSI, XX, XX },
+  { "popS",	eDI, XX, XX },
+  /* 60 */
+  { "pushaP",	XX, XX, XX },
+  { "popaP",	XX, XX, XX },
+  { "boundS",	Gv, Ma, XX },
+  { "arpl",	Ew, Gw, XX },
+  { "(bad)",	XX, XX, XX },			/* seg fs */
+  { "(bad)",	XX, XX, XX },			/* seg gs */
+  { "(bad)",	XX, XX, XX },			/* op size prefix */
+  { "(bad)",	XX, XX, XX },			/* adr size prefix */
+  /* 68 */
+  { "pushP",	Iv, XX, XX },		/* 386 book wrong */
+  { "imulS",	Gv, Ev, Iv },
+  { "pushP",	sIb, XX, XX },	/* push of byte really pushes 2 or 4 bytes */
+  { "imulS",	Gv, Ev, sIb },
+  { "insb",	Yb, indirDX, XX },
+  { "insR",	Yv, indirDX, XX },
+  { "outsb",	indirDX, Xb, XX },
+  { "outsR",	indirDX, Xv, XX },
+  /* 70 */
+  { "jo",	Jb, XX, XX },
+  { "jno",	Jb, XX, XX },
+  { "jb",	Jb, XX, XX },
+  { "jae",	Jb, XX, XX },
+  { "je",	Jb, XX, XX },
+  { "jne",	Jb, XX, XX },
+  { "jbe",	Jb, XX, XX },
+  { "ja",	Jb, XX, XX },
+  /* 78 */
+  { "js",	Jb, XX, XX },
+  { "jns",	Jb, XX, XX },
+  { "jp",	Jb, XX, XX },
+  { "jnp",	Jb, XX, XX },
+  { "jl",	Jb, XX, XX },
+  { "jge",	Jb, XX, XX },
+  { "jle",	Jb, XX, XX },
+  { "jg",	Jb, XX, XX },
+  /* 80 */
+  { GRP1b },
+  { GRP1S },
+  { "(bad)",	XX, XX, XX },
+  { GRP1Ss },
+  { "testB",	Eb, Gb, XX },
+  { "testS",	Ev, Gv, XX },
+  { "xchgB",	Eb, Gb, XX },
+  { "xchgS",	Ev, Gv, XX },
+  /* 88 */
+  { "movB",	Eb, Gb, XX },
+  { "movS",	Ev, Gv, XX },
+  { "movB",	Gb, Eb, XX },
+  { "movS",	Gv, Ev, XX },
+  { "movQ",	Ev, Sw, XX },
+  { "leaS",	Gv, M, XX },
+  { "movQ",	Sw, Ev, XX },
+  { "popQ",	Ev, XX, XX },
+  /* 90 */
+  { "nop",	XX, XX, XX },
+  { "xchgS",	eCX, eAX, XX },
+  { "xchgS",	eDX, eAX, XX },
+  { "xchgS",	eBX, eAX, XX },
+  { "xchgS",	eSP, eAX, XX },
+  { "xchgS",	eBP, eAX, XX },
+  { "xchgS",	eSI, eAX, XX },
+  { "xchgS",	eDI, eAX, XX },
+  /* 98 */
+  { "cWtR",	XX, XX, XX },
+  { "cRtd",	XX, XX, XX },
+  { "lcallP",	Ap, XX, XX },
+  { "(bad)",	XX, XX, XX },		/* fwait */
+  { "pushfP",	XX, XX, XX },
+  { "popfP",	XX, XX, XX },
+  { "sahf",	XX, XX, XX },
+  { "lahf",	XX, XX, XX },
+  /* a0 */
+  { "movB",	AL, Ob, XX },
+  { "movS",	eAX, Ov, XX },
+  { "movB",	Ob, AL, XX },
+  { "movS",	Ov, eAX, XX },
+  { "movsb",	Yb, Xb, XX },
+  { "movsR",	Yv, Xv, XX },
+  { "cmpsb",	Xb, Yb, XX },
+  { "cmpsR",	Xv, Yv, XX },
+  /* a8 */
+  { "testB",	AL, Ib, XX },
+  { "testS",	eAX, Iv, XX },
+  { "stosB",	Yb, AL, XX },
+  { "stosS",	Yv, eAX, XX },
+  { "lodsB",	AL, Xb, XX },
+  { "lodsS",	eAX, Xv, XX },
+  { "scasB",	AL, Yb, XX },
+  { "scasS",	eAX, Yv, XX },
+  /* b0 */
+  { "movB",	AL, Ib, XX },
+  { "movB",	CL, Ib, XX },
+  { "movB",	DL, Ib, XX },
+  { "movB",	BL, Ib, XX },
+  { "movB",	AH, Ib, XX },
+  { "movB",	CH, Ib, XX },
+  { "movB",	DH, Ib, XX },
+  { "movB",	BH, Ib, XX },
+  /* b8 */
+  { "movS",	eAX, Iv, XX },
+  { "movS",	eCX, Iv, XX },
+  { "movS",	eDX, Iv, XX },
+  { "movS",	eBX, Iv, XX },
+  { "movS",	eSP, Iv, XX },
+  { "movS",	eBP, Iv, XX },
+  { "movS",	eSI, Iv, XX },
+  { "movS",	eDI, Iv, XX },
+  /* c0 */
+  { GRP2b },
+  { GRP2S },
+  { "retP",	Iw, XX, XX },
+  { "retP",	XX, XX, XX },
+  { "lesS",	Gv, Mp, XX },
+  { "ldsS",	Gv, Mp, XX },
+  { "movA",	Eb, Ib, XX },
+  { "movQ",	Ev, Iv, XX },
+  /* c8 */
+  { "enterP",	Iw, Ib, XX },
+  { "leaveP",	XX, XX, XX },
+  { "lretP",	Iw, XX, XX },
+  { "lretP",	XX, XX, XX },
+  { "int3",	XX, XX, XX },
+  { "int",	Ib, XX, XX },
+  { "into",	XX, XX, XX},
+  { "iretP",	XX, XX, XX },
+  /* d0 */
+  { GRP2b_one },
+  { GRP2S_one },
+  { GRP2b_cl },
+  { GRP2S_cl },
+  { "aam",	sIb, XX, XX },
+  { "aad",	sIb, XX, XX },
+  { "(bad)",	XX, XX, XX },
+  { "xlat",	DSBX, XX, XX },
+  /* d8 */
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  /* e0 */
+  { "loopne",	Jb, XX, XX },
+  { "loope",	Jb, XX, XX },
+  { "loop",	Jb, XX, XX },
+  { "jEcxz",	Jb, XX, XX },
+  { "inB",	AL, Ib, XX },
+  { "inS",	eAX, Ib, XX },
+  { "outB",	Ib, AL, XX },
+  { "outS",	Ib, eAX, XX },
+  /* e8 */
+  { "callP",	Jv, XX, XX },
+  { "jmpP",	Jv, XX, XX },
+  { "ljmpP",	Ap, XX, XX },
+  { "jmp",	Jb, XX, XX },
+  { "inB",	AL, indirDX, XX },
+  { "inS",	eAX, indirDX, XX },
+  { "outB",	indirDX, AL, XX },
+  { "outS",	indirDX, eAX, XX },
+  /* f0 */
+  { "(bad)",	XX, XX, XX },			/* lock prefix */
+  { "(bad)",	XX, XX, XX },
+  { "(bad)",	XX, XX, XX },			/* repne */
+  { "(bad)",	XX, XX, XX },			/* repz */
+  { "hlt",	XX, XX, XX },
+  { "cmc",	XX, XX, XX },
+  { GRP3b },
+  { GRP3S },
+  /* f8 */
+  { "clc",	XX, XX, XX },
+  { "stc",	XX, XX, XX },
+  { "cli",	XX, XX, XX },
+  { "sti",	XX, XX, XX },
+  { "cld",	XX, XX, XX },
+  { "std",	XX, XX, XX },
+  { GRP4 },
+  { GRP5 },
+};
+
+static const struct dis386 dis386_intel[] = {
+  /* 00 */
+  { "add",	Eb, Gb, XX },
+  { "add",	Ev, Gv, XX },
+  { "add",	Gb, Eb, XX },
+  { "add",	Gv, Ev, XX },
+  { "add",	AL, Ib, XX },
+  { "add",	eAX, Iv, XX },
+  { "push",	es, XX, XX },
+  { "pop",	es, XX, XX },
+  /* 08 */
+  { "or",	Eb, Gb, XX },
+  { "or",	Ev, Gv, XX },
+  { "or",	Gb, Eb, XX },
+  { "or",	Gv, Ev, XX },
+  { "or",	AL, Ib, XX },
+  { "or",	eAX, Iv, XX },
+  { "push",	cs, XX, XX },
+  { "(bad)",	XX, XX, XX },	/* 0x0f extended opcode escape */
+  /* 10 */
+  { "adc",	Eb, Gb, XX },
+  { "adc",	Ev, Gv, XX },
+  { "adc",	Gb, Eb, XX },
+  { "adc",	Gv, Ev, XX },
+  { "adc",	AL, Ib, XX },
+  { "adc",	eAX, Iv, XX },
+  { "push",	ss, XX, XX },
+  { "pop",	ss, XX, XX },
+  /* 18 */
+  { "sbb",	Eb, Gb, XX },
+  { "sbb",	Ev, Gv, XX },
+  { "sbb",	Gb, Eb, XX },
+  { "sbb",	Gv, Ev, XX },
+  { "sbb",	AL, Ib, XX },
+  { "sbb",	eAX, Iv, XX },
+  { "push",	ds, XX, XX },
+  { "pop",	ds, XX, XX },
+  /* 20 */
+  { "and",	Eb, Gb, XX },
+  { "and",	Ev, Gv, XX },
+  { "and",	Gb, Eb, XX },
+  { "and",	Gv, Ev, XX },
+  { "and",	AL, Ib, XX },
+  { "and",	eAX, Iv, XX },
+  { "(bad)",	XX, XX, XX },			/* SEG ES prefix */
+  { "daa",	XX, XX, XX },
+  /* 28 */
+  { "sub",	Eb, Gb, XX },
+  { "sub",	Ev, Gv, XX },
+  { "sub",	Gb, Eb, XX },
+  { "sub",	Gv, Ev, XX },
+  { "sub",	AL, Ib, XX },
+  { "sub",	eAX, Iv, XX },
+  { "(bad)",	XX, XX, XX },			/* SEG CS prefix */
+  { "das",	XX, XX, XX },
+  /* 30 */
+  { "xor",	Eb, Gb, XX },
+  { "xor",	Ev, Gv, XX },
+  { "xor",	Gb, Eb, XX },
+  { "xor",	Gv, Ev, XX },
+  { "xor",	AL, Ib, XX },
+  { "xor",	eAX, Iv, XX },
+  { "(bad)",	XX, XX, XX },			/* SEG SS prefix */
+  { "aaa",	XX, XX, XX },
+  /* 38 */
+  { "cmp",	Eb, Gb, XX },
+  { "cmp",	Ev, Gv, XX },
+  { "cmp",	Gb, Eb, XX },
+  { "cmp",	Gv, Ev, XX },
+  { "cmp",	AL, Ib, XX },
+  { "cmp",	eAX, Iv, XX },
+  { "(bad)",	XX, XX, XX },			/* SEG DS prefix */
+  { "aas",	XX, XX, XX },
+  /* 40 */
+  { "inc",	eAX, XX, XX },
+  { "inc",	eCX, XX, XX },
+  { "inc",	eDX, XX, XX },
+  { "inc",	eBX, XX, XX },
+  { "inc",	eSP, XX, XX },
+  { "inc",	eBP, XX, XX },
+  { "inc",	eSI, XX, XX },
+  { "inc",	eDI, XX, XX },
+  /* 48 */
+  { "dec",	eAX, XX, XX },
+  { "dec",	eCX, XX, XX },
+  { "dec",	eDX, XX, XX },
+  { "dec",	eBX, XX, XX },
+  { "dec",	eSP, XX, XX },
+  { "dec",	eBP, XX, XX },
+  { "dec",	eSI, XX, XX },
+  { "dec",	eDI, XX, XX },
+  /* 50 */
+  { "push",	eAX, XX, XX },
+  { "push",	eCX, XX, XX },
+  { "push",	eDX, XX, XX },
+  { "push",	eBX, XX, XX },
+  { "push",	eSP, XX, XX },
+  { "push",	eBP, XX, XX },
+  { "push",	eSI, XX, XX },
+  { "push",	eDI, XX, XX },
+  /* 58 */
+  { "pop",	eAX, XX, XX },
+  { "pop",	eCX, XX, XX },
+  { "pop",	eDX, XX, XX },
+  { "pop",	eBX, XX, XX },
+  { "pop",	eSP, XX, XX },
+  { "pop",	eBP, XX, XX },
+  { "pop",	eSI, XX, XX },
+  { "pop",	eDI, XX, XX },
+  /* 60 */
+  { "pusha",	XX, XX, XX },
+  { "popa",	XX, XX, XX },
+  { "bound",	Gv, Ma, XX },
+  { "arpl",	Ew, Gw, XX },
+  { "(bad)",	XX, XX, XX },			/* seg fs */
+  { "(bad)",	XX, XX, XX },			/* seg gs */
+  { "(bad)",	XX, XX, XX },			/* op size prefix */
+  { "(bad)",	XX, XX, XX },			/* adr size prefix */
+  /* 68 */
+  { "push",	Iv, XX, XX },		/* 386 book wrong */
+  { "imul",	Gv, Ev, Iv },
+  { "push",	sIb, XX, XX },	/* push of byte really pushes 2 or 4 bytes */
+  { "imul",	Gv, Ev, sIb },
+  { "ins",	Yb, indirDX, XX },
+  { "ins",	Yv, indirDX, XX },
+  { "outs",	indirDX, Xb, XX },
+  { "outs",	indirDX, Xv, XX },
+  /* 70 */
+  { "jo",	Jb, XX, XX },
+  { "jno",	Jb, XX, XX },
+  { "jb",	Jb, XX, XX },
+  { "jae",	Jb, XX, XX },
+  { "je",	Jb, XX, XX },
+  { "jne",	Jb, XX, XX },
+  { "jbe",	Jb, XX, XX },
+  { "ja",	Jb, XX, XX },
+  /* 78 */
+  { "js",	Jb, XX, XX },
+  { "jns",	Jb, XX, XX },
+  { "jp",	Jb, XX, XX },
+  { "jnp",	Jb, XX, XX },
+  { "jl",	Jb, XX, XX },
+  { "jge",	Jb, XX, XX },
+  { "jle",	Jb, XX, XX },
+  { "jg",	Jb, XX, XX },
+  /* 80 */
+  { GRP1b },
+  { GRP1S },
+  { "(bad)",	XX, XX, XX },
+  { GRP1Ss },
+  { "test",	Eb, Gb, XX },
+  { "test",	Ev, Gv, XX },
+  { "xchg",	Eb, Gb, XX },
+  { "xchg",	Ev, Gv, XX },
+  /* 88 */
+  { "mov",	Eb, Gb, XX },
+  { "mov",	Ev, Gv, XX },
+  { "mov",	Gb, Eb, XX },
+  { "mov",	Gv, Ev, XX },
+  { "mov",	Ev, Sw, XX },
+  { "lea",	Gv, M, XX },
+  { "mov",	Sw, Ev, XX },
+  { "pop",	Ev, XX, XX },
+  /* 90 */
+  { "nop",	XX, XX, XX },
+  { "xchg",	eCX, eAX, XX },
+  { "xchg",	eDX, eAX, XX },
+  { "xchg",	eBX, eAX, XX },
+  { "xchg",	eSP, eAX, XX },
+  { "xchg",	eBP, eAX, XX },
+  { "xchg",	eSI, eAX, XX },
+  { "xchg",	eDI, eAX, XX },
+  /* 98 */
+  { "cW",	XX, XX, XX },		/* cwde and cbw */
+  { "cR",	XX, XX, XX },		/* cdq and cwd */
+  { "lcall",	Ap, XX, XX },
+  { "(bad)",	XX, XX, XX },		/* fwait */
+  { "pushf",	XX, XX, XX },
+  { "popf",	XX, XX, XX },
+  { "sahf",	XX, XX, XX },
+  { "lahf",	XX, XX, XX },
+  /* a0 */
+  { "mov",	AL, Ob, XX },
+  { "mov",	eAX, Ov, XX },
+  { "mov",	Ob, AL, XX },
+  { "mov",	Ov, eAX, XX },
+  { "movs",	Yb, Xb, XX },
+  { "movs",	Yv, Xv, XX },
+  { "cmps",	Xb, Yb, XX },
+  { "cmps",	Xv, Yv, XX },
+  /* a8 */
+  { "test",	AL, Ib, XX },
+  { "test",	eAX, Iv, XX },
+  { "stos",	Yb, AL, XX },
+  { "stos",	Yv, eAX, XX },
+  { "lods",	AL, Xb, XX },
+  { "lods",	eAX, Xv, XX },
+  { "scas",	AL, Yb, XX },
+  { "scas",	eAX, Yv, XX },
+  /* b0 */
+  { "mov",	AL, Ib, XX },
+  { "mov",	CL, Ib, XX },
+  { "mov",	DL, Ib, XX },
+  { "mov",	BL, Ib, XX },
+  { "mov",	AH, Ib, XX },
+  { "mov",	CH, Ib, XX },
+  { "mov",	DH, Ib, XX },
+  { "mov",	BH, Ib, XX },
+  /* b8 */
+  { "mov",	eAX, Iv, XX },
+  { "mov",	eCX, Iv, XX },
+  { "mov",	eDX, Iv, XX },
+  { "mov",	eBX, Iv, XX },
+  { "mov",	eSP, Iv, XX },
+  { "mov",	eBP, Iv, XX },
+  { "mov",	eSI, Iv, XX },
+  { "mov",	eDI, Iv, XX },
+  /* c0 */
+  { GRP2b },
+  { GRP2S },
+  { "ret",	Iw, XX, XX },
+  { "ret",	XX, XX, XX },
+  { "les",	Gv, Mp, XX },
+  { "lds",	Gv, Mp, XX },
+  { "mov",	Eb, Ib, XX },
+  { "mov",	Ev, Iv, XX },
+  /* c8 */
+  { "enter",	Iw, Ib, XX },
+  { "leave",	XX, XX, XX },
+  { "lret",	Iw, XX, XX },
+  { "lret",	XX, XX, XX },
+  { "int3",	XX, XX, XX },
+  { "int",	Ib, XX, XX },
+  { "into",	XX, XX, XX },
+  { "iret",	XX, XX, XX },
+  /* d0 */
+  { GRP2b_one },
+  { GRP2S_one },
+  { GRP2b_cl },
+  { GRP2S_cl },
+  { "aam",	sIb, XX, XX },
+  { "aad",	sIb, XX, XX },
+  { "(bad)",	XX, XX, XX },
+  { "xlat",	DSBX, XX, XX },
+  /* d8 */
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  { FLOAT },
+  /* e0 */
+  { "loopne",	Jb, XX, XX },
+  { "loope",	Jb, XX, XX },
+  { "loop",	Jb, XX, XX },
+  { "jEcxz",	Jb, XX, XX },
+  { "in",	AL, Ib, XX },
+  { "in",	eAX, Ib, XX },
+  { "out",	Ib, AL, XX },
+  { "out",	Ib, eAX, XX },
+  /* e8 */
+  { "call",	Jv, XX, XX },
+  { "jmp",	Jv, XX, XX },
+  { "ljmp",	Ap, XX, XX },
+  { "jmp",	Jb, XX, XX },
+  { "in",	AL, indirDX, XX },
+  { "in",	eAX, indirDX, XX },
+  { "out",	indirDX, AL, XX },
+  { "out",	indirDX, eAX, XX },
+  /* f0 */
+  { "(bad)",	XX, XX, XX },			/* lock prefix */
+  { "(bad)",	XX, XX, XX },
+  { "(bad)",	XX, XX, XX },			/* repne */
+  { "(bad)",	XX, XX, XX },			/* repz */
+  { "hlt",	XX, XX, XX },
+  { "cmc",	XX, XX, XX },
+  { GRP3b },
+  { GRP3S },
+  /* f8 */
+  { "clc",	XX, XX, XX },
+  { "stc",	XX, XX, XX },
+  { "cli",	XX, XX, XX },
+  { "sti",	XX, XX, XX },
+  { "cld",	XX, XX, XX },
+  { "std",	XX, XX, XX },
+  { GRP4 },
+  { GRP5 },
+};
+
+static const struct dis386 dis386_twobyte_att[] = {
+  /* 00 */
+  { GRP6 },
+  { GRP7 },
+  { "larS", Gv, Ew, XX },
+  { "lslS", Gv, Ew, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "clts", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  /* 08 */
+  { "invd", XX, XX, XX },
+  { "wbinvd", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "ud2a", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { GRPAMD },
+  { "femms", XX, XX, XX },
+  { "", MX, EM, OPSUF }, /* See OP_3DNowSuffix */
+  /* 10 */
+  { PREGRP8 },
+  { PREGRP9 },
+  { "movlps", XM, EX, SIMD_Fixup, 'h' },  /* really only 2 operands */
+  { "movlps", EX, XM, SIMD_Fixup, 'h' },
+  { "unpcklps", XM, EX, XX },
+  { "unpckhps", XM, EX, XX },
+  { "movhps", XM, EX, SIMD_Fixup, 'l' },
+  { "movhps", EX, XM, SIMD_Fixup, 'l' },
+  /* 18 */
+  { GRP14 },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  /* 20 */
+  /* these are all backward in appendix A of the intel book */
+  { "movL", Rd, Cd, XX },
+  { "movL", Rd, Dd, XX },
+  { "movL", Cd, Rd, XX },
+  { "movL", Dd, Rd, XX },
+  { "movL", Rd, Td, XX },
+  { "(bad)", XX, XX, XX },
+  { "movL", Td, Rd, XX },
+  { "(bad)", XX, XX, XX },
+  /* 28 */
+  { "movaps", XM, EX, XX },
+  { "movaps", EX, XM, XX },
+  { PREGRP2 },
+  { "movntps", Ev, XM, XX },
+  { PREGRP4 },
+  { PREGRP3 },
+  { "ucomiss", XM, EX, XX },
+  { "comiss", XM, EX, XX },
+  /* 30 */
+  { "wrmsr", XX, XX, XX },
+  { "rdtsc", XX, XX, XX },
+  { "rdmsr", XX, XX, XX },
+  { "rdpmc", XX, XX, XX },
+  { "sysenter", XX, XX, XX },
+  { "sysexit", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  /* 38 */
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  /* 40 */
+  { "cmovo", Gv, Ev, XX },
+  { "cmovno", Gv, Ev, XX },
+  { "cmovb", Gv, Ev, XX },
+  { "cmovae", Gv, Ev, XX },
+  { "cmove", Gv, Ev, XX },
+  { "cmovne", Gv, Ev, XX },
+  { "cmovbe", Gv, Ev, XX },
+  { "cmova", Gv, Ev, XX },
+  /* 48 */
+  { "cmovs", Gv, Ev, XX },
+  { "cmovns", Gv, Ev, XX },
+  { "cmovp", Gv, Ev, XX },
+  { "cmovnp", Gv, Ev, XX },
+  { "cmovl", Gv, Ev, XX },
+  { "cmovge", Gv, Ev, XX },
+  { "cmovle", Gv, Ev, XX },
+  { "cmovg", Gv, Ev, XX },
+  /* 50 */
+  { "movmskps", Gv, EX, XX },
+  { PREGRP13 },
+  { PREGRP12 },
+  { PREGRP11 },
+  { "andps", XM, EX, XX },
+  { "andnps", XM, EX, XX },
+  { "orps", XM, EX, XX },
+  { "xorps", XM, EX, XX },
+  /* 58 */
+  { PREGRP0 },
+  { PREGRP10 },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { PREGRP14 },
+  { PREGRP7 },
+  { PREGRP5 },
+  { PREGRP6 },
+  /* 60 */
+  { "punpcklbw", MX, EM, XX },
+  { "punpcklwd", MX, EM, XX },
+  { "punpckldq", MX, EM, XX },
+  { "packsswb", MX, EM, XX },
+  { "pcmpgtb", MX, EM, XX },
+  { "pcmpgtw", MX, EM, XX },
+  { "pcmpgtd", MX, EM, XX },
+  { "packuswb", MX, EM, XX },
+  /* 68 */
+  { "punpckhbw", MX, EM, XX },
+  { "punpckhwd", MX, EM, XX },
+  { "punpckhdq", MX, EM, XX },
+  { "packssdw", MX, EM, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "movd", MX, Ed, XX },
+  { "movq", MX, EM, XX },
+  /* 70 */
+  { "pshufw", MX, EM, Ib },
+  { GRP10 },
+  { GRP11 },
+  { GRP12 },
+  { "pcmpeqb", MX, EM, XX },
+  { "pcmpeqw", MX, EM, XX },
+  { "pcmpeqd", MX, EM, XX },
+  { "emms", XX, XX, XX },
+  /* 78 */
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "movd", Ed, MX, XX },
+  { "movq", EM, MX, XX },
+  /* 80 */
+  { "jo", Jv, XX, XX },
+  { "jno", Jv, XX, XX },
+  { "jb", Jv, XX, XX },
+  { "jae", Jv, XX, XX },
+  { "je", Jv, XX, XX },
+  { "jne", Jv, XX, XX },
+  { "jbe", Jv, XX, XX },
+  { "ja", Jv, XX, XX },
+  /* 88 */
+  { "js", Jv, XX, XX },
+  { "jns", Jv, XX, XX },
+  { "jp", Jv, XX, XX },
+  { "jnp", Jv, XX, XX },
+  { "jl", Jv, XX, XX },
+  { "jge", Jv, XX, XX },
+  { "jle", Jv, XX, XX },
+  { "jg", Jv, XX, XX },
+  /* 90 */
+  { "seto", Eb, XX, XX },
+  { "setno", Eb, XX, XX },
+  { "setb", Eb, XX, XX },
+  { "setae", Eb, XX, XX },
+  { "sete", Eb, XX, XX },
+  { "setne", Eb, XX, XX },
+  { "setbe", Eb, XX, XX },
+  { "seta", Eb, XX, XX },
+  /* 98 */
+  { "sets", Eb, XX, XX },
+  { "setns", Eb, XX, XX },
+  { "setp", Eb, XX, XX },
+  { "setnp", Eb, XX, XX },
+  { "setl", Eb, XX, XX },
+  { "setge", Eb, XX, XX },
+  { "setle", Eb, XX, XX },
+  { "setg", Eb, XX, XX },
+  /* a0 */
+  { "pushP", fs, XX, XX },
+  { "popP", fs, XX, XX },
+  { "cpuid", XX, XX, XX },
+  { "btS", Ev, Gv, XX },
+  { "shldS", Ev, Gv, Ib },
+  { "shldS", Ev, Gv, CL },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  /* a8 */
+  { "pushP", gs, XX, XX },
+  { "popP", gs, XX, XX },
+  { "rsm", XX, XX, XX },
+  { "btsS", Ev, Gv, XX },
+  { "shrdS", Ev, Gv, Ib },
+  { "shrdS", Ev, Gv, CL },
+  { GRP13 },
+  { "imulS", Gv, Ev, XX },
+  /* b0 */
+  { "cmpxchgB", Eb, Gb, XX },
+  { "cmpxchgS", Ev, Gv, XX },
+  { "lssS", Gv, Mp, XX },
+  { "btrS", Ev, Gv, XX },
+  { "lfsS", Gv, Mp, XX },
+  { "lgsS", Gv, Mp, XX },
+  { "movzbR", Gv, Eb, XX },
+  { "movzwR", Gv, Ew, XX }, /* yes, there really is movzww ! */
+  /* b8 */
+  { "(bad)", XX, XX, XX },
+  { "ud2b", XX, XX, XX },
+  { GRP8 },
+  { "btcS", Ev, Gv, XX },
+  { "bsfS", Gv, Ev, XX },
+  { "bsrS", Gv, Ev, XX },
+  { "movsbR", Gv, Eb, XX },
+  { "movswR", Gv, Ew, XX }, /* yes, there really is movsww ! */
+  /* c0 */
+  { "xaddB", Eb, Gb, XX },
+  { "xaddS", Ev, Gv, XX },
+  { PREGRP1 },
+  { "(bad)", XX, XX, XX },
+  { "pinsrw", MX, Ev, Ib },
+  { "pextrw", Ev, MX, Ib },
+  { "shufps", XM, EX, Ib },
+  { GRP9 },
+  /* c8 */
+  { "bswap", eAX, XX, XX },	/* bswap doesn't support 16 bit regs */
+  { "bswap", eCX, XX, XX },
+  { "bswap", eDX, XX, XX },
+  { "bswap", eBX, XX, XX },
+  { "bswap", eSP, XX, XX },
+  { "bswap", eBP, XX, XX },
+  { "bswap", eSI, XX, XX },
+  { "bswap", eDI, XX, XX },
+  /* d0 */
+  { "(bad)", XX, XX, XX },
+  { "psrlw", MX, EM, XX },
+  { "psrld", MX, EM, XX },
+  { "psrlq", MX, EM, XX },
+  { "(bad)", XX, XX, XX },
+  { "pmullw", MX, EM, XX },
+  { "(bad)", XX, XX, XX },
+  { "pmovmskb", Ev, MX, XX },
+  /* d8 */
+  { "psubusb", MX, EM, XX },
+  { "psubusw", MX, EM, XX },
+  { "pminub", MX, EM, XX },
+  { "pand", MX, EM, XX },
+  { "paddusb", MX, EM, XX },
+  { "paddusw", MX, EM, XX },
+  { "pmaxub", MX, EM, XX },
+  { "pandn", MX, EM, XX },
+  /* e0 */
+  { "pavgb", MX, EM, XX },
+  { "psraw", MX, EM, XX },
+  { "psrad", MX, EM, XX },
+  { "pavgw", MX, EM, XX },
+  { "pmulhuw", MX, EM, XX },
+  { "pmulhw", MX, EM, XX },
+  { "(bad)", XX, XX, XX },
+  { "movntq", Ev, MX, XX },
+  /* e8 */
+  { "psubsb", MX, EM, XX },
+  { "psubsw", MX, EM, XX },
+  { "pminsw", MX, EM, XX },
+  { "por", MX, EM, XX },
+  { "paddsb", MX, EM, XX },
+  { "paddsw", MX, EM, XX },
+  { "pmaxsw", MX, EM, XX },
+  { "pxor", MX, EM, XX },
+  /* f0 */
+  { "(bad)", XX, XX, XX },
+  { "psllw", MX, EM, XX },
+  { "pslld", MX, EM, XX },
+  { "psllq", MX, EM, XX },
+  { "(bad)", XX, XX, XX },
+  { "pmaddwd", MX, EM, XX },
+  { "psadbw", MX, EM, XX },
+  { "maskmovq", MX, EM, XX },
+  /* f8 */
+  { "psubb", MX, EM, XX },
+  { "psubw", MX, EM, XX },
+  { "psubd", MX, EM, XX },
+  { "(bad)", XX, XX, XX },
+  { "paddb", MX, EM, XX },
+  { "paddw", MX, EM, XX },
+  { "paddd", MX, EM, XX },
+  { "(bad)", XX, XX, XX }
+};
+
+static const struct dis386 dis386_twobyte_intel[] = {
+  /* 00 */
+  { GRP6 },
+  { GRP7 },
+  { "lar", Gv, Ew, XX },
+  { "lsl", Gv, Ew, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "clts", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  /* 08 */
+  { "invd", XX, XX, XX },
+  { "wbinvd", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "ud2a", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { GRPAMD },
+  { "femms" , XX, XX, XX},
+  { "", MX, EM, OPSUF }, /* See OP_3DNowSuffix */
+  /* 10 */
+  { PREGRP8 },
+  { PREGRP9 },
+  { "movlps", XM, EX, SIMD_Fixup, 'h' },  /* really only 2 operands */
+  { "movlps", EX, XM, SIMD_Fixup, 'h' },
+  { "unpcklps", XM, EX, XX },
+  { "unpckhps", XM, EX, XX },
+  { "movhps", XM, EX, SIMD_Fixup, 'l' },
+  { "movhps", EX, XM, SIMD_Fixup, 'l' },
+  /* 18 */
+  { GRP14 },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  /* 20 */
+  /* these are all backward in appendix A of the intel book */
+  { "mov", Rd, Cd, XX },
+  { "mov", Rd, Dd, XX },
+  { "mov", Cd, Rd, XX },
+  { "mov", Dd, Rd, XX },
+  { "mov", Rd, Td, XX },
+  { "(bad)", XX, XX, XX },
+  { "mov", Td, Rd, XX },
+  { "(bad)", XX, XX, XX },
+  /* 28 */
+  { "movaps", XM, EX, XX },
+  { "movaps", EX, XM, XX },
+  { PREGRP2 },
+  { "movntps", Ev, XM, XX },
+  { PREGRP4 },
+  { PREGRP3 },
+  { "ucomiss", XM, EX, XX },
+  { "comiss", XM, EX, XX },
+  /* 30 */
+  { "wrmsr", XX, XX, XX },
+  { "rdtsc", XX, XX, XX },
+  { "rdmsr", XX, XX, XX },
+  { "rdpmc", XX, XX, XX },
+  { "sysenter", XX, XX, XX },
+  { "sysexit", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  /* 38 */
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  /* 40 */
+  { "cmovo", Gv, Ev, XX },
+  { "cmovno", Gv, Ev, XX },
+  { "cmovb", Gv, Ev, XX },
+  { "cmovae", Gv, Ev, XX },
+  { "cmove", Gv, Ev, XX },
+  { "cmovne", Gv, Ev, XX },
+  { "cmovbe", Gv, Ev, XX },
+  { "cmova", Gv, Ev, XX },
+  /* 48 */
+  { "cmovs", Gv, Ev, XX },
+  { "cmovns", Gv, Ev, XX },
+  { "cmovp", Gv, Ev, XX },
+  { "cmovnp", Gv, Ev, XX },
+  { "cmovl", Gv, Ev, XX },
+  { "cmovge", Gv, Ev, XX },
+  { "cmovle", Gv, Ev, XX },
+  { "cmovg", Gv, Ev, XX },
+  /* 50 */
+  { "movmskps", Gv, EX, XX },
+  { PREGRP13 },
+  { PREGRP12 },
+  { PREGRP11 },
+  { "andps", XM, EX, XX },
+  { "andnps", XM, EX, XX },
+  { "orps", XM, EX, XX },
+  { "xorps", XM, EX, XX },
+  /* 58 */
+  { PREGRP0 },
+  { PREGRP10 },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { PREGRP14 },
+  { PREGRP7 },
+  { PREGRP5 },
+  { PREGRP6 },
+  /* 60 */
+  { "punpcklbw", MX, EM, XX },
+  { "punpcklwd", MX, EM, XX },
+  { "punpckldq", MX, EM, XX },
+  { "packsswb", MX, EM, XX },
+  { "pcmpgtb", MX, EM, XX },
+  { "pcmpgtw", MX, EM, XX },
+  { "pcmpgtd", MX, EM, XX },
+  { "packuswb", MX, EM, XX },
+  /* 68 */
+  { "punpckhbw", MX, EM, XX },
+  { "punpckhwd", MX, EM, XX },
+  { "punpckhdq", MX, EM, XX },
+  { "packssdw", MX, EM, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "movd", MX, Ed, XX },
+  { "movq", MX, EM, XX },
+  /* 70 */
+  { "pshufw", MX, EM, Ib },
+  { GRP10 },
+  { GRP11 },
+  { GRP12 },
+  { "pcmpeqb", MX, EM, XX },
+  { "pcmpeqw", MX, EM, XX },
+  { "pcmpeqd", MX, EM, XX },
+  { "emms", XX, XX, XX },
+  /* 78 */
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  { "movd", Ed, MX, XX },
+  { "movq", EM, MX, XX },
+  /* 80 */
+  { "jo", Jv, XX, XX },
+  { "jno", Jv, XX, XX },
+  { "jb", Jv, XX, XX },
+  { "jae", Jv, XX, XX },
+  { "je", Jv, XX, XX },
+  { "jne", Jv, XX, XX },
+  { "jbe", Jv, XX, XX },
+  { "ja", Jv, XX, XX },
+  /* 88 */
+  { "js", Jv, XX, XX },
+  { "jns", Jv, XX, XX },
+  { "jp", Jv, XX, XX },
+  { "jnp", Jv, XX, XX },
+  { "jl", Jv, XX, XX },
+  { "jge", Jv, XX, XX },
+  { "jle", Jv, XX, XX },
+  { "jg", Jv, XX, XX },
+  /* 90 */
+  { "seto", Eb, XX, XX },
+  { "setno", Eb, XX, XX },
+  { "setb", Eb, XX, XX },
+  { "setae", Eb, XX, XX },
+  { "sete", Eb, XX, XX },
+  { "setne", Eb, XX, XX },
+  { "setbe", Eb, XX, XX },
+  { "seta", Eb, XX, XX },
+  /* 98 */
+  { "sets", Eb, XX, XX },
+  { "setns", Eb, XX, XX },
+  { "setp", Eb, XX, XX },
+  { "setnp", Eb, XX, XX },
+  { "setl", Eb, XX, XX },
+  { "setge", Eb, XX, XX },
+  { "setle", Eb, XX, XX },
+  { "setg", Eb, XX, XX },
+  /* a0 */
+  { "push", fs, XX, XX },
+  { "pop", fs, XX, XX },
+  { "cpuid", XX, XX, XX },
+  { "bt", Ev, Gv, XX },
+  { "shld", Ev, Gv, Ib },
+  { "shld", Ev, Gv, CL },
+  { "(bad)", XX, XX, XX },
+  { "(bad)", XX, XX, XX },
+  /* a8 */
+  { "push", gs, XX, XX },
+  { "pop", gs, XX, XX },
+  { "rsm" , XX, XX, XX},
+  { "bts", Ev, Gv, XX },
+  { "shrd", Ev, Gv, Ib },
+  { "shrd", Ev, Gv, CL },
+  { GRP13 },
+  { "imul", Gv, Ev, XX },
+  /* b0 */
+  { "cmpxchg", Eb, Gb, XX },
+  { "cmpxchg", Ev, Gv, XX },
+  { "lss", Gv, Mp, XX },
+  { "btr", Ev, Gv, XX },
+  { "lfs", Gv, Mp, XX },
+  { "lgs", Gv, Mp, XX },
+  { "movzx", Gv, Eb, XX },
+  { "movzx", Gv, Ew, XX },
+  /* b8 */
+  { "(bad)", XX, XX, XX },
+  { "ud2b", XX, XX, XX },
+  { GRP8 },
+  { "btc", Ev, Gv, XX },
+  { "bsf", Gv, Ev, XX },
+  { "bsr", Gv, Ev, XX },
+  { "movsx", Gv, Eb, XX },
+  { "movsx", Gv, Ew, XX },
+  /* c0 */
+  { "xadd", Eb, Gb, XX },
+  { "xadd", Ev, Gv, XX },
+  { PREGRP1 },
+  { "(bad)", XX, XX, XX },
+  { "pinsrw", MX, Ev, Ib },
+  { "pextrw", Ev, MX, Ib },
+  { "shufps", XM, EX, Ib },
+  { GRP9 },
+  /* c8 */
+  { "bswap", eAX, XX, XX },	/* bswap doesn't support 16 bit regs */
+  { "bswap", eCX, XX, XX },
+  { "bswap", eDX, XX, XX },
+  { "bswap", eBX, XX, XX },
+  { "bswap", eSP, XX, XX },
+  { "bswap", eBP, XX, XX },
+  { "bswap", eSI, XX, XX },
+  { "bswap", eDI, XX, XX },
+  /* d0 */
+  { "(bad)", XX, XX, XX },
+  { "psrlw", MX, EM, XX },
+  { "psrld", MX, EM, XX },
+  { "psrlq", MX, EM, XX },
+  { "(bad)", XX, XX, XX },
+  { "pmullw", MX, EM, XX },
+  { "(bad)", XX, XX, XX },
+  { "pmovmskb", Ev, MX, XX },
+  /* d8 */
+  { "psubusb", MX, EM, XX },
+  { "psubusw", MX, EM, XX },
+  { "pminub", MX, EM, XX },
+  { "pand", MX, EM, XX },
+  { "paddusb", MX, EM, XX },
+  { "paddusw", MX, EM, XX },
+  { "pmaxub", MX, EM, XX },
+  { "pandn", MX, EM, XX },
+  /* e0 */
+  { "pavgb", MX, EM, XX },
+  { "psraw", MX, EM, XX },
+  { "psrad", MX, EM, XX },
+  { "pavgw", MX, EM, XX },
+  { "pmulhuw", MX, EM, XX },
+  { "pmulhw", MX, EM, XX },
+  { "(bad)", XX, XX, XX },
+  { "movntq", Ev, MX, XX },
+  /* e8 */
+  { "psubsb", MX, EM, XX },
+  { "psubsw", MX, EM, XX },
+  { "pminsw", MX, EM, XX },
+  { "por", MX, EM, XX },
+  { "paddsb", MX, EM, XX },
+  { "paddsw", MX, EM, XX },
+  { "pmaxsw", MX, EM, XX },
+  { "pxor", MX, EM, XX },
+  /* f0 */
+  { "(bad)", XX, XX, XX },
+  { "psllw", MX, EM, XX },
+  { "pslld", MX, EM, XX },
+  { "psllq", MX, EM, XX },
+  { "(bad)", XX, XX, XX },
+  { "pmaddwd", MX, EM, XX },
+  { "psadbw", MX, EM, XX },
+  { "maskmovq", MX, EM, XX },
+  /* f8 */
+  { "psubb", MX, EM, XX },
+  { "psubw", MX, EM, XX },
+  { "psubd", MX, EM, XX },
+  { "(bad)", XX, XX, XX },
+  { "paddb", MX, EM, XX },
+  { "paddw", MX, EM, XX },
+  { "paddd", MX, EM, XX },
+  { "(bad)", XX, XX, XX }
+};
+
+static const unsigned char onebyte_has_modrm[256] = {
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+  /*       -------------------------------        */
+  /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 00 */
+  /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 10 */
+  /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 20 */
+  /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 30 */
+  /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */
+  /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */
+  /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0, /* 60 */
+  /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */
+  /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 80 */
+  /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */
+  /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* a0 */
+  /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* b0 */
+  /* c0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* c0 */
+  /* d0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* d0 */
+  /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* e0 */
+  /* f0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1  /* f0 */
+  /*       -------------------------------        */
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+};
+
+static const unsigned char twobyte_has_modrm[256] = {
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+  /*       -------------------------------        */
+  /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */
+  /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, /* 1f */
+  /* 20 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 2f */
+  /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+  /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
+  /* 50 */ 1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1, /* 5f */
+  /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1, /* 6f */
+  /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, /* 7f */
+  /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+  /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
+  /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */
+  /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */
+  /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
+  /* d0 */ 0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1, /* df */
+  /* e0 */ 1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1, /* ef */
+  /* f0 */ 0,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0  /* ff */
+  /*       -------------------------------        */
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+};
+
+static const unsigned char twobyte_uses_f3_prefix[256] = {
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+  /*       -------------------------------        */
+  /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+  /* 10 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+  /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0, /* 2f */
+  /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+  /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+  /* 50 */ 0,1,1,1,0,0,0,0,1,1,0,0,1,1,1,1, /* 5f */
+  /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+  /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+  /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+  /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+  /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+  /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+  /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+  /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+  /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+  /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0  /* ff */
+  /*       -------------------------------        */
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+};
+
+static char obuf[100];
+static char *obufp;
+static char scratchbuf[100];
+static unsigned char *start_codep;
+static unsigned char *insn_codep;
+static unsigned char *codep;
+static disassemble_info *the_info;
+static int mod;
+static int rm;
+static int reg;
+static void oappend PARAMS ((const char *s));
+
+static const char *names32[]={
+  "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
+};
+static const char *names16[] = {
+  "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
+};
+static const char *names8[] = {
+  "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
+};
+static const char *names_seg[] = {
+  "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+};
+static const char *index16[] = {
+  "%bx,%si","%bx,%di","%bp,%si","%bp,%di","%si","%di","%bp","%bx"
+};
+
+static const struct dis386 grps[][8] = {
+  /* GRP1b */
+  {
+    { "addA",	Eb, Ib, XX },
+    { "orA",	Eb, Ib, XX },
+    { "adcA",	Eb, Ib, XX },
+    { "sbbA",	Eb, Ib, XX },
+    { "andA",	Eb, Ib, XX },
+    { "subA",	Eb, Ib, XX },
+    { "xorA",	Eb, Ib, XX },
+    { "cmpA",	Eb, Ib, XX }
+  },
+  /* GRP1S */
+  {
+    { "addQ",	Ev, Iv, XX },
+    { "orQ",	Ev, Iv, XX },
+    { "adcQ",	Ev, Iv, XX },
+    { "sbbQ",	Ev, Iv, XX },
+    { "andQ",	Ev, Iv, XX },
+    { "subQ",	Ev, Iv, XX },
+    { "xorQ",	Ev, Iv, XX },
+    { "cmpQ",	Ev, Iv, XX }
+  },
+  /* GRP1Ss */
+  {
+    { "addQ",	Ev, sIb, XX },
+    { "orQ",	Ev, sIb, XX },
+    { "adcQ",	Ev, sIb, XX },
+    { "sbbQ",	Ev, sIb, XX },
+    { "andQ",	Ev, sIb, XX },
+    { "subQ",	Ev, sIb, XX },
+    { "xorQ",	Ev, sIb, XX },
+    { "cmpQ",	Ev, sIb, XX }
+  },
+  /* GRP2b */
+  {
+    { "rolA",	Eb, Ib, XX },
+    { "rorA",	Eb, Ib, XX },
+    { "rclA",	Eb, Ib, XX },
+    { "rcrA",	Eb, Ib, XX },
+    { "shlA",	Eb, Ib, XX },
+    { "shrA",	Eb, Ib, XX },
+    { "(bad)",	XX, XX, XX },
+    { "sarA",	Eb, Ib, XX },
+  },
+  /* GRP2S */
+  {
+    { "rolQ",	Ev, Ib, XX },
+    { "rorQ",	Ev, Ib, XX },
+    { "rclQ",	Ev, Ib, XX },
+    { "rcrQ",	Ev, Ib, XX },
+    { "shlQ",	Ev, Ib, XX },
+    { "shrQ",	Ev, Ib, XX },
+    { "(bad)",	XX, XX, XX },
+    { "sarQ",	Ev, Ib, XX },
+  },
+  /* GRP2b_one */
+  {
+    { "rolA",	Eb, XX, XX },
+    { "rorA",	Eb, XX, XX },
+    { "rclA",	Eb, XX, XX },
+    { "rcrA",	Eb, XX, XX },
+    { "shlA",	Eb, XX, XX },
+    { "shrA",	Eb, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "sarA",	Eb, XX, XX },
+  },
+  /* GRP2S_one */
+  {
+    { "rolQ",	Ev, XX, XX },
+    { "rorQ",	Ev, XX, XX },
+    { "rclQ",	Ev, XX, XX },
+    { "rcrQ",	Ev, XX, XX },
+    { "shlQ",	Ev, XX, XX },
+    { "shrQ",	Ev, XX, XX },
+    { "(bad)",	XX, XX, XX},
+    { "sarQ",	Ev, XX, XX },
+  },
+  /* GRP2b_cl */
+  {
+    { "rolA",	Eb, CL, XX },
+    { "rorA",	Eb, CL, XX },
+    { "rclA",	Eb, CL, XX },
+    { "rcrA",	Eb, CL, XX },
+    { "shlA",	Eb, CL, XX },
+    { "shrA",	Eb, CL, XX },
+    { "(bad)",	XX, XX, XX },
+    { "sarA",	Eb, CL, XX },
+  },
+  /* GRP2S_cl */
+  {
+    { "rolQ",	Ev, CL, XX },
+    { "rorQ",	Ev, CL, XX },
+    { "rclQ",	Ev, CL, XX },
+    { "rcrQ",	Ev, CL, XX },
+    { "shlQ",	Ev, CL, XX },
+    { "shrQ",	Ev, CL, XX },
+    { "(bad)",	XX, XX, XX },
+    { "sarQ",	Ev, CL, XX }
+  },
+  /* GRP3b */
+  {
+    { "testA",	Eb, Ib, XX },
+    { "(bad)",	Eb, XX, XX },
+    { "notA",	Eb, XX, XX },
+    { "negA",	Eb, XX, XX },
+    { "mulB",	AL, Eb, XX },
+    { "imulB",	AL, Eb, XX },
+    { "divB",	AL, Eb, XX },
+    { "idivB",	AL, Eb, XX }
+  },
+  /* GRP3S */
+  {
+    { "testQ",	Ev, Iv, XX },
+    { "(bad)",	XX, XX, XX },
+    { "notQ",	Ev, XX, XX },
+    { "negQ",	Ev, XX, XX },
+    { "mulS",	eAX, Ev, XX },
+    { "imulS",	eAX, Ev, XX },
+    { "divS",	eAX, Ev, XX },
+    { "idivS",	eAX, Ev, XX },
+  },
+  /* GRP4 */
+  {
+    { "incA",	Eb, XX, XX },
+    { "decA",	Eb, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+  },
+  /* GRP5 */
+  {
+    { "incQ",	Ev, XX, XX },
+    { "decQ",	Ev, XX, XX },
+    { "callP",	indirEv, XX, XX },
+    { "lcallP",	indirEv, XX, XX },
+    { "jmpP",	indirEv, XX, XX },
+    { "ljmpP",	indirEv, XX, XX },
+    { "pushQ",	Ev, XX, XX },
+    { "(bad)",	XX, XX, XX },
+  },
+  /* GRP6 */
+  {
+    { "sldt",	Ew, XX, XX },
+    { "str",	Ew, XX, XX },
+    { "lldt",	Ew, XX, XX },
+    { "ltr",	Ew, XX, XX },
+    { "verr",	Ew, XX, XX },
+    { "verw",	Ew, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX }
+  },
+  /* GRP7 */
+  {
+    { "sgdt", Ew, XX, XX },
+    { "sidt", Ew, XX, XX },
+    { "lgdt", Ew, XX, XX },
+    { "lidt", Ew, XX, XX },
+    { "smsw", Ew, XX, XX },
+    { "(bad)", XX, XX, XX },
+    { "lmsw", Ew, XX, XX },
+    { "invlpg", Ew, XX, XX },
+  },
+  /* GRP8 */
+  {
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "btQ",	Ev, Ib, XX },
+    { "btsQ",	Ev, Ib, XX },
+    { "btrQ",	Ev, Ib, XX },
+    { "btcQ",	Ev, Ib, XX },
+  },
+  /* GRP9 */
+  {
+    { "(bad)",	XX, XX, XX },
+    { "cmpxchg8b", Ev, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+  },
+  /* GRP10 */
+  {
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "psrlw",	MS, Ib, XX },
+    { "(bad)",	XX, XX, XX },
+    { "psraw",	MS, Ib, XX },
+    { "(bad)",	XX, XX, XX },
+    { "psllw",	MS, Ib, XX },
+    { "(bad)",	XX, XX, XX },
+  },
+  /* GRP11 */
+  {
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "psrld",	MS, Ib, XX },
+    { "(bad)",	XX, XX, XX },
+    { "psrad",	MS, Ib, XX },
+    { "(bad)",	XX, XX, XX },
+    { "pslld",	MS, Ib, XX },
+    { "(bad)",	XX, XX, XX },
+  },
+  /* GRP12 */
+  {
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "psrlq",	MS, Ib, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "psllq",	MS, Ib, XX },
+    { "(bad)",	XX, XX, XX },
+  },
+  /* GRP13 */
+  {
+    { "fxsave", Ev, XX, XX },
+    { "fxrstor", Ev, XX, XX },
+    { "ldmxcsr", Ev, XX, XX },
+    { "stmxcsr", Ev, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "sfence", None, XX, XX },
+  },
+  /* GRP14 */
+  {
+    { "prefetchnta", Ev, XX, XX },
+    { "prefetcht0", Ev, XX, XX },
+    { "prefetcht1", Ev, XX, XX },
+    { "prefetcht2", Ev, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+  },
+  /* GRPAMD */
+  {
+    { "prefetch", Eb, XX, XX },
+    { "prefetchw", Eb, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+  }
+
+};
+
+static const struct dis386 prefix_user_table[][2] = {
+  /* PREGRP0 */
+  {
+    { "addps", XM, EX, XX },
+    { "addss", XM, EX, XX },
+  },
+  /* PREGRP1 */
+  {
+    { "", XM, EX, OPSIMD },	/* See OP_SIMD_SUFFIX */
+    { "", XM, EX, OPSIMD },
+  },
+  /* PREGRP2 */
+  {
+    { "cvtpi2ps", XM, EM, XX },
+    { "cvtsi2ss", XM, Ev, XX },
+  },
+  /* PREGRP3 */
+  {
+    { "cvtps2pi", MX, EX, XX },
+    { "cvtss2si", Gv, EX, XX },
+  },
+  /* PREGRP4 */
+  {
+    { "cvttps2pi", MX, EX, XX },
+    { "cvttss2si", Gv, EX, XX },
+  },
+  /* PREGRP5 */
+  {
+    { "divps", XM, EX, XX },
+    { "divss", XM, EX, XX },
+  },
+  /* PREGRP6 */
+  {
+    { "maxps", XM, EX, XX },
+    { "maxss", XM, EX, XX },
+  },
+  /* PREGRP7 */
+  {
+    { "minps", XM, EX, XX },
+    { "minss", XM, EX, XX },
+  },
+  /* PREGRP8 */
+  {
+    { "movups", XM, EX, XX },
+    { "movss", XM, EX, XX },
+  },
+  /* PREGRP9 */
+  {
+    { "movups", EX, XM, XX },
+    { "movss", EX, XM, XX },
+  },
+  /* PREGRP10 */
+  {
+    { "mulps", XM, EX, XX },
+    { "mulss", XM, EX, XX },
+  },
+  /* PREGRP11 */
+  {
+    { "rcpps", XM, EX, XX },
+    { "rcpss", XM, EX, XX },
+  },
+  /* PREGRP12 */
+  {
+    { "rsqrtps", XM, EX, XX },
+    { "rsqrtss", XM, EX, XX },
+  },
+  /* PREGRP13 */
+  {
+    { "sqrtps", XM, EX, XX },
+    { "sqrtss", XM, EX, XX },
+  },
+  /* PREGRP14 */
+  {
+    { "subps", XM, EX, XX },
+    { "subss", XM, EX, XX },
+  }
+};
+
+#define INTERNAL_DISASSEMBLER_ERROR "<internal disassembler error>"
+
+static void
+ckprefix ()
+{
+  prefixes = 0;
+  used_prefixes = 0;
+  while (1)
+    {
+      FETCH_DATA (the_info, codep + 1);
+      switch (*codep)
+	{
+	case 0xf3:
+	  prefixes |= PREFIX_REPZ;
+	  break;
+	case 0xf2:
+	  prefixes |= PREFIX_REPNZ;
+	  break;
+	case 0xf0:
+	  prefixes |= PREFIX_LOCK;
+	  break;
+	case 0x2e:
+	  prefixes |= PREFIX_CS;
+	  break;
+	case 0x36:
+	  prefixes |= PREFIX_SS;
+	  break;
+	case 0x3e:
+	  prefixes |= PREFIX_DS;
+	  break;
+	case 0x26:
+	  prefixes |= PREFIX_ES;
+	  break;
+	case 0x64:
+	  prefixes |= PREFIX_FS;
+	  break;
+	case 0x65:
+	  prefixes |= PREFIX_GS;
+	  break;
+	case 0x66:
+	  prefixes |= PREFIX_DATA;
+	  break;
+	case 0x67:
+	  prefixes |= PREFIX_ADDR;
+	  break;
+	case FWAIT_OPCODE:
+	  /* fwait is really an instruction.  If there are prefixes
+	     before the fwait, they belong to the fwait, *not* to the
+	     following instruction.  */
+	  if (prefixes)
+	    {
+	      prefixes |= PREFIX_FWAIT;
+	      codep++;
+	      return;
+	    }
+	  prefixes = PREFIX_FWAIT;
+	  break;
+	default:
+	  return;
+	}
+      codep++;
+    }
+}
+
+/* Return the name of the prefix byte PREF, or NULL if PREF is not a
+   prefix byte.  */
+
+static const char *
+prefix_name (pref, sizeflag)
+     int pref;
+     int sizeflag;
+{
+  switch (pref)
+    {
+    case 0xf3:
+      return "repz";
+    case 0xf2:
+      return "repnz";
+    case 0xf0:
+      return "lock";
+    case 0x2e:
+      return "cs";
+    case 0x36:
+      return "ss";
+    case 0x3e:
+      return "ds";
+    case 0x26:
+      return "es";
+    case 0x64:
+      return "fs";
+    case 0x65:
+      return "gs";
+    case 0x66:
+      return (sizeflag & DFLAG) ? "data16" : "data32";
+    case 0x67:
+      return (sizeflag & AFLAG) ? "addr16" : "addr32";
+    case FWAIT_OPCODE:
+      return "fwait";
+    default:
+      return NULL;
+    }
+}
+
+static char op1out[100], op2out[100], op3out[100];
+static int op_ad, op_index[3];
+static unsigned int op_address[3];
+static unsigned int start_pc;
+
+
+/*
+ *   On the 386's of 1988, the maximum length of an instruction is 15 bytes.
+ *   (see topic "Redundant prefixes" in the "Differences from 8086"
+ *   section of the "Virtual 8086 Mode" chapter.)
+ * 'pc' should be the address of this instruction, it will
+ *   be used to print the target address if this is a relative jump or call
+ * The function returns the length of this instruction in bytes.
+ */
+
+static int print_insn_i386
+  PARAMS ((bfd_vma pc, disassemble_info *info));
+
+static char intel_syntax;
+static char open_char;
+static char close_char;
+static char separator_char;
+static char scale_char;
+
+int
+print_insn_i386_att (pc, info)
+     bfd_vma pc;
+     disassemble_info *info;
+{
+  intel_syntax = 0;
+  open_char = '(';
+  close_char =  ')';
+  separator_char = ',';
+  scale_char = ',';
+
+  return print_insn_i386 (pc, info);
+}
+
+int
+print_insn_i386_intel (pc, info)
+     bfd_vma pc;
+     disassemble_info *info;
+{
+  intel_syntax = 1;
+  open_char = '[';
+  close_char = ']';
+  separator_char = '+';
+  scale_char = '*';
+
+  return print_insn_i386 (pc, info);
+}
+
+static int
+print_insn_i386 (pc, info)
+     bfd_vma pc;
+     disassemble_info *info;
+{
+  const struct dis386 *dp;
+  int i;
+  int two_source_ops;
+  char *first, *second, *third;
+  int needcomma;
+  unsigned char need_modrm;
+  unsigned char uses_f3_prefix;
+  VOLATILE int sizeflag;
+  VOLATILE int orig_sizeflag;
+
+  struct dis_private priv;
+  bfd_byte *inbuf = priv.the_buffer;
+
+  if (info->mach == bfd_mach_i386_i386
+      || info->mach == bfd_mach_i386_i386_intel_syntax)
+    sizeflag = AFLAG|DFLAG;
+  else if (info->mach == bfd_mach_i386_i8086)
+    sizeflag = 0;
+  else
+    abort ();
+  orig_sizeflag = sizeflag;
+
+  /* The output looks better if we put 7 bytes on a line, since that
+     puts most long word instructions on a single line.  */
+  info->bytes_per_line = 7;
+
+  info->private_data = (PTR) &priv;
+  priv.max_fetched = priv.the_buffer;
+  priv.insn_start = pc;
+
+  obuf[0] = 0;
+  op1out[0] = 0;
+  op2out[0] = 0;
+  op3out[0] = 0;
+
+  op_index[0] = op_index[1] = op_index[2] = -1;
+
+  the_info = info;
+  start_pc = pc;
+  start_codep = inbuf;
+  codep = inbuf;
+
+#ifndef __KERNEL__
+  if (setjmp (priv.bailout) != 0)
+    {
+      const char *name;
+
+      /* Getting here means we tried for data but didn't get it.  That
+         means we have an incomplete instruction of some sort.  Just
+         print the first byte as a prefix or a .byte pseudo-op.  */
+      if (codep > inbuf)
+	{
+	  name = prefix_name (inbuf[0], orig_sizeflag);
+	  if (name != NULL)
+	    (*info->fprintf_func) (info->stream, "%s", name);
+	  else
+	    {
+	      /* Just print the first byte as a .byte instruction.  */
+	      (*info->fprintf_func) (info->stream, ".byte 0x%x",
+				     (unsigned int) inbuf[0]);
+	    }
+
+	  return 1;
+	}
+
+      return -1;
+    }
+#endif
+
+  ckprefix ();
+
+  insn_codep = codep;
+
+  FETCH_DATA (info, codep + 1);
+  two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
+
+  obufp = obuf;
+
+  if ((prefixes & PREFIX_FWAIT)
+      && ((*codep < 0xd8) || (*codep > 0xdf)))
+    {
+      const char *name;
+
+      /* fwait not followed by floating point instruction.  Print the
+         first prefix, which is probably fwait itself.  */
+      name = prefix_name (inbuf[0], orig_sizeflag);
+      if (name == NULL)
+	name = INTERNAL_DISASSEMBLER_ERROR;
+      (*info->fprintf_func) (info->stream, "%s", name);
+      return 1;
+    }
+
+  if (*codep == 0x0f)
+    {
+      FETCH_DATA (info, codep + 2);
+      if (intel_syntax)
+        dp = &dis386_twobyte_intel[*++codep];
+      else
+        dp = &dis386_twobyte_att[*++codep];
+      need_modrm = twobyte_has_modrm[*codep];
+      uses_f3_prefix = twobyte_uses_f3_prefix[*codep];
+    }
+  else
+    {
+      if (intel_syntax)
+        dp = &dis386_intel[*codep];
+      else
+        dp = &dis386_att[*codep];
+      need_modrm = onebyte_has_modrm[*codep];
+      uses_f3_prefix = 0;
+    }
+  codep++;
+
+  if (!uses_f3_prefix && (prefixes & PREFIX_REPZ))
+    {
+      oappend ("repz ");
+      used_prefixes |= PREFIX_REPZ;
+    }
+  if (prefixes & PREFIX_REPNZ)
+    {
+      oappend ("repnz ");
+      used_prefixes |= PREFIX_REPNZ;
+    }
+  if (prefixes & PREFIX_LOCK)
+    {
+      oappend ("lock ");
+      used_prefixes |= PREFIX_LOCK;
+    }
+
+  if (prefixes & PREFIX_DATA)
+    sizeflag ^= DFLAG;
+
+  if (prefixes & PREFIX_ADDR)
+    {
+      sizeflag ^= AFLAG;
+      if (sizeflag & AFLAG)
+        oappend ("addr32 ");
+      else
+	oappend ("addr16 ");
+      used_prefixes |= PREFIX_ADDR;
+    }
+
+  if (need_modrm)
+    {
+      FETCH_DATA (info, codep + 1);
+      mod = (*codep >> 6) & 3;
+      reg = (*codep >> 3) & 7;
+      rm = *codep & 7;
+    }
+
+  if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
+    {
+      dofloat (sizeflag);
+    }
+  else
+    {
+      if (dp->name == NULL)
+	{
+	  switch(dp->bytemode2)
+	    {
+	      case USE_GROUPS:
+	        dp = &grps[dp->bytemode1][reg];
+		break;
+	      case USE_PREFIX_USER_TABLE:
+		dp = &prefix_user_table[dp->bytemode1][prefixes & PREFIX_REPZ ? 1 : 0];
+		used_prefixes |= (prefixes & PREFIX_REPZ);
+		break;
+	      default:
+		oappend (INTERNAL_DISASSEMBLER_ERROR);
+		break;
+	    }
+	}
+
+      putop (dp->name, sizeflag);
+
+      obufp = op1out;
+      op_ad = 2;
+      if (dp->op1)
+	(*dp->op1)(dp->bytemode1, sizeflag);
+
+      obufp = op2out;
+      op_ad = 1;
+      if (dp->op2)
+	(*dp->op2)(dp->bytemode2, sizeflag);
+
+      obufp = op3out;
+      op_ad = 0;
+      if (dp->op3)
+	(*dp->op3)(dp->bytemode3, sizeflag);
+    }
+
+  /* See if any prefixes were not used.  If so, print the first one
+     separately.  If we don't do this, we'll wind up printing an
+     instruction stream which does not precisely correspond to the
+     bytes we are disassembling.  */
+  if ((prefixes & ~used_prefixes) != 0)
+    {
+      const char *name;
+
+      name = prefix_name (inbuf[0], orig_sizeflag);
+      if (name == NULL)
+	name = INTERNAL_DISASSEMBLER_ERROR;
+      (*info->fprintf_func) (info->stream, "%s", name);
+      return 1;
+    }
+
+  obufp = obuf + strlen (obuf);
+  for (i = strlen (obuf); i < 6; i++)
+    oappend (" ");
+  oappend (" ");
+  (*info->fprintf_func) (info->stream, "%s", obuf);
+
+  /* The enter and bound instructions are printed with operands in the same
+     order as the intel book; everything else is printed in reverse order.  */
+  if (intel_syntax || two_source_ops)
+    {
+      first = op1out;
+      second = op2out;
+      third = op3out;
+      op_ad = op_index[0];
+      op_index[0] = op_index[2];
+      op_index[2] = op_ad;
+    }
+  else
+    {
+      first = op3out;
+      second = op2out;
+      third = op1out;
+    }
+  needcomma = 0;
+  if (*first)
+    {
+      if (op_index[0] != -1)
+	(*info->print_address_func) ((bfd_vma) op_address[op_index[0]], info);
+      else
+	(*info->fprintf_func) (info->stream, "%s", first);
+      needcomma = 1;
+    }
+  if (*second)
+    {
+      if (needcomma)
+	(*info->fprintf_func) (info->stream, ",");
+      if (op_index[1] != -1)
+	(*info->print_address_func) ((bfd_vma) op_address[op_index[1]], info);
+      else
+	(*info->fprintf_func) (info->stream, "%s", second);
+      needcomma = 1;
+    }
+  if (*third)
+    {
+      if (needcomma)
+	(*info->fprintf_func) (info->stream, ",");
+      if (op_index[2] != -1)
+	(*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info);
+      else
+	(*info->fprintf_func) (info->stream, "%s", third);
+    }
+  return codep - inbuf;
+}
+
+static const char *float_mem_att[] = {
+  /* d8 */
+  "fadds",
+  "fmuls",
+  "fcoms",
+  "fcomps",
+  "fsubs",
+  "fsubrs",
+  "fdivs",
+  "fdivrs",
+  /*  d9 */
+  "flds",
+  "(bad)",
+  "fsts",
+  "fstps",
+  "fldenv",
+  "fldcw",
+  "fNstenv",
+  "fNstcw",
+  /* da */
+  "fiaddl",
+  "fimull",
+  "ficoml",
+  "ficompl",
+  "fisubl",
+  "fisubrl",
+  "fidivl",
+  "fidivrl",
+  /* db */
+  "fildl",
+  "(bad)",
+  "fistl",
+  "fistpl",
+  "(bad)",
+  "fldt",
+  "(bad)",
+  "fstpt",
+  /* dc */
+  "faddl",
+  "fmull",
+  "fcoml",
+  "fcompl",
+  "fsubl",
+  "fsubrl",
+  "fdivl",
+  "fdivrl",
+  /* dd */
+  "fldl",
+  "(bad)",
+  "fstl",
+  "fstpl",
+  "frstor",
+  "(bad)",
+  "fNsave",
+  "fNstsw",
+  /* de */
+  "fiadd",
+  "fimul",
+  "ficom",
+  "ficomp",
+  "fisub",
+  "fisubr",
+  "fidiv",
+  "fidivr",
+  /* df */
+  "fild",
+  "(bad)",
+  "fist",
+  "fistp",
+  "fbld",
+  "fildll",
+  "fbstp",
+  "fistpll",
+};
+
+static const char *float_mem_intel[] = {
+  /* d8 */
+  "fadd",
+  "fmul",
+  "fcom",
+  "fcomp",
+  "fsub",
+  "fsubr",
+  "fdiv",
+  "fdivr",
+  /*  d9 */
+  "fld",
+  "(bad)",
+  "fst",
+  "fstp",
+  "fldenv",
+  "fldcw",
+  "fNstenv",
+  "fNstcw",
+  /* da */
+  "fiadd",
+  "fimul",
+  "ficom",
+  "ficomp",
+  "fisub",
+  "fisubr",
+  "fidiv",
+  "fidivr",
+  /* db */
+  "fild",
+  "(bad)",
+  "fist",
+  "fistp",
+  "(bad)",
+  "fld",
+  "(bad)",
+  "fstp",
+  /* dc */
+  "fadd",
+  "fmul",
+  "fcom",
+  "fcomp",
+  "fsub",
+  "fsubr",
+  "fdiv",
+  "fdivr",
+  /* dd */
+  "fld",
+  "(bad)",
+  "fst",
+  "fstp",
+  "frstor",
+  "(bad)",
+  "fNsave",
+  "fNstsw",
+  /* de */
+  "fiadd",
+  "fimul",
+  "ficom",
+  "ficomp",
+  "fisub",
+  "fisubr",
+  "fidiv",
+  "fidivr",
+  /* df */
+  "fild",
+  "(bad)",
+  "fist",
+  "fistp",
+  "fbld",
+  "fild",
+  "fbstp",
+  "fistpll",
+};
+
+#define ST OP_ST, 0
+#define STi OP_STi, 0
+
+#define FGRPd9_2 NULL, NULL, 0, NULL, 0, NULL, 0
+#define FGRPd9_4 NULL, NULL, 1, NULL, 0, NULL, 0
+#define FGRPd9_5 NULL, NULL, 2, NULL, 0, NULL, 0
+#define FGRPd9_6 NULL, NULL, 3, NULL, 0, NULL, 0
+#define FGRPd9_7 NULL, NULL, 4, NULL, 0, NULL, 0
+#define FGRPda_5 NULL, NULL, 5, NULL, 0, NULL, 0
+#define FGRPdb_4 NULL, NULL, 6, NULL, 0, NULL, 0
+#define FGRPde_3 NULL, NULL, 7, NULL, 0, NULL, 0
+#define FGRPdf_4 NULL, NULL, 8, NULL, 0, NULL, 0
+
+static const struct dis386 float_reg[][8] = {
+  /* d8 */
+  {
+    { "fadd",	ST, STi, XX },
+    { "fmul",	ST, STi, XX },
+    { "fcom",	STi, XX, XX },
+    { "fcomp",	STi, XX, XX },
+    { "fsub",	ST, STi, XX },
+    { "fsubr",	ST, STi, XX },
+    { "fdiv",	ST, STi, XX },
+    { "fdivr",	ST, STi, XX },
+  },
+  /* d9 */
+  {
+    { "fld",	STi, XX, XX },
+    { "fxch",	STi, XX, XX },
+    { FGRPd9_2 },
+    { "(bad)",	XX, XX, XX },
+    { FGRPd9_4 },
+    { FGRPd9_5 },
+    { FGRPd9_6 },
+    { FGRPd9_7 },
+  },
+  /* da */
+  {
+    { "fcmovb",	ST, STi, XX },
+    { "fcmove",	ST, STi, XX },
+    { "fcmovbe",ST, STi, XX },
+    { "fcmovu",	ST, STi, XX },
+    { "(bad)",	XX, XX, XX },
+    { FGRPda_5 },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+  },
+  /* db */
+  {
+    { "fcmovnb",ST, STi, XX },
+    { "fcmovne",ST, STi, XX },
+    { "fcmovnbe",ST, STi, XX },
+    { "fcmovnu",ST, STi, XX },
+    { FGRPdb_4 },
+    { "fucomi",	ST, STi, XX },
+    { "fcomi",	ST, STi, XX },
+    { "(bad)",	XX, XX, XX },
+  },
+  /* dc */
+  {
+    { "fadd",	STi, ST, XX },
+    { "fmul",	STi, ST, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+#if UNIXWARE_COMPAT
+    { "fsub",	STi, ST, XX },
+    { "fsubr",	STi, ST, XX },
+    { "fdiv",	STi, ST, XX },
+    { "fdivr",	STi, ST, XX },
+#else
+    { "fsubr",	STi, ST, XX },
+    { "fsub",	STi, ST, XX },
+    { "fdivr",	STi, ST, XX },
+    { "fdiv",	STi, ST, XX },
+#endif
+  },
+  /* dd */
+  {
+    { "ffree",	STi, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "fst",	STi, XX, XX },
+    { "fstp",	STi, XX, XX },
+    { "fucom",	STi, XX, XX },
+    { "fucomp",	STi, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+  },
+  /* de */
+  {
+    { "faddp",	STi, ST, XX },
+    { "fmulp",	STi, ST, XX },
+    { "(bad)",	XX, XX, XX },
+    { FGRPde_3 },
+#if UNIXWARE_COMPAT
+    { "fsubp",	STi, ST, XX },
+    { "fsubrp",	STi, ST, XX },
+    { "fdivp",	STi, ST, XX },
+    { "fdivrp",	STi, ST, XX },
+#else
+    { "fsubrp",	STi, ST, XX },
+    { "fsubp",	STi, ST, XX },
+    { "fdivrp",	STi, ST, XX },
+    { "fdivp",	STi, ST, XX },
+#endif
+  },
+  /* df */
+  {
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { "(bad)",	XX, XX, XX },
+    { FGRPdf_4 },
+    { "fucomip",ST, STi, XX },
+    { "fcomip", ST, STi, XX },
+    { "(bad)",	XX, XX, XX },
+  },
+};
+
+
+static char *fgrps[][8] = {
+  /* d9_2  0 */
+  {
+    "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+
+  /* d9_4  1 */
+  {
+    "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
+  },
+
+  /* d9_5  2 */
+  {
+    "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
+  },
+
+  /* d9_6  3 */
+  {
+    "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
+  },
+
+  /* d9_7  4 */
+  {
+    "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
+  },
+
+  /* da_5  5 */
+  {
+    "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+
+  /* db_4  6 */
+  {
+    "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
+    "fNsetpm(287 only)","(bad)","(bad)","(bad)",
+  },
+
+  /* de_3  7 */
+  {
+    "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+
+  /* df_4  8 */
+  {
+    "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+  },
+};
+
+static void
+dofloat (sizeflag)
+     int sizeflag;
+{
+  const struct dis386 *dp;
+  unsigned char floatop;
+
+  floatop = codep[-1];
+
+  if (mod != 3)
+    {
+      if (intel_syntax)
+        putop (float_mem_intel[(floatop - 0xd8 ) * 8 + reg], sizeflag);
+      else
+        putop (float_mem_att[(floatop - 0xd8 ) * 8 + reg], sizeflag);
+      obufp = op1out;
+      if (floatop == 0xdb)
+        OP_E (x_mode, sizeflag);
+      else if (floatop == 0xdd)
+        OP_E (d_mode, sizeflag);
+      else
+        OP_E (v_mode, sizeflag);
+      return;
+    }
+  codep++;
+
+  dp = &float_reg[floatop - 0xd8][reg];
+  if (dp->name == NULL)
+    {
+      putop (fgrps[dp->bytemode1][rm], sizeflag);
+
+      /* instruction fnstsw is only one with strange arg */
+      if (floatop == 0xdf && codep[-1] == 0xe0)
+	strcpy (op1out, names16[0]);
+    }
+  else
+    {
+      putop (dp->name, sizeflag);
+
+      obufp = op1out;
+      if (dp->op1)
+	(*dp->op1)(dp->bytemode1, sizeflag);
+      obufp = op2out;
+      if (dp->op2)
+	(*dp->op2)(dp->bytemode2, sizeflag);
+    }
+}
+
+/* ARGSUSED */
+static void
+OP_ST (ignore, sizeflag)
+     int ignore ATTRIBUTE_UNUSED;
+     int sizeflag ATTRIBUTE_UNUSED;
+{
+  oappend ("%st");
+}
+
+/* ARGSUSED */
+static void
+OP_STi (ignore, sizeflag)
+     int ignore ATTRIBUTE_UNUSED;
+     int sizeflag ATTRIBUTE_UNUSED;
+{
+  sprintf (scratchbuf, "%%st(%d)", rm);
+  oappend (scratchbuf);
+}
+
+
+/* capital letters in template are macros */
+static void
+putop (template, sizeflag)
+     const char *template;
+     int sizeflag;
+{
+  const char *p;
+
+  for (p = template; *p; p++)
+    {
+      switch (*p)
+	{
+	default:
+	  *obufp++ = *p;
+	  break;
+	case 'A':
+          if (intel_syntax)
+            break;
+	  if (mod != 3
+#ifdef SUFFIX_ALWAYS
+	      || (sizeflag & SUFFIX_ALWAYS)
+#endif
+	      )
+	    *obufp++ = 'b';
+	  break;
+	case 'B':
+          if (intel_syntax)
+            break;
+#ifdef SUFFIX_ALWAYS
+	  if (sizeflag & SUFFIX_ALWAYS)
+	    *obufp++ = 'b';
+#endif
+	  break;
+	case 'E':		/* For jcxz/jecxz */
+	  if (sizeflag & AFLAG)
+	    *obufp++ = 'e';
+	  break;
+	case 'L':
+          if (intel_syntax)
+            break;
+#ifdef SUFFIX_ALWAYS
+	  if (sizeflag & SUFFIX_ALWAYS)
+	    *obufp++ = 'l';
+#endif
+	  break;
+	case 'N':
+	  if ((prefixes & PREFIX_FWAIT) == 0)
+	    *obufp++ = 'n';
+	  else
+	    used_prefixes |= PREFIX_FWAIT;
+	  break;
+	case 'P':
+          if (intel_syntax)
+            break;
+	  if ((prefixes & PREFIX_DATA)
+#ifdef SUFFIX_ALWAYS
+	      || (sizeflag & SUFFIX_ALWAYS)
+#endif
+	      )
+	    {
+	      if (sizeflag & DFLAG)
+		*obufp++ = 'l';
+	      else
+		*obufp++ = 'w';
+	      used_prefixes |= (prefixes & PREFIX_DATA);
+	    }
+	  break;
+	case 'Q':
+          if (intel_syntax)
+            break;
+	  if (mod != 3
+#ifdef SUFFIX_ALWAYS
+	      || (sizeflag & SUFFIX_ALWAYS)
+#endif
+	      )
+	    {
+	      if (sizeflag & DFLAG)
+		*obufp++ = 'l';
+	      else
+		*obufp++ = 'w';
+	      used_prefixes |= (prefixes & PREFIX_DATA);
+	    }
+	  break;
+	case 'R':
+          if (intel_syntax)
+	    {
+	      if (sizeflag & DFLAG)
+		{
+		  *obufp++ = 'd';
+		  *obufp++ = 'q';
+		}
+	      else
+		{
+		  *obufp++ = 'w';
+		  *obufp++ = 'd';
+		}
+	    }
+	  else
+	    {
+	      if (sizeflag & DFLAG)
+		*obufp++ = 'l';
+	      else
+		*obufp++ = 'w';
+	    }
+	  used_prefixes |= (prefixes & PREFIX_DATA);
+	  break;
+	case 'S':
+          if (intel_syntax)
+            break;
+#ifdef SUFFIX_ALWAYS
+	  if (sizeflag & SUFFIX_ALWAYS)
+	    {
+	      if (sizeflag & DFLAG)
+		*obufp++ = 'l';
+	      else
+		*obufp++ = 'w';
+	      used_prefixes |= (prefixes & PREFIX_DATA);
+	    }
+#endif
+	  break;
+	case 'W':
+	  /* operand size flag for cwtl, cbtw */
+	  if (sizeflag & DFLAG)
+	    *obufp++ = 'w';
+	  else
+	    *obufp++ = 'b';
+          if (intel_syntax)
+	    {
+	      if (sizeflag & DFLAG)
+		{
+		  *obufp++ = 'd';
+		  *obufp++ = 'e';
+		}
+	      else
+		{
+		  *obufp++ = 'w';
+		}
+	    }
+	  used_prefixes |= (prefixes & PREFIX_DATA);
+	  break;
+	}
+    }
+  *obufp = 0;
+}
+
+static void
+oappend (s)
+     const char *s;
+{
+  strcpy (obufp, s);
+  obufp += strlen (s);
+}
+
+static void
+append_seg ()
+{
+  if (prefixes & PREFIX_CS)
+    {
+      oappend ("%cs:");
+      used_prefixes |= PREFIX_CS;
+    }
+  if (prefixes & PREFIX_DS)
+    {
+      oappend ("%ds:");
+      used_prefixes |= PREFIX_DS;
+    }
+  if (prefixes & PREFIX_SS)
+    {
+      oappend ("%ss:");
+      used_prefixes |= PREFIX_SS;
+    }
+  if (prefixes & PREFIX_ES)
+    {
+      oappend ("%es:");
+      used_prefixes |= PREFIX_ES;
+    }
+  if (prefixes & PREFIX_FS)
+    {
+      oappend ("%fs:");
+      used_prefixes |= PREFIX_FS;
+    }
+  if (prefixes & PREFIX_GS)
+    {
+      oappend ("%gs:");
+      used_prefixes |= PREFIX_GS;
+    }
+}
+
+static void
+OP_indirE (bytemode, sizeflag)
+     int bytemode;
+     int sizeflag;
+{
+  if (!intel_syntax)
+    oappend ("*");
+  OP_E (bytemode, sizeflag);
+}
+
+static void
+OP_E (bytemode, sizeflag)
+     int bytemode;
+     int sizeflag;
+{
+  int disp;
+
+  /* skip mod/rm byte */
+  codep++;
+
+  if (mod == 3)
+    {
+      switch (bytemode)
+	{
+	case b_mode:
+	  oappend (names8[rm]);
+	  break;
+	case w_mode:
+	  oappend (names16[rm]);
+	  break;
+	case d_mode:
+	  oappend (names32[rm]);
+	  break;
+	case v_mode:
+	  if (sizeflag & DFLAG)
+	    oappend (names32[rm]);
+	  else
+	    oappend (names16[rm]);
+	  used_prefixes |= (prefixes & PREFIX_DATA);
+	  break;
+	case 0:
+	  if ( !(codep[-2] == 0xAE && codep[-1] == 0xF8 /* sfence */))
+	    BadOp();	/* bad sfence,lea,lds,les,lfs,lgs,lss modrm */
+	  break;
+	default:
+	  oappend (INTERNAL_DISASSEMBLER_ERROR);
+	  break;
+	}
+      return;
+    }
+
+  disp = 0;
+  append_seg ();
+
+  if (sizeflag & AFLAG) /* 32 bit address mode */
+    {
+      int havesib;
+      int havebase;
+      int base;
+      int index = 0;
+      int scale = 0;
+
+      havesib = 0;
+      havebase = 1;
+      base = rm;
+
+      if (base == 4)
+	{
+	  havesib = 1;
+	  FETCH_DATA (the_info, codep + 1);
+	  scale = (*codep >> 6) & 3;
+	  index = (*codep >> 3) & 7;
+	  base = *codep & 7;
+	  codep++;
+	}
+
+      switch (mod)
+	{
+	case 0:
+	  if (base == 5)
+	    {
+	      havebase = 0;
+	      disp = get32 ();
+	    }
+	  break;
+	case 1:
+	  FETCH_DATA (the_info, codep + 1);
+	  disp = *codep++;
+	  if ((disp & 0x80) != 0)
+	    disp -= 0x100;
+	  break;
+	case 2:
+	  disp = get32 ();
+	  break;
+	}
+
+      if (!intel_syntax)
+        if (mod != 0 || base == 5)
+          {
+            sprintf (scratchbuf, "0x%x", disp);
+            oappend (scratchbuf);
+          }
+
+      if (havebase || (havesib && (index != 4 || scale != 0)))
+	{
+          if (intel_syntax)
+            {
+              switch (bytemode)
+                {
+                case b_mode:
+                  oappend("BYTE PTR ");
+                  break;
+                case w_mode:
+                  oappend("WORD PTR ");
+                  break;
+                case v_mode:
+                  oappend("DWORD PTR ");
+                  break;
+                case d_mode:
+                  oappend("QWORD PTR ");
+                  break;
+                case x_mode:
+                  oappend("XWORD PTR ");
+                  break;
+                default:
+                  break;
+                }
+             }
+	  *obufp++ = open_char;
+          *obufp = '\0';
+	  if (havebase)
+	    oappend (names32[base]);
+	  if (havesib)
+	    {
+	      if (index != 4)
+		{
+                  if (intel_syntax)
+                    {
+                      if (havebase)
+                        {
+                          *obufp++ = separator_char;
+                          *obufp = '\0';
+                        }
+                      sprintf (scratchbuf, "%s", names32[index]);
+                    }
+                  else
+		    sprintf (scratchbuf, ",%s", names32[index]);
+		  oappend (scratchbuf);
+		}
+              if (!intel_syntax
+                  || (intel_syntax
+                      && bytemode != b_mode
+                      && bytemode != w_mode
+                      && bytemode != v_mode))
+                {
+                  *obufp++ = scale_char;
+                  *obufp = '\0';
+	          sprintf (scratchbuf, "%d", 1 << scale);
+	          oappend (scratchbuf);
+                }
+	    }
+          if (intel_syntax)
+            if (mod != 0 || base == 5)
+              {
+                /* Don't print zero displacements */
+                if (disp > 0)
+                  {
+                    sprintf (scratchbuf, "+%d", disp);
+                    oappend (scratchbuf);
+                  }
+                else if (disp < 0)
+                  {
+                    sprintf (scratchbuf, "%d", disp);
+                    oappend (scratchbuf);
+                  }
+              }
+
+	  *obufp++ = close_char;
+          *obufp = '\0';
+	}
+      else if (intel_syntax)
+        {
+          if (mod != 0 || base == 5)
+            {
+	      if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+			      | PREFIX_ES | PREFIX_FS | PREFIX_GS))
+		;
+	      else
+		{
+		  oappend (names_seg[3]);
+		  oappend (":");
+		}
+              sprintf (scratchbuf, "0x%x", disp);
+              oappend (scratchbuf);
+            }
+        }
+    }
+  else
+    { /* 16 bit address mode */
+      switch (mod)
+	{
+	case 0:
+	  if (rm == 6)
+	    {
+	      disp = get16 ();
+	      if ((disp & 0x8000) != 0)
+		disp -= 0x10000;
+	    }
+	  break;
+	case 1:
+	  FETCH_DATA (the_info, codep + 1);
+	  disp = *codep++;
+	  if ((disp & 0x80) != 0)
+	    disp -= 0x100;
+	  break;
+	case 2:
+	  disp = get16 ();
+	  if ((disp & 0x8000) != 0)
+	    disp -= 0x10000;
+	  break;
+	}
+
+      if (!intel_syntax)
+        if (mod != 0 || rm == 6)
+          {
+            sprintf (scratchbuf, "%d", disp);
+            oappend (scratchbuf);
+          }
+
+      if (mod != 0 || rm != 6)
+	{
+	  *obufp++ = open_char;
+          *obufp = '\0';
+	  oappend (index16[rm]);
+          *obufp++ = close_char;
+          *obufp = '\0';
+	}
+    }
+}
+
+static void
+OP_G (bytemode, sizeflag)
+     int bytemode;
+     int sizeflag;
+{
+  switch (bytemode)
+    {
+    case b_mode:
+      oappend (names8[reg]);
+      break;
+    case w_mode:
+      oappend (names16[reg]);
+      break;
+    case d_mode:
+      oappend (names32[reg]);
+      break;
+    case v_mode:
+      if (sizeflag & DFLAG)
+	oappend (names32[reg]);
+      else
+	oappend (names16[reg]);
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      break;
+    }
+}
+
+static int
+get32 ()
+{
+  int x = 0;
+
+  FETCH_DATA (the_info, codep + 4);
+  x = *codep++ & 0xff;
+  x |= (*codep++ & 0xff) << 8;
+  x |= (*codep++ & 0xff) << 16;
+  x |= (*codep++ & 0xff) << 24;
+  return x;
+}
+
+static int
+get16 ()
+{
+  int x = 0;
+
+  FETCH_DATA (the_info, codep + 2);
+  x = *codep++ & 0xff;
+  x |= (*codep++ & 0xff) << 8;
+  return x;
+}
+
+static void
+set_op (op)
+     unsigned int op;
+{
+  op_index[op_ad] = op_ad;
+  op_address[op_ad] = op;
+}
+
+static void
+OP_REG (code, sizeflag)
+     int code;
+     int sizeflag;
+{
+  const char *s;
+
+  switch (code)
+    {
+    case indir_dx_reg:
+      s = "(%dx)";
+      break;
+    case ax_reg: case cx_reg: case dx_reg: case bx_reg:
+    case sp_reg: case bp_reg: case si_reg: case di_reg:
+      s = names16[code - ax_reg];
+      break;
+    case es_reg: case ss_reg: case cs_reg:
+    case ds_reg: case fs_reg: case gs_reg:
+      s = names_seg[code - es_reg];
+      break;
+    case al_reg: case ah_reg: case cl_reg: case ch_reg:
+    case dl_reg: case dh_reg: case bl_reg: case bh_reg:
+      s = names8[code - al_reg];
+      break;
+    case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+    case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+      if (sizeflag & DFLAG)
+	s = names32[code - eAX_reg];
+      else
+	s = names16[code - eAX_reg];
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    default:
+      s = INTERNAL_DISASSEMBLER_ERROR;
+      break;
+    }
+  oappend (s);
+}
+
+static void
+OP_I (bytemode, sizeflag)
+     int bytemode;
+     int sizeflag;
+{
+  int op;
+
+  switch (bytemode)
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      op = *codep++ & 0xff;
+      break;
+    case v_mode:
+      if (sizeflag & DFLAG)
+	op = get32 ();
+      else
+	op = get16 ();
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    case w_mode:
+      op = get16 ();
+      break;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      return;
+    }
+
+  if (intel_syntax)
+    sprintf (scratchbuf, "0x%x", op);
+  else
+    sprintf (scratchbuf, "$0x%x", op);
+  oappend (scratchbuf);
+  scratchbuf[0] = '\0';
+}
+
+static void
+OP_sI (bytemode, sizeflag)
+     int bytemode;
+     int sizeflag;
+{
+  int op;
+
+  switch (bytemode)
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      op = *codep++;
+      if ((op & 0x80) != 0)
+	op -= 0x100;
+      break;
+    case v_mode:
+      if (sizeflag & DFLAG)
+	op = get32 ();
+      else
+	{
+	  op = get16();
+	  if ((op & 0x8000) != 0)
+	    op -= 0x10000;
+	}
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    case w_mode:
+      op = get16 ();
+      if ((op & 0x8000) != 0)
+	op -= 0x10000;
+      break;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      return;
+    }
+  if (intel_syntax)
+    sprintf (scratchbuf, "%d", op);
+  else
+    sprintf (scratchbuf, "$0x%x", op);
+  oappend (scratchbuf);
+}
+
+static void
+OP_J (bytemode, sizeflag)
+     int bytemode;
+     int sizeflag;
+{
+  int disp;
+  int mask = -1;
+
+  switch (bytemode)
+    {
+    case b_mode:
+      FETCH_DATA (the_info, codep + 1);
+      disp = *codep++;
+      if ((disp & 0x80) != 0)
+	disp -= 0x100;
+      break;
+    case v_mode:
+      if (sizeflag & DFLAG)
+	disp = get32 ();
+      else
+	{
+	  disp = get16 ();
+	  /* for some reason, a data16 prefix on a jump instruction
+	     means that the pc is masked to 16 bits after the
+	     displacement is added!  */
+	  mask = 0xffff;
+	}
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      return;
+    }
+  disp = (start_pc + codep - start_codep + disp) & mask;
+  set_op (disp);
+  sprintf (scratchbuf, "0x%x", disp);
+  oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+static void
+OP_SEG (dummy, sizeflag)
+     int dummy ATTRIBUTE_UNUSED;
+     int sizeflag ATTRIBUTE_UNUSED;
+{
+  static char *sreg[] = {
+    "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+  };
+
+  oappend (sreg[reg]);
+}
+
+/* ARGSUSED */
+static void
+OP_DIR (dummy, sizeflag)
+     int dummy ATTRIBUTE_UNUSED;
+     int sizeflag;
+{
+  int seg, offset;
+
+  if (sizeflag & DFLAG)
+    {
+      offset = get32 ();
+      seg = get16 ();
+    }
+  else
+    {
+      offset = get16 ();
+      seg = get16 ();
+    }
+  used_prefixes |= (prefixes & PREFIX_DATA);
+  sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset);
+  oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+static void
+OP_OFF (ignore, sizeflag)
+     int ignore ATTRIBUTE_UNUSED;
+     int sizeflag;
+{
+  int off;
+
+  append_seg ();
+
+  if (sizeflag & AFLAG)
+    off = get32 ();
+  else
+    off = get16 ();
+
+  if (intel_syntax)
+    {
+      if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+		        | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
+	{
+	  oappend (names_seg[3]);
+	  oappend (":");
+	}
+    }
+  sprintf (scratchbuf, "0x%x", off);
+  oappend (scratchbuf);
+}
+
+static void
+ptr_reg (code, sizeflag)
+     int code;
+     int sizeflag;
+{
+  const char *s;
+  oappend ("(");
+  if (sizeflag & AFLAG)
+    s = names32[code - eAX_reg];
+  else
+    s = names16[code - eAX_reg];
+  oappend (s);
+  oappend (")");
+}
+
+static void
+OP_ESreg (code, sizeflag)
+     int code;
+     int sizeflag;
+{
+  oappend ("%es:");
+  ptr_reg (code, sizeflag);
+}
+
+static void
+OP_DSreg (code, sizeflag)
+     int code;
+     int sizeflag;
+{
+  if ((prefixes
+       & (PREFIX_CS
+	  | PREFIX_DS
+	  | PREFIX_SS
+	  | PREFIX_ES
+	  | PREFIX_FS
+	  | PREFIX_GS)) == 0)
+    prefixes |= PREFIX_DS;
+  append_seg();
+  ptr_reg (code, sizeflag);
+}
+
+/* ARGSUSED */
+static void
+OP_C (dummy, sizeflag)
+     int dummy ATTRIBUTE_UNUSED;
+     int sizeflag ATTRIBUTE_UNUSED;
+{
+  sprintf (scratchbuf, "%%cr%d", reg);
+  oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+static void
+OP_D (dummy, sizeflag)
+     int dummy ATTRIBUTE_UNUSED;
+     int sizeflag ATTRIBUTE_UNUSED;
+{
+  sprintf (scratchbuf, "%%db%d", reg);
+  oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+static void
+OP_T (dummy, sizeflag)
+     int dummy ATTRIBUTE_UNUSED;
+     int sizeflag ATTRIBUTE_UNUSED;
+{
+  sprintf (scratchbuf, "%%tr%d", reg);
+  oappend (scratchbuf);
+}
+
+static void
+OP_Rd (bytemode, sizeflag)
+     int bytemode;
+     int sizeflag;
+{
+  if (mod == 3)
+    OP_E (bytemode, sizeflag);
+  else
+    BadOp();
+}
+
+static void
+OP_MMX (ignore, sizeflag)
+     int ignore ATTRIBUTE_UNUSED;
+     int sizeflag ATTRIBUTE_UNUSED;
+{
+  sprintf (scratchbuf, "%%mm%d", reg);
+  oappend (scratchbuf);
+}
+
+static void
+OP_XMM (bytemode, sizeflag)
+     int bytemode ATTRIBUTE_UNUSED;
+     int sizeflag ATTRIBUTE_UNUSED;
+{
+  sprintf (scratchbuf, "%%xmm%d", reg);
+  oappend (scratchbuf);
+}
+
+static void
+OP_EM (bytemode, sizeflag)
+     int bytemode;
+     int sizeflag;
+{
+  if (mod != 3)
+    {
+      OP_E (bytemode, sizeflag);
+      return;
+    }
+
+  codep++;
+  sprintf (scratchbuf, "%%mm%d", rm);
+  oappend (scratchbuf);
+}
+
+static void
+OP_EX (bytemode, sizeflag)
+     int bytemode;
+     int sizeflag;
+{
+  if (mod != 3)
+    {
+      OP_E (bytemode, sizeflag);
+      return;
+    }
+
+  codep++;
+  sprintf (scratchbuf, "%%xmm%d", rm);
+  oappend (scratchbuf);
+}
+
+static void
+OP_MS (bytemode, sizeflag)
+     int bytemode;
+     int sizeflag;
+{
+  if (mod == 3)
+    OP_EM (bytemode, sizeflag);
+  else
+    BadOp();
+}
+
+static const char *Suffix3DNow[] = {
+/* 00 */	NULL,		NULL,		NULL,		NULL,
+/* 04 */	NULL,		NULL,		NULL,		NULL,
+/* 08 */	NULL,		NULL,		NULL,		NULL,
+/* 0C */	"pi2fw",	"pi2fd",	NULL,		NULL,
+/* 10 */	NULL,		NULL,		NULL,		NULL,
+/* 14 */	NULL,		NULL,		NULL,		NULL,
+/* 18 */	NULL,		NULL,		NULL,		NULL,
+/* 1C */	"pf2iw",	"pf2id",	NULL,		NULL,
+/* 20 */	NULL,		NULL,		NULL,		NULL,
+/* 24 */	NULL,		NULL,		NULL,		NULL,
+/* 28 */	NULL,		NULL,		NULL,		NULL,
+/* 2C */	NULL,		NULL,		NULL,		NULL,
+/* 30 */	NULL,		NULL,		NULL,		NULL,
+/* 34 */	NULL,		NULL,		NULL,		NULL,
+/* 38 */	NULL,		NULL,		NULL,		NULL,
+/* 3C */	NULL,		NULL,		NULL,		NULL,
+/* 40 */	NULL,		NULL,		NULL,		NULL,
+/* 44 */	NULL,		NULL,		NULL,		NULL,
+/* 48 */	NULL,		NULL,		NULL,		NULL,
+/* 4C */	NULL,		NULL,		NULL,		NULL,
+/* 50 */	NULL,		NULL,		NULL,		NULL,
+/* 54 */	NULL,		NULL,		NULL,		NULL,
+/* 58 */	NULL,		NULL,		NULL,		NULL,
+/* 5C */	NULL,		NULL,		NULL,		NULL,
+/* 60 */	NULL,		NULL,		NULL,		NULL,
+/* 64 */	NULL,		NULL,		NULL,		NULL,
+/* 68 */	NULL,		NULL,		NULL,		NULL,
+/* 6C */	NULL,		NULL,		NULL,		NULL,
+/* 70 */	NULL,		NULL,		NULL,		NULL,
+/* 74 */	NULL,		NULL,		NULL,		NULL,
+/* 78 */	NULL,		NULL,		NULL,		NULL,
+/* 7C */	NULL,		NULL,		NULL,		NULL,
+/* 80 */	NULL,		NULL,		NULL,		NULL,
+/* 84 */	NULL,		NULL,		NULL,		NULL,
+/* 88 */	NULL,		NULL,		"pfnacc",	NULL,
+/* 8C */	NULL,		NULL,		"pfpnacc",	NULL,
+/* 90 */	"pfcmpge",	NULL,		NULL,		NULL,
+/* 94 */	"pfmin",	NULL,		"pfrcp",	"pfrsqrt",
+/* 98 */	NULL,		NULL,		"pfsub",	NULL,
+/* 9C */	NULL,		NULL,		"pfadd",	NULL,
+/* A0 */	"pfcmpgt",	NULL,		NULL,		NULL,
+/* A4 */	"pfmax",	NULL,		"pfrcpit1",	"pfrsqit1",
+/* A8 */	NULL,		NULL,		"pfsubr",	NULL,
+/* AC */	NULL,		NULL,		"pfacc",	NULL,
+/* B0 */	"pfcmpeq",	NULL,		NULL,		NULL,
+/* B4 */	"pfmul",	NULL,		"pfrcpit2",	"pfmulhrw",
+/* B8 */	NULL,		NULL,		NULL,		"pswapd",
+/* BC */	NULL,		NULL,		NULL,		"pavgusb",
+/* C0 */	NULL,		NULL,		NULL,		NULL,
+/* C4 */	NULL,		NULL,		NULL,		NULL,
+/* C8 */	NULL,		NULL,		NULL,		NULL,
+/* CC */	NULL,		NULL,		NULL,		NULL,
+/* D0 */	NULL,		NULL,		NULL,		NULL,
+/* D4 */	NULL,		NULL,		NULL,		NULL,
+/* D8 */	NULL,		NULL,		NULL,		NULL,
+/* DC */	NULL,		NULL,		NULL,		NULL,
+/* E0 */	NULL,		NULL,		NULL,		NULL,
+/* E4 */	NULL,		NULL,		NULL,		NULL,
+/* E8 */	NULL,		NULL,		NULL,		NULL,
+/* EC */	NULL,		NULL,		NULL,		NULL,
+/* F0 */	NULL,		NULL,		NULL,		NULL,
+/* F4 */	NULL,		NULL,		NULL,		NULL,
+/* F8 */	NULL,		NULL,		NULL,		NULL,
+/* FC */	NULL,		NULL,		NULL,		NULL,
+};
+
+static void
+OP_3DNowSuffix (bytemode, sizeflag)
+     int bytemode ATTRIBUTE_UNUSED;
+     int sizeflag ATTRIBUTE_UNUSED;
+{
+  const char *mnemonic;
+
+  FETCH_DATA (the_info, codep + 1);
+  /* AMD 3DNow! instructions are specified by an opcode suffix in the
+     place where an 8-bit immediate would normally go.  ie. the last
+     byte of the instruction.  */
+  obufp = obuf + strlen(obuf);
+  mnemonic = Suffix3DNow[*codep++ & 0xff];
+  if (mnemonic)
+    oappend (mnemonic);
+  else
+    {
+      /* Since a variable sized modrm/sib chunk is between the start
+	 of the opcode (0x0f0f) and the opcode suffix, we need to do
+	 all the modrm processing first, and don't know until now that
+	 we have a bad opcode.  This necessitates some cleaning up.  */
+      op1out[0] = '\0';
+      op2out[0] = '\0';
+      BadOp();
+    }
+}
+
+
+static const char *simd_cmp_op [] = {
+  "eq",
+  "lt",
+  "le",
+  "unord",
+  "neq",
+  "nlt",
+  "nle",
+  "ord"
+};
+
+static void
+OP_SIMD_Suffix (bytemode, sizeflag)
+     int bytemode ATTRIBUTE_UNUSED;
+     int sizeflag ATTRIBUTE_UNUSED;
+{
+  unsigned int cmp_type;
+
+  FETCH_DATA (the_info, codep + 1);
+  obufp = obuf + strlen(obuf);
+  cmp_type = *codep++ & 0xff;
+  if (cmp_type < 8)
+    {
+      sprintf (scratchbuf, "cmp%s%cs",
+	       simd_cmp_op[cmp_type],
+	       prefixes & PREFIX_REPZ ? 's' : 'p');
+      used_prefixes |= (prefixes & PREFIX_REPZ);
+      oappend (scratchbuf);
+    }
+  else
+    {
+      /* We have a bad extension byte.  Clean up.  */
+      op1out[0] = '\0';
+      op2out[0] = '\0';
+      BadOp();
+    }
+}
+
+static void
+SIMD_Fixup (extrachar, sizeflag)
+     int extrachar;
+     int sizeflag ATTRIBUTE_UNUSED;
+{
+  /* Change movlps/movhps to movhlps/movlhps for 2 register operand
+     forms of these instructions.  */
+  if (mod == 3)
+    {
+      char *p = obuf + strlen(obuf);
+      *(p+1) = '\0';
+      *p     = *(p-1);
+      *(p-1) = *(p-2);
+      *(p-2) = *(p-3);
+      *(p-3) = extrachar;
+    }
+}
+
+static void BadOp (void)
+{
+  codep = insn_codep + 1;	/* throw away prefixes and 1st. opcode byte */
+  oappend ("(bad)");
+}
Index: 2.4.x-xfs/arch/i386/kdb/kdba_bp.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kdb/kdba_bp.c	Thu Jan  1 10:00:00 1970
+++ 2.4.x-xfs/arch/i386/kdb/kdba_bp.c	Mon Aug  9 13:54:51 2004
@@ -0,0 +1,804 @@
+/*
+ * Kernel Debugger Architecture Dependent Breakpoint Handling
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/ptrace.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+
+
+static char *kdba_rwtypes[] = { "Instruction(Register)", "Data Write",
+			"I/O", "Data Access"};
+
+/*
+ * Table describing processor architecture hardware
+ * breakpoint registers.
+ */
+
+kdbhard_bp_t	kdb_hardbreaks[KDB_MAXHARDBPT];
+
+/*
+ * kdba_db_trap
+ *
+ * 	Perform breakpoint processing upon entry to the
+ *	processor debugger fault.   Determine and print
+ *	the active breakpoint.
+ *
+ * Parameters:
+ *	regs	Exception frame containing machine register state
+ *	error	Error number passed to kdb.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	KDB_DB_BPT	Standard instruction or data breakpoint encountered
+ *	KDB_DB_SS	Single Step fault ('ss' command or end of 'ssb' command)
+ *	KDB_DB_SSB	Single Step fault, caller should continue ('ssb' command)
+ *	KDB_DB_SSBPT	Single step over breakpoint
+ *	KDB_DB_NOBPT	No existing kdb breakpoint matches this debug exception
+ * Locking:
+ *	None.
+ * Remarks:
+ *	Yup, there be goto's here.
+ *
+ *	If multiple processors receive debug exceptions simultaneously,
+ *	one may be waiting at the kdb fence in kdb() while the user
+ *	issues a 'bc' command to clear the breakpoint the processor
+ *	which is waiting has already encountered.  If this is the case,
+ *	the debug registers will no longer match any entry in the
+ *	breakpoint table, and we'll return the value KDB_DB_NOBPT.
+ *	This can cause a panic in die_if_kernel().  It is safer to
+ *	disable the breakpoint (bd), go until all processors are past
+ *	the breakpoint then clear the breakpoint (bc).  This code
+ *	recognises a breakpoint even when disabled but not when it has
+ *	been cleared.
+ *
+ *	WARNING: This routine clears the debug state.  It should be called
+ *		 once per debug and the result cached.
+ */
+
+kdb_dbtrap_t
+kdba_db_trap(struct pt_regs *regs, int error_unused)
+{
+	kdb_machreg_t  dr6;
+	kdb_machreg_t  dr7;
+	int rw, reg;
+	int i;
+	kdb_dbtrap_t rv = KDB_DB_BPT;
+	kdb_bp_t *bp;
+
+	if (KDB_NULL_REGS(regs))
+		return KDB_DB_NOBPT;
+
+	dr6 = kdba_getdr6();
+	dr7 = kdba_getdr7();
+
+	if (KDB_DEBUG(BP))
+		kdb_printf("kdb: dr6 0x%lx dr7 0x%lx\n", dr6, dr7);
+	if (dr6 & DR6_BS) {
+		if (KDB_STATE(SSBPT)) {
+			if (KDB_DEBUG(BP))
+				kdb_printf("ssbpt\n");
+			KDB_STATE_CLEAR(SSBPT);
+			for(i=0,bp=kdb_breakpoints;
+			    i < KDB_MAXBPT;
+			    i++, bp++) {
+				if (KDB_DEBUG(BP))
+					kdb_printf("bp 0x%p enabled %d delayed %d global %d cpu %d\n",
+						   bp, bp->bp_enabled, bp->bp_delayed, bp->bp_global, bp->bp_cpu);
+				if (!bp->bp_enabled)
+					continue;
+				if (!bp->bp_global && bp->bp_cpu != smp_processor_id())
+					continue;
+				if (KDB_DEBUG(BP))
+					kdb_printf("bp for this cpu\n");
+				if (bp->bp_delayed) {
+					bp->bp_delayed = 0;
+					if (KDB_DEBUG(BP))
+						kdb_printf("kdba_installbp\n");
+					kdba_installbp(regs, bp);
+					if (!KDB_STATE(DOING_SS)) {
+						regs->eflags &= ~EF_TF;
+						return(KDB_DB_SSBPT);
+					}
+					break;
+				}
+			}
+			if (i == KDB_MAXBPT) {
+				kdb_printf("kdb: Unable to find delayed breakpoint\n");
+			}
+			if (!KDB_STATE(DOING_SS)) {
+				regs->eflags &= ~EF_TF;
+				return(KDB_DB_NOBPT);
+			}
+			/* FALLTHROUGH */
+		}
+
+		/*
+		 * KDB_STATE_DOING_SS is set when the kernel debugger is using
+		 * the processor trap flag to single-step a processor.  If a
+		 * single step trap occurs and this flag is clear, the SS trap
+		 * will be ignored by KDB and the kernel will be allowed to deal
+		 * with it as necessary (e.g. for ptrace).
+		 */
+		if (!KDB_STATE(DOING_SS))
+			goto unknown;
+
+		/* single step */
+		rv = KDB_DB_SS;		/* Indicate single step */
+		if (KDB_STATE(DOING_SSB)) {
+			unsigned char instruction[2];
+
+			kdb_id1(regs->eip);
+			if (kdb_getarea(instruction, regs->eip) ||
+			    (instruction[0]&0xf0) == 0xe0 ||	/* short disp jumps */
+			    (instruction[0]&0xf0) == 0x70 ||	/* Misc. jumps */
+			    instruction[0]        == 0xc2 ||	/* ret */
+			    instruction[0]        == 0x9a ||	/* call */
+			    (instruction[0]&0xf8) == 0xc8 ||	/* enter, leave, iret, int, */
+			    ((instruction[0]      == 0x0f) &&
+			     ((instruction[1]&0xf0)== 0x80))
+			   ) {
+				/*
+				 * End the ssb command here.
+				 */
+				KDB_STATE_CLEAR(DOING_SSB);
+				KDB_STATE_CLEAR(DOING_SS);
+			} else {
+				rv = KDB_DB_SSB; /* Indicate ssb - dismiss immediately */
+			}
+		} else {
+			/*
+			 * Print current insn
+			 */
+			kdb_printf("SS trap at ");
+			kdb_symbol_print(regs->eip, NULL, KDB_SP_DEFAULT|KDB_SP_NEWLINE);
+			kdb_id1(regs->eip);
+			KDB_STATE_CLEAR(DOING_SS);
+		}
+
+		if (rv != KDB_DB_SSB)
+			regs->eflags &= ~EF_TF;
+	}
+
+	if (dr6 & DR6_B0) {
+		rw = DR7_RW0(dr7);
+		reg = 0;
+		goto handle;
+	}
+
+	if (dr6 & DR6_B1) {
+		rw = DR7_RW1(dr7);
+		reg = 1;
+		goto handle;
+	}
+
+	if (dr6 & DR6_B2) {
+		rw = DR7_RW2(dr7);
+		reg = 2;
+		goto handle;
+	}
+
+	if (dr6 & DR6_B3) {
+		rw = DR7_RW3(dr7);
+		reg = 3;
+		goto handle;
+	}
+
+	if (rv > 0)
+		goto handled;
+
+	goto unknown;	/* dismiss */
+
+handle:
+	/*
+	 * Set Resume Flag
+	 */
+	regs->eflags |= EF_RF;
+
+	/*
+	 * Determine which breakpoint was encountered.
+	 */
+	for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) {
+		if (!(bp->bp_free)
+		 && (bp->bp_global || bp->bp_cpu == smp_processor_id())
+		 && (bp->bp_hard)
+		 && (bp->bp_hard->bph_reg == reg)) {
+			/*
+			 * Hit this breakpoint.
+			 */
+			kdb_printf("%s breakpoint #%d at " kdb_bfd_vma_fmt "\n",
+				  kdba_rwtypes[rw],
+				  i, bp->bp_addr);
+
+			/*
+			 * For an instruction breakpoint, disassemble
+			 * the current instruction.
+			 */
+			if (rw == 0) {
+				kdb_id1(regs->eip);
+			}
+
+			goto handled;
+		}
+	}
+
+unknown:
+	regs->eflags |= EF_RF;	/* Supress further faults */
+	rv = KDB_DB_NOBPT;	/* Cause kdb() to return */
+
+handled:
+
+	/*
+	 * Clear the pending exceptions.
+	 */
+	kdba_putdr6(0);
+
+	return rv;
+}
+
+/*
+ * kdba_bp_trap
+ *
+ * 	Perform breakpoint processing upon entry to the
+ *	processor breakpoint instruction fault.   Determine and print
+ *	the active breakpoint.
+ *
+ * Parameters:
+ *	regs	Exception frame containing machine register state
+ *	error	Error number passed to kdb.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	0	Standard instruction or data breakpoint encountered
+ *	1	Single Step fault ('ss' command)
+ *	2	Single Step fault, caller should continue ('ssb' command)
+ *	3	No existing kdb breakpoint matches this debug exception
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ * 	If multiple processors receive debug exceptions simultaneously,
+ *	one may be waiting at the kdb fence in kdb() while the user
+ *	issues a 'bc' command to clear the breakpoint the processor which
+ * 	is waiting has already encountered.   If this is the case, the
+ *	debug registers will no longer match any entry in the breakpoint
+ *	table, and we'll return the value '3'.  This can cause a panic
+ *	in die_if_kernel().  It is safer to disable the breakpoint (bd),
+ *	'go' until all processors are past the breakpoint then clear the
+ *	breakpoint (bc).  This code recognises a breakpoint even when
+ *	disabled but not when it has been cleared.
+ *
+ *	WARNING: This routine resets the eip.  It should be called
+ *		 once per breakpoint and the result cached.
+ */
+
+kdb_dbtrap_t
+kdba_bp_trap(struct pt_regs *regs, int error_unused)
+{
+	int i;
+	kdb_dbtrap_t rv;
+	kdb_bp_t *bp;
+
+	if (KDB_NULL_REGS(regs))
+		return KDB_DB_NOBPT;
+
+	/*
+	 * Determine which breakpoint was encountered.
+	 */
+	if (KDB_DEBUG(BP))
+		kdb_printf("kdba_bp_trap: eip=0x%lx (not adjusted) "
+			   "eflags=0x%lx regs=0x%p esp=0x%lx\n",
+			   regs->eip, regs->eflags, regs, regs->esp);
+
+	rv = KDB_DB_NOBPT;	/* Cause kdb() to return */
+
+	for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) {
+		if (bp->bp_free)
+			continue;
+		if (!bp->bp_global && bp->bp_cpu != smp_processor_id())
+			continue;
+		 if ((void *)bp->bp_addr == (void *)(regs->eip - bp->bp_adjust)) {
+			/* Hit this breakpoint.  */
+			regs->eip -= bp->bp_adjust;
+			kdb_printf("Instruction(i) breakpoint #%d at 0x%lx (adjusted)\n",
+				  i, regs->eip);
+			kdb_id1(regs->eip);
+			rv = KDB_DB_BPT;
+			bp->bp_delay = 1;
+			/* SSBPT is set when the kernel debugger must single
+			 * step a task in order to re-establish an instruction
+			 * breakpoint which uses the instruction replacement
+			 * mechanism.  It is cleared by any action that removes
+			 * the need to single-step the breakpoint.
+			 */
+			KDB_STATE_SET(SSBPT);
+			break;
+		}
+	}
+
+	return rv;
+}
+
+/*
+ * kdba_handle_bp
+ *
+ *	Handle an instruction-breakpoint trap.  Called when re-installing
+ *	an enabled breakpoint which has has the bp_delay bit set.
+ *
+ * Parameters:
+ * Returns:
+ * Locking:
+ * Remarks:
+ *
+ * Ok, we really need to:
+ *	1) Restore the original instruction byte
+ *	2) Single Step
+ *	3) Restore breakpoint instruction
+ *	4) Continue.
+ *
+ *
+ */
+
+static void
+kdba_handle_bp(struct pt_regs *regs, kdb_bp_t *bp)
+{
+	if (KDB_NULL_REGS(regs))
+		return;
+
+	if (KDB_DEBUG(BP))
+		kdb_printf("regs->eip = 0x%lx\n", regs->eip);
+
+	/*
+	 * Setup single step
+	 */
+	kdba_setsinglestep(regs);
+
+	/*
+	 * Reset delay attribute
+	 */
+	bp->bp_delay = 0;
+	bp->bp_delayed = 1;
+}
+
+
+/*
+ * kdba_bptype
+ *
+ *	Return a string describing type of breakpoint.
+ *
+ * Parameters:
+ *	bph	Pointer to hardware breakpoint description
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Character string.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+char *
+kdba_bptype(kdbhard_bp_t *bph)
+{
+	char *mode;
+
+	mode = kdba_rwtypes[bph->bph_mode];
+
+	return mode;
+}
+
+/*
+ * kdba_printbpreg
+ *
+ *	Print register name assigned to breakpoint
+ *
+ * Parameters:
+ *	bph	Pointer hardware breakpoint structure
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void
+kdba_printbpreg(kdbhard_bp_t *bph)
+{
+	kdb_printf(" in dr%ld", bph->bph_reg);
+}
+
+/*
+ * kdba_printbp
+ *
+ *	Print string describing hardware breakpoint.
+ *
+ * Parameters:
+ *	bph	Pointer to hardware breakpoint description
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void
+kdba_printbp(kdb_bp_t *bp)
+{
+	kdb_printf("\n    is enabled");
+	if (bp->bp_hardtype) {
+		kdba_printbpreg(bp->bp_hard);
+		if (bp->bp_hard->bph_mode != 0) {
+			kdb_printf(" for %d bytes",
+				   bp->bp_hard->bph_length+1);
+		}
+	}
+}
+
+/*
+ * kdba_parsebp
+ *
+ *	Parse architecture dependent portion of the
+ *	breakpoint command.
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Zero for success, a kdb diagnostic for failure
+ * Locking:
+ *	None.
+ * Remarks:
+ *	for Ia32 architure, data access, data write and
+ *	I/O breakpoints are supported in addition to instruction
+ * 	breakpoints.
+ *
+ *	{datar|dataw|io|inst} [length]
+ */
+
+int
+kdba_parsebp(int argc, const char **argv, int *nextargp, kdb_bp_t *bp)
+{
+	int		nextarg = *nextargp;
+	int		diag;
+	kdbhard_bp_t 	*bph = &bp->bp_template;
+
+	bph->bph_mode = 0;		/* Default to instruction breakpoint */
+	bph->bph_length = 0;		/* Length must be zero for insn bp */
+	if ((argc + 1) != nextarg) {
+		if (strnicmp(argv[nextarg], "datar", sizeof("datar")) == 0) {
+			bph->bph_mode = 3;
+		} else if (strnicmp(argv[nextarg], "dataw", sizeof("dataw")) == 0) {
+			bph->bph_mode = 1;
+		} else if (strnicmp(argv[nextarg], "io", sizeof("io")) == 0) {
+			bph->bph_mode = 2;
+		} else if (strnicmp(argv[nextarg], "inst", sizeof("inst")) == 0) {
+			bph->bph_mode = 0;
+		} else {
+			return KDB_ARGCOUNT;
+		}
+
+		bph->bph_length = 3;	/* Default to 4 byte */
+
+		nextarg++;
+
+		if ((argc + 1) != nextarg) {
+			unsigned long len;
+
+			diag = kdbgetularg((char *)argv[nextarg],
+					   &len);
+			if (diag)
+				return diag;
+
+
+			if ((len > 4) || (len == 3))
+				return KDB_BADLENGTH;
+
+			bph->bph_length = len;
+			bph->bph_length--; /* Normalize for debug register */
+			nextarg++;
+		}
+
+		if ((argc + 1) != nextarg)
+			return KDB_ARGCOUNT;
+
+		/*
+		 * Indicate to architecture independent level that
+		 * a hardware register assignment is required to enable
+		 * this breakpoint.
+		 */
+
+		bph->bph_free = 0;
+	} else {
+		if (KDB_DEBUG(BP))
+			kdb_printf("kdba_bp: no args, forcehw is %d\n", bp->bp_forcehw);
+		if (bp->bp_forcehw) {
+			/*
+			 * We are forced to use a hardware register for this
+			 * breakpoint because either the bph or bpha
+			 * commands were used to establish this breakpoint.
+			 */
+			bph->bph_free = 0;
+		} else {
+			/*
+			 * Indicate to architecture dependent level that
+			 * the instruction replacement breakpoint technique
+			 * should be used for this breakpoint.
+			 */
+			bph->bph_free = 1;
+			bp->bp_adjust = 1;	/* software, int 3 is one byte */
+		}
+	}
+
+	if (bph->bph_mode != 2 && kdba_verify_rw(bp->bp_addr, bph->bph_length+1)) {
+		kdb_printf("Invalid address for breakpoint, ignoring bp command\n");
+		return KDB_BADADDR;
+	}
+
+	*nextargp = nextarg;
+	return 0;
+}
+
+/*
+ * kdba_allocbp
+ *
+ *	Associate a hardware register with a breakpoint.
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	A pointer to the allocated register kdbhard_bp_t structure for
+ *	success, Null and a non-zero diagnostic for failure.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+kdbhard_bp_t *
+kdba_allocbp(kdbhard_bp_t *bph, int *diagp)
+{
+	int i;
+	kdbhard_bp_t *newbph;
+
+	for(i=0,newbph=kdb_hardbreaks; i < KDB_MAXHARDBPT; i++, newbph++) {
+		if (newbph->bph_free) {
+			break;
+		}
+	}
+
+	if (i == KDB_MAXHARDBPT) {
+		*diagp = KDB_TOOMANYDBREGS;
+		return NULL;
+	}
+
+	*diagp = 0;
+
+	/*
+	 * Copy data from template.  Can't just copy the entire template
+	 * here because the register number in kdb_hardbreaks must be
+	 * preserved.
+	 */
+	newbph->bph_data = bph->bph_data;
+	newbph->bph_write = bph->bph_write;
+	newbph->bph_mode = bph->bph_mode;
+	newbph->bph_length = bph->bph_length;
+
+	/*
+	 * Mark entry allocated.
+	 */
+	newbph->bph_free = 0;
+
+	return newbph;
+}
+
+/*
+ * kdba_freebp
+ *
+ *	Deallocate a hardware breakpoint
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Zero for success, a kdb diagnostic for failure
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void
+kdba_freebp(kdbhard_bp_t *bph)
+{
+	bph->bph_free = 1;
+}
+
+/*
+ * kdba_initbp
+ *
+ *	Initialize the breakpoint table for the hardware breakpoint
+ *	register.
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Zero for success, a kdb diagnostic for failure
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ *	There is one entry per register.  On the ia32 architecture
+ *	all the registers are interchangeable, so no special allocation
+ *	criteria are required.
+ */
+
+void
+kdba_initbp(void)
+{
+	int i;
+	kdbhard_bp_t *bph;
+
+	/*
+	 * Clear the hardware breakpoint table
+	 */
+
+	memset(kdb_hardbreaks, '\0', sizeof(kdb_hardbreaks));
+
+	for(i=0,bph=kdb_hardbreaks; i<KDB_MAXHARDBPT; i++, bph++) {
+		bph->bph_reg = i;
+		bph->bph_free = 1;
+	}
+}
+
+/*
+ * kdba_installbp
+ *
+ *	Install a breakpoint
+ *
+ * Parameters:
+ *	regs	Exception frame
+ *	bp	Breakpoint structure for the breakpoint to be installed
+ * Outputs:
+ *	None.
+ * Returns:
+ *	0 if breakpoint installed.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	For hardware breakpoints, a debug register is allocated
+ *	and assigned to the breakpoint.  If no debug register is
+ *	available, a warning message is printed and the breakpoint
+ *	is disabled.
+ *
+ *	For instruction replacement breakpoints, we must single-step
+ *	over the replaced instruction at this point so we can re-install
+ *	the breakpoint instruction after the single-step.  SSBPT is set
+ *	when the breakpoint is initially hit and is cleared by any action
+ *	that removes the need for single-step over the breakpoint.
+ */
+
+int
+kdba_installbp(struct pt_regs *regs, kdb_bp_t *bp)
+{
+	/*
+	 * Install the breakpoint, if it is not already installed.
+	 */
+
+	if (KDB_DEBUG(BP)) {
+		kdb_printf("kdba_installbp bp_installed %d\n", bp->bp_installed);
+	}
+	if (!KDB_STATE(SSBPT))
+		bp->bp_delay = 0;
+	if (!bp->bp_installed) {
+		if (bp->bp_hardtype) {
+			kdba_installdbreg(bp);
+			bp->bp_installed = 1;
+			if (KDB_DEBUG(BP)) {
+				kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt "\n",
+					   bp->bp_hard->bph_reg, bp->bp_addr);
+			}
+		} else if (bp->bp_delay) {
+			if (KDB_DEBUG(BP))
+				kdb_printf("kdba_installbp delayed bp\n");
+			kdba_handle_bp(regs, bp);
+		} else {
+			if (kdb_getarea_size(&(bp->bp_inst), bp->bp_addr, 1) ||
+			    kdb_putword(bp->bp_addr, IA32_BREAKPOINT_INSTRUCTION, 1)) {
+				kdb_printf("kdba_installbp failed to set software breakpoint at 0x%lx\n", bp->bp_addr);
+				return(1);
+			}
+			bp->bp_installed = 1;
+			if (KDB_DEBUG(BP))
+				kdb_printf("kdba_installbp instruction 0x%x at " kdb_bfd_vma_fmt "\n",
+					   IA32_BREAKPOINT_INSTRUCTION, bp->bp_addr);
+		}
+	}
+	return(0);
+}
+
+/*
+ * kdba_removebp
+ *
+ *	Make a breakpoint ineffective.
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+int
+kdba_removebp(kdb_bp_t *bp)
+{
+	/*
+	 * For hardware breakpoints, remove it from the active register,
+	 * for software breakpoints, restore the instruction stream.
+	 */
+	if (KDB_DEBUG(BP)) {
+		kdb_printf("kdba_removebp bp_installed %d\n", bp->bp_installed);
+	}
+	if (bp->bp_installed) {
+		if (bp->bp_hardtype) {
+			if (KDB_DEBUG(BP)) {
+				kdb_printf("kdb: removing hardware reg %ld at " kdb_bfd_vma_fmt "\n",
+					   bp->bp_hard->bph_reg, bp->bp_addr);
+			}
+			kdba_removedbreg(bp);
+		} else {
+			if (KDB_DEBUG(BP))
+				kdb_printf("kdb: restoring instruction 0x%x at " kdb_bfd_vma_fmt "\n",
+					   bp->bp_inst, bp->bp_addr);
+			if (kdb_putword(bp->bp_addr, bp->bp_inst, 1))
+				return(1);
+		}
+		bp->bp_installed = 0;
+	}
+	return(0);
+}
Index: 2.4.x-xfs/arch/i386/kdb/kdba_bt.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kdb/kdba_bt.c	Thu Jan  1 10:00:00 1970
+++ 2.4.x-xfs/arch/i386/kdb/kdba_bt.c	Mon Aug  9 13:54:51 2004
@@ -0,0 +1,379 @@
+/*
+ * Kernel Debugger Architecture Dependent Stack Traceback
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/config.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kallsyms.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <asm/system.h>
+
+#ifdef CONFIG_FRAME_POINTER
+#define EFPSTR	"EBP"
+#define EFP	ebp
+#define NOBP	0
+#else
+#define EFPSTR	"ESP"
+#define EFP	esp
+#define NOBP	esp
+#endif
+
+/*
+ * bt_print_one
+ *
+ *	Print one back trace entry.
+ *
+ * Inputs:
+ *	eip	Current program counter, or return address.
+ *	efp	#ifdef CONFIG_FRAME_POINTER: Previous frame pointer ebp,
+ *		0 if not valid; #else: Stack pointer esp when at eip.
+ *	ar	Activation record for this frame.
+ *	symtab	Information about symbol that eip falls within.
+ *	argcount Maximum number of arguments to print.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	None.
+ */
+
+static void
+bt_print_one(kdb_machreg_t eip, kdb_machreg_t efp, const kdb_ar_t *ar,
+	     const kdb_symtab_t *symtab, int argcount)
+{
+	int	btsymarg = 0;
+	int	nosect = 0;
+	kdb_machreg_t word;
+
+	kdbgetintenv("BTSYMARG", &btsymarg);
+	kdbgetintenv("NOSECT", &nosect);
+
+	if (efp)
+		kdb_printf("0x%08lx", efp);
+	else
+		kdb_printf("          ");
+	kdb_symbol_print(eip, symtab, KDB_SP_SPACEB|KDB_SP_VALUE);
+	if (argcount && ar->args) {
+		int i, argc = ar->args / 4;
+
+		kdb_printf(" (");
+		if (argc > argcount)
+			argc = argcount;
+
+		for(i=1; i<=argc; i++){
+			kdb_machreg_t argp = ar->arg0 - ar->args + 4*i;
+
+			if (i != 1)
+				kdb_printf(", ");
+			kdb_getword(&word, argp, sizeof(word));
+			kdb_printf("0x%lx", word);
+		}
+		kdb_printf(")");
+	}
+	if (symtab->sym_name) {
+		if (!nosect) {
+			kdb_printf("\n");
+			kdb_printf("                               %s %s 0x%lx 0x%lx 0x%lx",
+				symtab->mod_name,
+				symtab->sec_name,
+				symtab->sec_start,
+				symtab->sym_start,
+				symtab->sym_end);
+		}
+	}
+	kdb_printf("\n");
+	if (argcount && ar->args && btsymarg) {
+		int i, argc = ar->args / 4;
+		kdb_symtab_t	arg_symtab;
+		kdb_machreg_t	arg;
+		for(i=1; i<=argc; i++){
+			kdb_machreg_t argp = ar->arg0 - ar->args + 4*i;
+			kdb_getword(&arg, argp, sizeof(arg));
+			if (kdbnearsym(arg, &arg_symtab)) {
+				kdb_printf("                               ");
+				kdb_symbol_print(arg, &arg_symtab, KDB_SP_DEFAULT|KDB_SP_NEWLINE);
+			}
+		}
+	}
+}
+
+/*
+ * kdba_bt_stack
+ *
+ * Inputs:
+ *	addr	Pointer to Address provided to 'bt' command, if any.
+ *	argcount
+ *	p	Pointer to task for 'btp' command.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	mds comes in handy when examining the stack to do a manual
+ *	traceback.
+ */
+
+static int
+kdba_bt_stack(kdb_machreg_t addr, int argcount, struct task_struct *p)
+{
+	kdb_ar_t	ar;
+	kdb_machreg_t	eip, esp, ebp, ss, cs;
+	kdb_symtab_t	symtab;
+	int count;
+
+	/*
+	 * The caller may have supplied an address at which the
+	 * stack traceback operation should begin.  This address
+	 * is assumed by this code to point to a return-address
+	 * on the stack to be traced back.
+	 *
+	 * The end result of this will make it appear as if a function
+	 * entitled '<unknown>' was called from the function which
+	 * contains return-address.
+	 */
+	if (addr) {
+		eip = 0;
+		ebp = 0;
+		esp = addr;
+		cs  = __KERNEL_CS;	/* have to assume kernel space */
+	} else {
+		if (kdb_task_has_cpu(p)) {
+			struct kdb_running_process *krp = kdb_running_process + kdb_process_cpu(p);
+			struct pt_regs *regs;
+			if (!krp->seqno) {
+				kdb_printf("Process did not save state, cannot backtrace\n");
+				kdb_ps1(p);
+				return 0;
+			}
+			regs = krp->regs;
+			if (KDB_NULL_REGS(regs))
+				return KDB_BADREG;
+			kdba_getregcontents("eip", regs, &eip);
+			kdba_getregcontents("ebp", regs, &ebp);
+			kdba_getregcontents("esp", regs, &esp);
+			kdba_getregcontents("xcs", regs, &cs);
+		}
+		else {
+			/* Not on cpu, assume blocked.  Blocked i386 tasks do
+			 * not have pt_regs.  p->thread.{esp,eip} are set, esp
+			 * points to the ebp value, assume kernel space.
+			 */
+			eip = p->thread.eip;
+			esp = p->thread.esp;
+			ebp = *(unsigned long *)esp;
+			cs  = __KERNEL_CS;
+		}
+		if (esp < (unsigned long)p || esp >= (unsigned long)p + THREAD_SIZE) {
+			kdb_printf("Stack is not in task_struct, backtrace not available\n");
+			return(0);
+		}
+	}
+	ss = esp & -THREAD_SIZE;
+
+	if ((cs & 0xffff) != __KERNEL_CS) {
+		kdb_printf("Stack is not in kernel space, backtrace not available\n");
+		return 0;
+	}
+
+	kdb_printf(EFPSTR "        EIP        Function (args)\n");
+
+	/*
+	 * Run through the activation records and print them.
+	 */
+
+	for (count = 0; count < 200; ++count) {
+		kdb_ar_t save_ar = ar;
+		kdbnearsym(eip, &symtab);
+		if (!kdb_get_next_ar(esp, symtab.sym_start, eip, ebp, ss,
+			&ar, &symtab)) {
+			break;
+		}
+
+		if (strncmp(".text.lock.", symtab.sym_name, 11) == 0) {
+			/*
+			 * Instructions in the .text.lock area are generated by
+			 * the out of line code in lock handling, see
+			 * include/asm-i386 semaphore.h and rwlock.h.  There can
+			 * be multiple instructions which eventually end with a
+			 * jump back to the mainline code.  Use the disassmebler
+			 * to silently step through the code until we find the
+			 * jump, resolve its destination and translate it to a
+			 * symbol.  Replace '.text.lock' with the symbol.
+			 */
+			unsigned char inst;
+			kdb_machreg_t offset = 0, realeip = eip;
+			int length, offsize = 0;
+			kdb_symtab_t lock_symtab;
+			/* Dummy out the disassembler print function */
+			fprintf_ftype save_fprintf_func = kdb_di.fprintf_func;
+
+			kdb_di.fprintf_func = &kdb_dis_fprintf_dummy;
+			while((length = kdba_id_printinsn(realeip, &kdb_di)) > 0) {
+				kdb_getarea(inst, realeip);
+				offsize = 0;
+				switch (inst) {
+				case 0xeb:	/* jmp with 1 byte offset */
+					offsize = 1-4;
+					/* drop through */
+				case 0xe9:	/* jmp with 4 byte offset */
+					offsize += 4;
+					kdb_getword(&offset, realeip+1, offsize);
+					break;
+				default:
+					realeip += length;	/* next instruction */
+					break;
+				}
+				if (offsize)
+					break;
+			}
+			kdb_di.fprintf_func = save_fprintf_func;
+
+			if (offsize) {
+				realeip += 1 + offsize + (offsize == 1 ? (s8)offset : (s32)offset);
+				if (kdbnearsym(realeip, &lock_symtab)) {
+					/* Print the stext entry without args */
+					bt_print_one(eip, NOBP, &ar, &symtab, 0);
+					/* Point to mainline code */
+					eip = realeip;
+					ar = save_ar;	/* lock text does not consume an activation frame */
+					continue;
+				}
+			}
+		}
+
+		if (strcmp("ret_from_intr", symtab.sym_name) == 0 ||
+		    strcmp("error_code", symtab.sym_name) == 0) {
+			if (strcmp("ret_from_intr", symtab.sym_name) == 0) {
+				/*
+				 * Non-standard frame.  ret_from_intr is
+				 * preceded by 9 registers (ebx, ecx, edx, esi,
+				 * edi, ebp, eax, ds, cs), original eax and the
+				 * return address for a total of 11 words.
+				 */
+				ar.start = ar.end + 11*4;
+			}
+			if (strcmp("error_code", symtab.sym_name) == 0) {
+				/*
+				 * Non-standard frame.  error_code is preceded
+				 * by two parameters (-> registers, error code),
+				 * 9 registers (ebx, ecx, edx, esi, edi, ebp,
+				 * eax, ds, cs), original eax and the return
+				 * address for a total of 13 words.
+				 */
+				ar.start = ar.end + 13*4;
+			}
+			/* Print the non-standard entry without args */
+			bt_print_one(eip, NOBP, &ar, &symtab, 0);
+			kdb_printf("Interrupt registers:\n");
+			kdba_dumpregs((struct pt_regs *)(ar.end), NULL, NULL);
+			/* Step the frame to the interrupted code */
+			kdb_getword(&eip, ar.start-4, 4);
+			ebp = 0;
+			esp = ar.start;
+			if ((((struct pt_regs *)(ar.end))->xcs & 0xffff) != __KERNEL_CS) {
+				kdb_printf("Interrupt from user space, end of kernel trace\n");
+				break;
+			}
+			continue;
+		}
+
+		bt_print_one(eip, EFP, &ar, &symtab, argcount);
+
+		if (ar.ret == 0)
+			break;	/* End of frames */
+		eip = ar.ret;
+		ebp = ar.oldfp;
+		esp = ar.start;
+	}
+	if (count >= 200)
+		kdb_printf("bt truncated, count limit reached\n");
+
+	return 0;
+}
+
+/*
+ * kdba_bt_address
+ *
+ *	Do a backtrace starting at a specified stack address.  Use this if the
+ *	heuristics get the i386 stack decode wrong.
+ *
+ * Inputs:
+ *	addr	Address provided to 'bt' command.
+ *	argcount
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	mds %esp comes in handy when examining the stack to do a manual
+ *	traceback.
+ */
+
+int
+kdba_bt_address(kdb_machreg_t addr, int argcount)
+{
+	return kdba_bt_stack(addr, argcount, NULL);
+}
+
+/*
+ * kdba_bt_process
+ *
+ *	Do a backtrace for a specified process.
+ *
+ * Inputs:
+ *	p	Struct task pointer extracted by 'bt' command.
+ *	argcount
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ */
+
+int
+kdba_bt_process(struct task_struct *p, int argcount)
+{
+	return kdba_bt_stack(0, argcount, p);
+}
Index: 2.4.x-xfs/arch/i386/kdb/kdba_id.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kdb/kdba_id.c	Thu Jan  1 10:00:00 1970
+++ 2.4.x-xfs/arch/i386/kdb/kdba_id.c	Mon Aug  9 13:54:51 2004
@@ -0,0 +1,279 @@
+/*
+ * Kernel Debugger Architecture Dependent Instruction Disassembly
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <stdarg.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+
+/*
+ * kdba_dis_getsym
+ *
+ *	Get a symbol for the disassembler.
+ *
+ * Parameters:
+ *	addr	Address for which to get symbol
+ *	dip	Pointer to disassemble_info
+ * Returns:
+ *	0
+ * Locking:
+ * Remarks:
+ *	Not used for kdb.
+ */
+
+/* ARGSUSED */
+static int
+kdba_dis_getsym(bfd_vma addr, disassemble_info *dip)
+{
+
+	return 0;
+}
+
+/*
+ * kdba_printaddress
+ *
+ *	Print (symbolically) an address.
+ *
+ * Parameters:
+ *	addr	Address for which to get symbol
+ *	dip	Pointer to disassemble_info
+ *	flag	True if a ":<tab>" sequence should follow the address
+ * Returns:
+ *	0
+ * Locking:
+ * Remarks:
+ *
+ */
+
+/* ARGSUSED */
+void
+kdba_printaddress(kdb_machreg_t addr, disassemble_info *dip, int flag)
+{
+	kdb_symtab_t symtab;
+	int spaces = 5;
+	unsigned int offset;
+
+	/*
+	 * Print a symbol name or address as necessary.
+	 */
+	kdbnearsym(addr, &symtab);
+	if (symtab.sym_name) {
+		/* Do not use kdb_symbol_print here, it always does
+		 * kdb_printf but we want dip->fprintf_func.
+		 */
+		dip->fprintf_func(dip->stream,
+			"0x%0*lx %s",
+			2*sizeof(addr), addr, symtab.sym_name);
+		if ((offset = addr - symtab.sym_start) == 0) {
+			spaces += 4;
+		}
+		else {
+			unsigned int o = offset;
+			while (o >>= 4)
+				--spaces;
+			dip->fprintf_func(dip->stream, "+0x%x", offset);
+		}
+
+	} else {
+		dip->fprintf_func(dip->stream, "0x%x", addr);
+	}
+
+	if (flag) {
+		if (spaces < 1) {
+			spaces = 1;
+		}
+		dip->fprintf_func(dip->stream, ":%*s", spaces, " ");
+	}
+}
+
+/*
+ * kdba_dis_printaddr
+ *
+ *	Print (symbolically) an address.  Called by GNU disassembly
+ *	code via disassemble_info structure.
+ *
+ * Parameters:
+ *	addr	Address for which to get symbol
+ *	dip	Pointer to disassemble_info
+ * Returns:
+ *	0
+ * Locking:
+ * Remarks:
+ *	This function will never append ":<tab>" to the printed
+ *	symbolic address.
+ */
+
+static void
+kdba_dis_printaddr(bfd_vma addr, disassemble_info *dip)
+{
+	kdba_printaddress(addr, dip, 0);
+}
+
+/*
+ * kdba_dis_getmem
+ *
+ *	Fetch 'length' bytes from 'addr' into 'buf'.
+ *
+ * Parameters:
+ *	addr	Address for which to get symbol
+ *	buf	Address of buffer to fill with bytes from 'addr'
+ *	length	Number of bytes to fetch
+ *	dip	Pointer to disassemble_info
+ * Returns:
+ *	0 if data is available, otherwise error.
+ * Locking:
+ * Remarks:
+ *
+ */
+
+/* ARGSUSED */
+static int
+kdba_dis_getmem(bfd_vma addr, bfd_byte *buf, unsigned int length, disassemble_info *dip)
+{
+	return kdb_getarea_size(buf, addr, length);
+}
+
+/*
+ * kdba_id_parsemode
+ *
+ * 	Parse IDMODE environment variable string and
+ *	set appropriate value into "disassemble_info" structure.
+ *
+ * Parameters:
+ *	mode	Mode string
+ *	dip	Disassemble_info structure pointer
+ * Returns:
+ * Locking:
+ * Remarks:
+ *	We handle the values 'x86' and '8086' to enable either
+ *	32-bit instruction set or 16-bit legacy instruction set.
+ */
+
+int
+kdba_id_parsemode(const char *mode, disassemble_info *dip)
+{
+
+	if (mode) {
+		if (strcmp(mode, "x86") == 0) {
+			dip->mach = bfd_mach_i386_i386;
+		} else if (strcmp(mode, "8086") == 0) {
+			dip->mach = bfd_mach_i386_i8086;
+		} else {
+			return KDB_BADMODE;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * kdba_check_pc
+ *
+ * 	Check that the pc is satisfactory.
+ *
+ * Parameters:
+ *	pc	Program Counter Value.
+ * Returns:
+ *	None
+ * Locking:
+ *	None.
+ * Remarks:
+ *	Can change pc.
+ */
+
+void
+kdba_check_pc(kdb_machreg_t *pc)
+{
+	/* No action */
+}
+
+/*
+ * kdba_id_printinsn
+ *
+ * 	Format and print a single instruction at 'pc'. Return the
+ *	length of the instruction.
+ *
+ * Parameters:
+ *	pc	Program Counter Value.
+ *	dip	Disassemble_info structure pointer
+ * Returns:
+ *	Length of instruction, -1 for error.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	Depends on 'IDMODE' environment variable.
+ */
+
+int
+kdba_id_printinsn(kdb_machreg_t pc, disassemble_info *dip)
+{
+	kdba_printaddress(pc, dip, 1);
+	return print_insn_i386_att(pc, dip);
+}
+
+/*
+ * kdba_id_init
+ *
+ * 	Initialize the architecture dependent elements of
+ *	the disassembly information structure
+ *	for the GNU disassembler.
+ *
+ * Parameters:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+void __init
+kdba_id_init(disassemble_info *dip)
+{
+	dip->read_memory_func       = kdba_dis_getmem;
+	dip->print_address_func     = kdba_dis_printaddr;
+	dip->symbol_at_address_func = kdba_dis_getsym;
+
+	dip->flavour                = bfd_target_elf_flavour;
+	dip->arch		    = bfd_arch_i386;
+	dip->mach		    = bfd_mach_i386_i386;
+	dip->endian	    	    = BFD_ENDIAN_LITTLE;
+
+	dip->display_endian         = BFD_ENDIAN_LITTLE;
+}
Index: 2.4.x-xfs/arch/i386/kdb/kdba_io.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kdb/kdba_io.c	Thu Jan  1 10:00:00 1970
+++ 2.4.x-xfs/arch/i386/kdb/kdba_io.c	Mon Aug  9 13:54:51 2004
@@ -0,0 +1,522 @@
+/*
+ * Kernel Debugger Architecture Dependent Console I/O handler
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/pc_keyb.h>
+#include <linux/console.h>
+#include <linux/ctype.h>
+#include <linux/keyboard.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <asm/keyboard.h>	/* ashishk@sco.com */
+
+#ifdef	CONFIG_VT_CONSOLE
+#define KDB_BLINK_LED 1
+#else
+#undef	KDB_BLINK_LED
+#endif
+
+#ifdef CONFIG_KDB_USB
+struct kdb_usb_exchange kdb_usb_infos = { NULL, NULL, NULL, NULL, NULL, 0};
+
+static unsigned char kdb_usb_keycode[256] = {
+	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
+	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
+	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
+	 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
+	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
+	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
+	 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
+	120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
+	115,114,  0,  0,  0,124,  0,181,182,183,184,185,186,187,188,189,
+	190,191,192,193,194,195,196,197,198,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
+	150,158,159,128,136,177,178,176,142,152,173,140
+};
+
+/* get_usb_char
+ * This function drives the UHCI controller,
+ * fetch the USB scancode and decode it
+ */
+static int get_usb_char(void)
+{
+	static int usb_lock;
+	unsigned char keycode, spec;
+	extern u_short  plain_map[], shift_map[], ctrl_map[];
+
+	/* Is USB initialized ? */
+	if(!kdb_usb_infos.poll_func || !kdb_usb_infos.urb)
+    		return -1;
+
+	/* Transfer char if they are present */
+	(*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb);
+
+	spec = kdb_usb_infos.buffer[0];
+	keycode = kdb_usb_infos.buffer[2];
+	kdb_usb_infos.buffer[0] = (char)0;
+	kdb_usb_infos.buffer[2] = (char)0;
+
+	if(kdb_usb_infos.buffer[3])
+  		return -1;
+
+	/* A normal key is pressed, decode it */
+	if(keycode)
+		keycode = kdb_usb_keycode[keycode];
+
+	/* 2 Keys pressed at one time ? */
+	if (spec && keycode) {
+		switch(spec)
+  		{
+  			case 0x2:
+  			case 0x20: /* Shift */
+    				return shift_map[keycode];
+	  		case 0x1:
+  			case 0x10: /* Ctrl */
+    				return ctrl_map[keycode];
+			case 0x4:
+			case 0x40: /* Alt */
+    				break;
+  		}
+	}
+	else {
+    		if(keycode) { /* If only one key pressed */
+      			switch(keycode)
+			{
+				case 0x1C: /* Enter */
+	  				return 13;
+
+				case 0x3A: /* Capslock */
+	  				usb_lock ? (usb_lock = 0) : (usb_lock = 1);
+	  				break;
+				case 0x0E: /* Backspace */
+	  				return 8;
+				case 0x0F: /* TAB */
+					return 9;
+				case 0x77: /* Pause */
+	  				break ;
+				default:
+	  				if(!usb_lock) {
+	    					return plain_map[keycode];
+					}
+					else {
+	    					return shift_map[keycode];
+	  				}
+			}
+    		}
+   	}
+	return -1;
+}
+#endif
+
+/*
+ * This module contains code to read characters from the keyboard or a serial
+ * port.
+ *
+ * It is used by the kernel debugger, and is polled, not interrupt driven.
+ *
+ */
+
+#ifdef	KDB_BLINK_LED
+/*
+ * send:  Send a byte to the keyboard controller.  Used primarily to
+ * 	  alter LED settings.
+ */
+
+static void
+kdb_kbdsend(unsigned char byte)
+{
+	while (inb(KBD_STATUS_REG) & KBD_STAT_IBF)
+		;
+	outb(byte, KBD_DATA_REG);
+}
+
+static void
+kdb_toggleled(int led)
+{
+	static int leds;
+
+	leds ^= led;
+
+	kdb_kbdsend(KBD_CMD_SET_LEDS);
+	kdb_kbdsend((unsigned char)leds);
+}
+#endif	/* KDB_BLINK_LED */
+
+#if defined(CONFIG_SERIAL_CONSOLE)
+
+struct kdb_serial kdb_serial;
+
+static inline unsigned int
+serial_inp(struct kdb_serial *kdb_serial, unsigned long offset)
+{
+	offset <<= kdb_serial->ioreg_shift;
+
+	switch (kdb_serial->io_type) {
+	case SERIAL_IO_MEM:
+		return readb(kdb_serial->iobase + offset);
+		break;
+	default:
+		return inb(kdb_serial->iobase + offset);
+		break;
+	}
+}
+
+/* Check if there is a byte ready at the serial port */
+static int get_serial_char(void)
+{
+	unsigned char ch;
+
+	if (kdb_serial.iobase == 0)
+		return -1;
+
+	if (serial_inp(&kdb_serial, UART_LSR) & UART_LSR_DR) {
+		ch = serial_inp(&kdb_serial, UART_RX);
+		if (ch == 0x7f)
+			ch = 8;
+		return ch;
+	}
+	return -1;
+}
+#endif /* CONFIG_SERIAL_CONSOLE */
+
+#ifdef	CONFIG_VT_CONSOLE
+
+static int kbd_exists = -1;
+
+/*
+ * Check if the keyboard controller has a keypress for us.
+ * Some parts (Enter Release, LED change) are still blocking polled here,
+ * but hopefully they are all short.
+ */
+static int get_kbd_char(void)
+{
+	int	scancode, scanstatus;
+	static int shift_lock;	/* CAPS LOCK state (0-off, 1-on) */
+	static int shift_key;	/* Shift next keypress */
+	static int ctrl_key;
+	u_short keychar;
+	extern u_short plain_map[], shift_map[], ctrl_map[];
+
+	if (kbd_exists <= 0) {
+		if (kbd_exists == 0)
+			return -1;
+
+		if (inb(KBD_STATUS_REG) == 0xff && inb(KBD_DATA_REG) == 0xff) {
+			kbd_exists = 0;
+			return -1;
+		}
+		kbd_exists = 1;
+	}
+
+	if ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
+		return -1;
+
+	/*
+	 * Fetch the scancode
+	 */
+	scancode = inb(KBD_DATA_REG);
+	scanstatus = inb(KBD_STATUS_REG);
+
+	/*
+	 * Ignore mouse events.
+	 */
+	if (scanstatus & KBD_STAT_MOUSE_OBF)
+		return -1;
+
+	/*
+	 * Ignore release, trigger on make
+	 * (except for shift keys, where we want to
+	 *  keep the shift state so long as the key is
+	 *  held down).
+	 */
+
+	if (((scancode&0x7f) == 0x2a) || ((scancode&0x7f) == 0x36)) {
+		/*
+		 * Next key may use shift table
+		 */
+		if ((scancode & 0x80) == 0) {
+			shift_key=1;
+		} else {
+			shift_key=0;
+		}
+		return -1;
+	}
+
+	if ((scancode&0x7f) == 0x1d) {
+		/*
+		 * Left ctrl key
+		 */
+		if ((scancode & 0x80) == 0) {
+			ctrl_key = 1;
+		} else {
+			ctrl_key = 0;
+		}
+		return -1;
+	}
+
+	if ((scancode & 0x80) != 0)
+		return -1;
+
+	scancode &= 0x7f;
+
+	/*
+	 * Translate scancode
+	 */
+
+	if (scancode == 0x3a) {
+		/*
+		 * Toggle caps lock
+		 */
+		shift_lock ^= 1;
+
+#ifdef	KDB_BLINK_LED
+		kdb_toggleled(0x4);
+#endif
+		return -1;
+	}
+
+	if (scancode == 0x0e) {
+		/*
+		 * Backspace
+		 */
+		return 8;
+	}
+
+	/* Special Key */
+	switch (scancode) {
+	case 0xF: /* Tab */
+		return 9;
+	case 0x53: /* Del */
+		return 4;
+	case 0x47: /* Home */
+		return 1;
+	case 0x4F: /* End */
+		return 5;
+	case 0x4B: /* Left */
+		return 2;
+	case 0x48: /* Up */
+		return 16;
+	case 0x50: /* Down */
+		return 14;
+	case 0x4D: /* Right */
+		return 6;
+	}
+
+	if (scancode == 0xe0) {
+		return -1;
+	}
+
+	/*
+	 * For Japanese 86/106 keyboards
+	 * 	See comment in drivers/char/pc_keyb.c.
+	 * 	- Masahiro Adegawa
+	 */
+	if (scancode == 0x73) {
+		scancode = 0x59;
+	} else if (scancode == 0x7d) {
+		scancode = 0x7c;
+	}
+
+	if (!shift_lock && !shift_key && !ctrl_key) {
+		keychar = plain_map[scancode];
+	} else if (shift_lock || shift_key) {
+		keychar = shift_map[scancode];
+	} else if (ctrl_key) {
+		keychar = ctrl_map[scancode];
+	} else {
+		keychar = 0x0020;
+		kdb_printf("Unknown state/scancode (%d)\n", scancode);
+	}
+	keychar &= 0x0fff;
+	if (keychar == '\t')
+		keychar = ' ';
+	switch (KTYP(keychar)) {
+	case KT_LETTER:
+	case KT_LATIN:
+		if (isprint(keychar))
+			break;		/* printable characters */
+		/* drop through */
+	case KT_SPEC:
+		if (keychar == K_ENTER)
+			break;
+		/* drop through */
+	default:
+		return(-1);	/* ignore unprintables */
+	}
+
+	if ((scancode & 0x7f) == 0x1c) {
+		/*
+		 * enter key.  All done.  Absorb the release scancode.
+		 */
+		while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
+			;
+
+		/*
+		 * Fetch the scancode
+		 */
+		scancode = inb(KBD_DATA_REG);
+		scanstatus = inb(KBD_STATUS_REG);
+
+		while (scanstatus & KBD_STAT_MOUSE_OBF) {
+			scancode = inb(KBD_DATA_REG);
+			scanstatus = inb(KBD_STATUS_REG);
+		}
+
+		if (scancode != 0x9c) {
+			/*
+			 * Wasn't an enter-release,  why not?
+			 */
+			kdb_printf("kdb: expected enter got 0x%x status 0x%x\n",
+			       scancode, scanstatus);
+		}
+
+		kdb_printf("\n");
+		return 13;
+	}
+
+	return keychar & 0xff;
+}
+#endif	/* CONFIG_VT_CONSOLE */
+
+#ifdef KDB_BLINK_LED
+
+/* Leave numlock alone, setting it messes up laptop keyboards with the keypad
+ * mapped over normal keys.
+ */
+int kdba_blink_mask = 0x1 | 0x4;
+
+#define BOGOMIPS (boot_cpu_data.loops_per_jiffy/(500000/HZ))
+static int blink_led(void)
+{
+	static long delay;
+
+	if (kbd_exists == 0)
+		return -1;
+
+	if (--delay < 0) {
+		if (BOGOMIPS == 0)	/* early kdb */
+			delay = 150000000/1000;     /* arbitrary bogomips */
+		else
+			delay = 150000000/BOGOMIPS; /* Roughly 1 second when polling */
+		kdb_toggleled(kdba_blink_mask);
+	}
+	return -1;
+}
+#endif
+
+get_char_func poll_funcs[] = {
+#if defined(CONFIG_VT_CONSOLE)
+	get_kbd_char,
+#endif
+#if defined(CONFIG_SERIAL_CONSOLE)
+	get_serial_char,
+#endif
+#ifdef KDB_BLINK_LED
+	blink_led,
+#endif
+#ifdef CONFIG_KDB_USB
+	get_usb_char,
+#endif
+	NULL
+};
+
+/* 
+ * On some Compaq Deskpro's, there is a keyboard freeze many times after
+ * exiting from the kdb. As kdb's keyboard handler is not interrupt-driven and 
+ * uses a polled interface, it makes more sense to disable motherboard keyboard
+ * controller's OBF interrupts during kdb's polling.In case, of interrupts 
+ * remaining enabled during kdb's polling, it may cause un-necessary 
+ * interrupts being signalled during keypresses, which are also sometimes seen
+ * as spurious interrupts after exiting from kdb. This hack to disable OBF
+ * interrupts before entry to kdb and re-enabling them at kdb exit point also 
+ * solves the keyboard freeze issue. These functions are called from
+ * kdb_local(), hence these are arch. specific setup and cleanup functions
+ * executing only on the local processor - ashishk@sco.com 
+ */
+
+void kdba_local_arch_setup(void)
+{
+#ifdef	CONFIG_VT_CONSOLE
+	unsigned char c;
+
+	while (kbd_read_status() & KBD_STAT_IBF);
+	kbd_write_command(KBD_CCMD_READ_MODE);
+	mdelay(1);
+	while (kbd_read_status() & KBD_STAT_IBF);
+	while ( !(kbd_read_status() & KBD_STAT_OBF) );
+	c = kbd_read_input();
+	c &= ~KBD_MODE_KBD_INT;
+	while (kbd_read_status() & KBD_STAT_IBF);
+	kbd_write_command(KBD_CCMD_WRITE_MODE);
+	mdelay(1);
+	while (kbd_read_status() & KBD_STAT_IBF);
+	kbd_write_output(c);
+	mdelay(1);
+	while (kbd_read_status() & KBD_STAT_IBF);
+	mdelay(1);
+#endif	/* CONFIG_VT_CONSOLE */
+}
+
+void kdba_local_arch_cleanup(void)
+{
+#ifdef	CONFIG_VT_CONSOLE
+	unsigned char c;
+
+	while (kbd_read_status() & KBD_STAT_IBF);
+	kbd_write_command(KBD_CCMD_READ_MODE);
+	mdelay(1);
+	while (kbd_read_status() & KBD_STAT_IBF);
+	while ( !(kbd_read_status() & KBD_STAT_OBF) );
+	c = kbd_read_input();
+	c |= KBD_MODE_KBD_INT;
+	while (kbd_read_status() & KBD_STAT_IBF);
+	kbd_write_command(KBD_CCMD_WRITE_MODE);
+	mdelay(1);
+	while (kbd_read_status() & KBD_STAT_IBF);
+	kbd_write_output(c);
+	mdelay(1);
+	while (kbd_read_status() & KBD_STAT_IBF);
+	mdelay(1);
+#endif	/* CONFIG_VT_CONSOLE */
+}
Index: 2.4.x-xfs/arch/i386/kdb/kdbasupport.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kdb/kdbasupport.c	Thu Jan  1 10:00:00 1970
+++ 2.4.x-xfs/arch/i386/kdb/kdbasupport.c	Mon Aug  9 13:54:51 2004
@@ -0,0 +1,1406 @@
+/*
+ * Kernel Debugger Architecture Independent Support Functions
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/uaccess.h>
+
+/*
+ * kdba_find_return_1
+ *
+ *	Given a starting point on the stack and symtab data for the
+ *	current function, scan up the stack looking for a return
+ *	address for this function.
+ * Inputs:
+ *	sp	Starting stack pointer for scan
+ *	ss	Start of stack for current process
+ *	symtab	kallsyms symbol data for the function
+ *	assume	When false, do not apply tests that have to assume a branch is valid
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Position on stack of return address, 0 if not found.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	This is sensitive to the calling sequence generated by gcc.
+ */
+
+static kdb_machreg_t
+kdba_find_return_1(kdb_machreg_t sp, kdb_machreg_t ss, const kdb_symtab_t *symtab, int assume)
+{
+	kdb_machreg_t	ret;
+	kdb_symtab_t	caller_symtab;
+	unsigned long	disp8;
+	unsigned long	disp32;
+	unsigned char	code[7];
+#define retaddr(off) code[sizeof(code)+(off)]
+
+	for (;ret = 0, sp & (THREAD_SIZE-1);sp += 4) {
+		if (KDB_DEBUG(ARA)) {
+			kdb_printf("    sp=0x%lx", sp);
+		}
+		if (kdb_getword(&ret, sp, 4))
+			break;
+		kdbnearsym(ret, &caller_symtab);
+		if (KDB_DEBUG(ARA)) {
+			kdb_printf(" ret=");
+			kdb_symbol_print(ret, &caller_symtab, KDB_SP_DEFAULT|KDB_SP_SYMSIZE);
+		}
+		if (!caller_symtab.sym_name) {
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf("\n");
+			}
+			continue;	/* not a valid kernel address */
+		}
+		KDB_STATE_SET(SUPPRESS);
+		if (kdb_getarea(code, ret-sizeof(code)) ||
+		    kdb_getword(&disp32, ret-4, 4) ||
+		    kdb_getword(&disp8, ret-1, 1))
+			continue;	/* not a valid return address */
+		if (retaddr(-5) == 0xe8) {
+			/* call disp32 */
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf(" call disp32");
+			}
+			if (ret + (s32) disp32 == symtab->sym_start) {
+				if (KDB_DEBUG(ARA)) {
+					kdb_printf(" matched\n");
+				}
+				break;		/* call to this function */
+			}
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf(" failed");
+			}
+		} else if (retaddr(-5) == 0xe9) {
+			/* jmp disp32.  I have been told that gcc may
+			 * do function tail optimization and replace
+			 * call with jmp.
+			 */
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf(" jmp disp32\n");
+			}
+			if (ret + (s32) disp32 == symtab->sym_start) {
+				if (KDB_DEBUG(ARA)) {
+					kdb_printf(" matched\n");
+				}
+				break;		/* jmp to this function */
+			}
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf(" failed");
+			}
+		} else if (retaddr(-2) == 0xeb) {
+			/* jmp disp8 */
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf(" jmp disp8\n");
+			}
+			if (ret + (s8) disp8 == symtab->sym_start) {
+				if (KDB_DEBUG(ARA)) {
+					kdb_printf(" matched\n");
+				}
+				break;		/* jmp to this function */
+			}
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf(" failed");
+			}
+		} else if (strcmp(caller_symtab.sym_name, "ret_from_intr") == 0
+		           && ret == caller_symtab.sym_start) {
+			/* ret_from_intr is pushed on stack for interrupts */
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf(" ret_from_intr matched\n");
+			}
+			break;		/* special case, hand crafted frame */
+		} else if (!assume) {
+			/* All following tests cannot validate the target address so they
+			 * must assume that the return address is valid.
+			 */
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf("\n");
+			}
+			continue;
+		} else if (retaddr(-7) == 0xff && retaddr(-6) == 0x14 && retaddr(-5) == 0x85) {
+			/* call *disp32(,%eax,4), used by syscall.
+			 * Cannot calculate address, assume it is valid
+			 * if the current function name starts with
+			 * 'sys_' or 'old_'.
+			 */
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf(" call *0xnnnn(,%%eax,4)");
+			}
+			if (strncmp(symtab->sym_name, "sys_", 4) == 0 ||
+			    strncmp(symtab->sym_name, "old_", 4) == 0) {
+				if (KDB_DEBUG(ARA)) {
+					kdb_printf(" assume valid\n");
+				}
+				break;		/* probably call to this function */
+			}
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf(" failed");
+			}
+		} else if (retaddr(-2) == 0xff &&
+			   ((retaddr(-1) & 0xf8) == 0xd0 || (retaddr(-1) & 0xf8) == 0x10)) {
+			/* call *%reg.  Cannot validate, have to assume
+			 * it is valid.
+			 */
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf(" call *%%reg, assume valid\n");
+			}
+			break;		/* hope it is a call to this function */
+		} else if (retaddr(-3) == 0xff && (retaddr(-2) & 0xf8) == 0x50) {
+			/* call *disp8(%reg).  Cannot validate, have to assume
+			 * it is valid.
+			 */
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf(" call *disp8(%%reg), assume valid\n");
+			}
+			break;		/* hope it is a call to this function */
+		} else if (retaddr(-6) == 0xff && (retaddr(-5) & 0xf8) == 0x90) {
+			/* call *disp32(%reg).  Cannot validate, have to assume
+			 * it is valid.
+			 */
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf(" call *disp32(%%reg), assume valid\n");
+			}
+			break;		/* hope it is a call to this function */
+		}
+		if (KDB_DEBUG(ARA)) {
+			kdb_printf("\n");
+		}
+	}
+	if (KDB_DEBUG(ARA)) {
+		kdb_printf("  end ret=0x%lx sp=0x%lx\n", ret, sp);
+	}
+	if (ret)
+		return sp;
+	return 0;
+}
+
+/*
+ * kdba_find_return
+ *
+ *	Given a starting point on the stack and symtab data for the
+ *	current function, scan up the stack looking for a return
+ *	address for this function.
+ * Inputs:
+ *	sp	Starting stack pointer for scan
+ *	ss	Start of stack for current process
+ *	symtab	kallsyms symbol data for the function
+ * Outputs:
+ *	None.
+ * Returns:
+ *	Position on stack of return address, 0 if not found.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	This is sensitive to the calling sequence generated by gcc.
+ */
+
+static kdb_machreg_t
+kdba_find_return(kdb_machreg_t sp, kdb_machreg_t ss, const kdb_symtab_t *symtab)
+{
+	kdb_machreg_t	ret;
+
+	if (KDB_DEBUG(ARA)) {
+		kdb_printf("  kdba_find_return: start\n");
+	}
+
+	if ((sp & -THREAD_SIZE) != ss) {
+		kdb_printf("    sp is in wrong stack 0x%lx 0x%lx 0x%lx\n", sp, ss, sp & -THREAD_SIZE);
+		return 0;
+	}
+
+	if ((sp & (THREAD_SIZE - 1)) < sizeof(struct task_struct)) {
+		kdb_printf("    sp is inside task_struct\n");
+		return 0;
+	}
+
+	if (KDB_DEBUG(ARA)) {
+		kdb_printf(" kdba_find_return_1(assume==0)\n");
+	}
+	if ((ret = kdba_find_return_1(sp, ss, symtab, 0)))
+		return ret;
+	if (KDB_DEBUG(ARA)) {
+		kdb_printf(" kdba_find_return_1(assume==1)\n");
+	}
+	ret = kdba_find_return_1(sp, ss, symtab, 1);
+	return ret;
+}
+
+/*
+ * kdba_prologue
+ *
+ *	This function analyzes a gcc-generated function prototype
+ *	with or without frame pointers to determine the amount of
+ *	automatic storage and register save storage is used on the
+ *	stack of the target function.  It only counts instructions
+ *	that have been executed up to but excluding the current eip.
+ * Inputs:
+ *	code	Start address of function code to analyze
+ *	pc	Current program counter within function
+ *	sp	Current stack pointer for function
+ *	fp	Current frame pointer for function, may not be valid
+ *	ss	Start of stack for current process.
+ *	caller	1 if looking for data on the caller frame, 0 for callee.
+ * Outputs:
+ *	ar	Activation record, all fields may be set.  fp and oldfp
+ *		are 0 if they cannot be extracted.  return is 0 if the
+ *		code cannot find a valid return address.  args and arg0
+ *		are 0 if the number of arguments cannot be safely
+ *		calculated.
+ * Returns:
+ *	1 if prologue is valid, 0 otherwise.  If pc is 0 treat it as a
+ *	valid prologue to allow bt on wild branches.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ *	A prologue for ia32 generally looks like:
+ *
+ *		pushl  %ebp		[All functions, but only if
+ *		movl   %esp, %ebp	 compiled with frame pointers]
+ *		subl   $auto, %esp	[some functions]
+ *		pushl  %reg		[some functions]
+ *		pushl  %reg		[some functions]
+ *
+ *	FIXME: Mike Galbraith says that gcc 2.95 can generate a slightly
+ *	       different prologue.  No support for gcc 2.95 yet.
+ */
+
+int
+kdba_prologue(const kdb_symtab_t *symtab, kdb_machreg_t pc, kdb_machreg_t sp,
+	      kdb_machreg_t fp, kdb_machreg_t ss, int caller, kdb_ar_t *ar)
+{
+	kdb_machreg_t	ret_p, code = symtab->sym_start;
+	int		oldfp_present = 0, unwound = 0;
+	unsigned char	instruction[6];
+
+	if (KDB_DEBUG(ARA)) {
+		kdb_printf("kdba_prologue: code=0x%lx %s pc=0x%lx sp=0x%lx fp=0x%lx\n",
+		code, symtab->sym_name, pc, sp, fp);
+	}
+
+	/* Special case for wild branches.  Assumes top of stack is return address */
+	if (pc == 0) {
+		memset(ar, 0, sizeof(*ar));
+		ar->setup = 4;
+		ar->end = sp;
+		ar->start = ar->end + 4;
+		kdb_getword(&(ar->ret), sp, 4);
+		if (KDB_DEBUG(ARA)) {
+			kdb_printf("  pc==0: ret=0x%lx\n", ar->ret);
+		}
+		return(1);
+	}
+
+	if (code == 0 || sp & 3 || ss != (sp & -THREAD_SIZE))
+		return(0);
+
+	ar->end = sp;				/* End of activation record +1 */
+
+	/* Special cases galore when the caller pc is within entry.S.
+	 * The return address for these routines is outside the kernel,
+	 * so the normal algorithm to find the frame does not work.
+	 * Hand craft the frame to no setup, regs, locals etc, assume 6
+	 * parameters.
+	 * This list was extracted from entry.S by looking for all call
+	 * instructions that were eventually followed by RESTORE_ALL,
+	 * take the label before each such instruction.
+	 */
+	if (caller &&
+	    (strcmp(symtab->sym_name, "lcall7") == 0 ||
+	     strcmp(symtab->sym_name, "lcall27") == 0 ||
+	     strcmp(symtab->sym_name, "kdb_call") == 0 ||
+	     strcmp(symtab->sym_name, "system_call") == 0 ||
+	     strcmp(symtab->sym_name, "tracesys") == 0 ||
+	     strcmp(symtab->sym_name, "signal_return") == 0 ||
+	     strcmp(symtab->sym_name, "v86_signal_return") == 0 ||
+	     strcmp(symtab->sym_name, "tracesys") == 0 ||
+	     strcmp(symtab->sym_name, "tracesys_exit") == 0 ||
+	     strcmp(symtab->sym_name, "handle_softirq") == 0 ||
+	     strcmp(symtab->sym_name, "reschedule") == 0 ||
+	     strcmp(symtab->sym_name, "error_code") == 0 ||
+	     strcmp(symtab->sym_name, "device_not_available") == 0 ||
+	     strcmp(symtab->sym_name, "nmi") == 0)) {
+		ar->start = ar->end + 6*4;	/* 6 parameters */
+		if ((ar->start & -THREAD_SIZE) != ss)
+			ar->start = 0;
+		return(1);
+	}
+
+	ar->setup = 4;	/* Return address is always on stack */
+
+	/* Kludge.  If we are sitting on 'ret' then the stack has been unwound,
+	 * ignore all the startup code.
+	 */
+	if (kdb_getarea(instruction[0], pc))
+		return(0);
+	if (instruction[0] == 0xc3) {
+		/* ret */
+		unwound = 1;
+	}
+
+	if (kdb_getarea(instruction, code))
+		return(0);
+	if (!unwound && code < pc && instruction[0] == 0x55) {
+		/* pushl %ebp */
+		ar->setup += 4;	/* Frame pointer is on stack */
+		oldfp_present = 1;
+		++code;
+		if (KDB_DEBUG(ARA)) {
+			kdb_printf("  pushl %%ebp\n");
+		}
+		if (code < pc && instruction[0] == 0x89 && instruction[1] == 0xe5) {
+			/* movl %esp,%ebp */
+			if (fp >= sp && (fp & -THREAD_SIZE) == ss)
+				ar->fp = fp;	/* %ebp has been set */
+			code += 2;
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf("  movl %%esp,%%ebp, fp=0x%lx\n", ar->fp);
+			}
+		}
+	}
+
+	if (!unwound && code < pc) {
+		if (instruction[0] == 0x83 && instruction[1] == 0xec) {
+			/* subl $xx,%esp */
+			kdb_getword(&(ar->locals), (unsigned long)(instruction+2), 1);
+			code += 3;
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf("  subl $xx,%%esp, locals=%ld\n", ar->locals);
+			}
+		} else if (instruction[0] == 0x81 && instruction[1] == 0xec) {
+			/* subl $xxxxxxxx,%esp */
+			kdb_getword(&(ar->locals), (unsigned long)(instruction+2), 4);
+			code += 6;
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf("  subl $xxxxxxxx,%%esp, locals=%ld\n", ar->locals);
+			}
+		}
+	}
+
+	while (!unwound && code < pc &&
+	       kdb_getarea(instruction, code) == 0 &&
+	       (instruction[0] & 0xf8) == 0x50) {
+		/* pushl %reg */
+		ar->regs += 4;
+		++code;
+		if (KDB_DEBUG(ARA)) {
+			kdb_printf("  pushl %%reg, regs=%ld\n", ar->regs);
+		}
+	}
+
+	/* Check the return address.  It must point within the kernel
+	 * and the code at that location must be a valid entry sequence.
+	 */
+	if (ar->fp) {
+		ret_p = ar->fp + ar->setup;
+	}
+	else {
+		ret_p = ar->end + ar->regs + ar->locals + ar->setup;
+	}
+	ret_p -= 4;
+	if (KDB_DEBUG(ARA)) {
+		kdb_printf("  ret_p(0)=0x%lx\n", ret_p);
+	}
+	ar->ret = 0;
+	if ((ret_p & -THREAD_SIZE) == ss &&
+	    (ret_p = kdba_find_return(ret_p, ss, symtab))) {
+		kdb_getword(&(ar->ret), ret_p, 4);
+	}
+	if (KDB_DEBUG(ARA)) {
+		kdb_printf("  ret_p(1)=0x%lx ret=0x%lx\n", ret_p, ar->ret);
+	}
+	if (ar->ret) {
+		ar->fp = ret_p - ar->setup + 4;	/* "accurate" fp */
+		ar->start = ret_p + 4;
+		if (KDB_DEBUG(ARA)) {
+			kdb_printf("  fp=0x%lx start=0x%lx\n", ar->fp, ar->start);
+		}
+	}
+	if (oldfp_present) {
+		if (ar->fp)
+			kdb_getword(&(ar->oldfp), ar->fp, 4);
+		if (KDB_DEBUG(ARA)) {
+			kdb_printf("  oldfp=0x%lx", ar->oldfp);
+		}
+		if (ar->oldfp <= ar->fp || (ar->oldfp & -THREAD_SIZE) != ss) {
+			ar->oldfp = 0;
+			if (KDB_DEBUG(ARA)) {
+				kdb_printf(" (out of range)");
+			}
+		}
+		if (KDB_DEBUG(ARA)) {
+			kdb_printf("\n");
+		}
+	}
+	return(1);
+}
+
+kdb_machreg_t
+kdba_getdr6(void)
+{
+	return kdba_getdr(6);
+}
+
+kdb_machreg_t
+kdba_getdr7(void)
+{
+	return kdba_getdr(7);
+}
+
+void
+kdba_putdr6(kdb_machreg_t contents)
+{
+	kdba_putdr(6, contents);
+}
+
+static void
+kdba_putdr7(kdb_machreg_t contents)
+{
+	kdba_putdr(7, contents);
+}
+
+void
+kdba_installdbreg(kdb_bp_t *bp)
+{
+	kdb_machreg_t	dr7;
+
+	dr7 = kdba_getdr7();
+
+	kdba_putdr(bp->bp_hard->bph_reg, bp->bp_addr);
+
+	dr7 |= DR7_GE;
+	if (cpu_has_de)
+		set_in_cr4(X86_CR4_DE);
+
+	switch (bp->bp_hard->bph_reg){
+	case 0:
+		DR7_RW0SET(dr7,bp->bp_hard->bph_mode);
+		DR7_LEN0SET(dr7,bp->bp_hard->bph_length);
+		DR7_G0SET(dr7);
+		break;
+	case 1:
+		DR7_RW1SET(dr7,bp->bp_hard->bph_mode);
+		DR7_LEN1SET(dr7,bp->bp_hard->bph_length);
+		DR7_G1SET(dr7);
+		break;
+	case 2:
+		DR7_RW2SET(dr7,bp->bp_hard->bph_mode);
+		DR7_LEN2SET(dr7,bp->bp_hard->bph_length);
+		DR7_G2SET(dr7);
+		break;
+	case 3:
+		DR7_RW3SET(dr7,bp->bp_hard->bph_mode);
+		DR7_LEN3SET(dr7,bp->bp_hard->bph_length);
+		DR7_G3SET(dr7);
+		break;
+	default:
+		kdb_printf("kdb: Bad debug register!! %ld\n",
+			   bp->bp_hard->bph_reg);
+		break;
+	}
+
+	kdba_putdr7(dr7);
+	return;
+}
+
+void
+kdba_removedbreg(kdb_bp_t *bp)
+{
+	int 		regnum;
+	kdb_machreg_t	dr7;
+
+	if (!bp->bp_hard)
+		return;
+
+	regnum = bp->bp_hard->bph_reg;
+
+	dr7 = kdba_getdr7();
+
+	kdba_putdr(regnum, 0);
+
+	switch (regnum) {
+	case 0:
+		DR7_G0CLR(dr7);
+		DR7_L0CLR(dr7);
+		break;
+	case 1:
+		DR7_G1CLR(dr7);
+		DR7_L1CLR(dr7);
+		break;
+	case 2:
+		DR7_G2CLR(dr7);
+		DR7_L2CLR(dr7);
+		break;
+	case 3:
+		DR7_G3CLR(dr7);
+		DR7_L3CLR(dr7);
+		break;
+	default:
+		kdb_printf("kdb: Bad debug register!! %d\n", regnum);
+		break;
+	}
+
+	kdba_putdr7(dr7);
+}
+
+kdb_machreg_t
+kdba_getdr(int regnum)
+{
+	kdb_machreg_t contents = 0;
+	switch(regnum) {
+	case 0:
+		__asm__ ("movl %%db0,%0\n\t":"=r"(contents));
+		break;
+	case 1:
+		__asm__ ("movl %%db1,%0\n\t":"=r"(contents));
+		break;
+	case 2:
+		__asm__ ("movl %%db2,%0\n\t":"=r"(contents));
+		break;
+	case 3:
+		__asm__ ("movl %%db3,%0\n\t":"=r"(contents));
+		break;
+	case 4:
+	case 5:
+		break;
+	case 6:
+		__asm__ ("movl %%db6,%0\n\t":"=r"(contents));
+		break;
+	case 7:
+		__asm__ ("movl %%db7,%0\n\t":"=r"(contents));
+		break;
+	default:
+		break;
+	}
+
+	return contents;
+}
+
+
+kdb_machreg_t
+kdb_getcr(int regnum)
+{
+	kdb_machreg_t contents = 0;
+	switch(regnum) {
+	case 0:
+		__asm__ ("movl %%cr0,%0\n\t":"=r"(contents));
+		break;
+	case 1:
+		break;
+	case 2:
+		__asm__ ("movl %%cr2,%0\n\t":"=r"(contents));
+		break;
+	case 3:
+		__asm__ ("movl %%cr3,%0\n\t":"=r"(contents));
+		break;
+	case 4:
+		__asm__ ("movl %%cr4,%0\n\t":"=r"(contents));
+		break;
+	default:
+		break;
+	}
+
+	return contents;
+}
+
+void
+kdba_putdr(int regnum, kdb_machreg_t contents)
+{
+	switch(regnum) {
+	case 0:
+		__asm__ ("movl %0,%%db0\n\t"::"r"(contents));
+		break;
+	case 1:
+		__asm__ ("movl %0,%%db1\n\t"::"r"(contents));
+		break;
+	case 2:
+		__asm__ ("movl %0,%%db2\n\t"::"r"(contents));
+		break;
+	case 3:
+		__asm__ ("movl %0,%%db3\n\t"::"r"(contents));
+		break;
+	case 4:
+	case 5:
+		break;
+	case 6:
+		__asm__ ("movl %0,%%db6\n\t"::"r"(contents));
+		break;
+	case 7:
+		__asm__ ("movl %0,%%db7\n\t"::"r"(contents));
+		break;
+	default:
+		break;
+	}
+}
+
+/*
+ * kdba_getregcontents
+ *
+ *	Return the contents of the register specified by the
+ *	input string argument.   Return an error if the string
+ *	does not match a machine register.
+ *
+ *	The following pseudo register names are supported:
+ *	   &regs	 - Prints address of exception frame
+ *	   kesp		 - Prints kernel stack pointer at time of fault
+ *	   cesp		 - Prints current kernel stack pointer, inside kdb
+ *	   ceflags	 - Prints current flags, inside kdb
+ *	   %<regname>	 - Uses the value of the registers at the
+ *			   last time the user process entered kernel
+ *			   mode, instead of the registers at the time
+ *			   kdb was entered.
+ *
+ * Parameters:
+ *	regname		Pointer to string naming register
+ *	regs		Pointer to structure containing registers.
+ * Outputs:
+ *	*contents	Pointer to unsigned long to recieve register contents
+ * Returns:
+ *	0		Success
+ *	KDB_BADREG	Invalid register name
+ * Locking:
+ * 	None.
+ * Remarks:
+ * 	If kdb was entered via an interrupt from the kernel itself then
+ *	ss and esp are *not* on the stack.
+ */
+
+static struct kdbregs {
+	char   *reg_name;
+	size_t	reg_offset;
+} kdbreglist[] = {
+	{ "eax",	offsetof(struct pt_regs, eax) },
+	{ "ebx",	offsetof(struct pt_regs, ebx) },
+	{ "ecx",	offsetof(struct pt_regs, ecx) },
+	{ "edx",	offsetof(struct pt_regs, edx) },
+
+	{ "esi",	offsetof(struct pt_regs, esi) },
+	{ "edi",	offsetof(struct pt_regs, edi) },
+	{ "esp",	offsetof(struct pt_regs, esp) },
+	{ "eip",	offsetof(struct pt_regs, eip) },
+
+	{ "ebp",	offsetof(struct pt_regs, ebp) },
+	{ "xss", 	offsetof(struct pt_regs, xss) },
+	{ "xcs",	offsetof(struct pt_regs, xcs) },
+	{ "eflags", 	offsetof(struct pt_regs, eflags) },
+
+	{ "xds", 	offsetof(struct pt_regs, xds) },
+	{ "xes", 	offsetof(struct pt_regs, xes) },
+	{ "origeax",	offsetof(struct pt_regs, orig_eax) },
+
+};
+
+static const int nkdbreglist = sizeof(kdbreglist) / sizeof(struct kdbregs);
+
+static struct kdbregs dbreglist[] = {
+	{ "dr0", 	0 },
+	{ "dr1", 	1 },
+	{ "dr2",	2 },
+	{ "dr3", 	3 },
+	{ "dr6", 	6 },
+	{ "dr7",	7 },
+};
+
+static const int ndbreglist = sizeof(dbreglist) / sizeof(struct kdbregs);
+
+int
+kdba_getregcontents(const char *regname,
+		    struct pt_regs *regs,
+		    kdb_machreg_t *contents)
+{
+	int i;
+
+	if (strcmp(regname, "cesp") == 0) {
+		asm volatile("movl %%esp,%0":"=m" (*contents));
+		return 0;
+	}
+
+	if (strcmp(regname, "ceflags") == 0) {
+		int flags;
+		__save_flags(flags);
+		*contents = flags;
+		return 0;
+	}
+
+	if (regname[0] == '%') {
+		/* User registers:  %%e[a-c]x, etc */
+		regname++;
+		regs = (struct pt_regs *)
+			(kdb_current_task->thread.esp0 - sizeof(struct pt_regs));
+	}
+
+	for (i=0; i<ndbreglist; i++) {
+		if (strnicmp(dbreglist[i].reg_name,
+			     regname,
+			     strlen(regname)) == 0)
+			break;
+	}
+
+	if ((i < ndbreglist)
+	 && (strlen(dbreglist[i].reg_name) == strlen(regname))) {
+		*contents = kdba_getdr(dbreglist[i].reg_offset);
+		return 0;
+	}
+
+	if (!regs) {
+		kdb_printf("%s: pt_regs not available\n", __FUNCTION__);
+		return KDB_BADREG;
+	}
+
+	if (strcmp(regname, "&regs") == 0) {
+		*contents = (unsigned long)regs;
+		return 0;
+	}
+
+	if (strcmp(regname, "kesp") == 0) {
+		*contents = (unsigned long)regs + sizeof(struct pt_regs);
+		if ((regs->xcs & 0xffff) == __KERNEL_CS) {
+			/* esp and ss are not on stack */
+			*contents -= 2*4;
+		}
+		return 0;
+	}
+
+	for (i=0; i<nkdbreglist; i++) {
+		if (strnicmp(kdbreglist[i].reg_name,
+			     regname,
+			     strlen(regname)) == 0)
+			break;
+	}
+
+	if ((i < nkdbreglist)
+	 && (strlen(kdbreglist[i].reg_name) == strlen(regname))) {
+		if ((regs->xcs & 0xffff) == __KERNEL_CS) {
+			/* No cpl switch, esp and ss are not on stack */
+			if (strcmp(kdbreglist[i].reg_name, "esp") == 0) {
+				*contents = (kdb_machreg_t)regs +
+					sizeof(struct pt_regs) - 2*4;
+				return(0);
+			}
+			if (strcmp(kdbreglist[i].reg_name, "xss") == 0) {
+				asm volatile(
+					"pushl %%ss\n"
+					"popl %0\n"
+					:"=m" (*contents));
+				return(0);
+			}
+		}
+		*contents = *(unsigned long *)((unsigned long)regs +
+				kdbreglist[i].reg_offset);
+		return(0);
+	}
+
+	return KDB_BADREG;
+}
+
+/*
+ * kdba_setregcontents
+ *
+ *	Set the contents of the register specified by the
+ *	input string argument.   Return an error if the string
+ *	does not match a machine register.
+ *
+ *	Supports modification of user-mode registers via
+ *	%<register-name>
+ *
+ * Parameters:
+ *	regname		Pointer to string naming register
+ *	regs		Pointer to structure containing registers.
+ *	contents	Unsigned long containing new register contents
+ * Outputs:
+ * Returns:
+ *	0		Success
+ *	KDB_BADREG	Invalid register name
+ * Locking:
+ * 	None.
+ * Remarks:
+ */
+
+int
+kdba_setregcontents(const char *regname,
+		  struct pt_regs *regs,
+		  unsigned long contents)
+{
+	int i;
+
+	if (regname[0] == '%') {
+		regname++;
+		regs = (struct pt_regs *)
+			(kdb_current_task->thread.esp0 - sizeof(struct pt_regs));
+	}
+
+	for (i=0; i<ndbreglist; i++) {
+		if (strnicmp(dbreglist[i].reg_name,
+			     regname,
+			     strlen(regname)) == 0)
+			break;
+	}
+
+	if ((i < ndbreglist)
+	 && (strlen(dbreglist[i].reg_name) == strlen(regname))) {
+		kdba_putdr(dbreglist[i].reg_offset, contents);
+		return 0;
+	}
+
+	if (!regs) {
+		kdb_printf("%s: pt_regs not available\n", __FUNCTION__);
+		return KDB_BADREG;
+	}
+
+	for (i=0; i<nkdbreglist; i++) {
+		if (strnicmp(kdbreglist[i].reg_name,
+			     regname,
+			     strlen(regname)) == 0)
+			break;
+	}
+
+	if ((i < nkdbreglist)
+	 && (strlen(kdbreglist[i].reg_name) == strlen(regname))) {
+		*(unsigned long *)((unsigned long)regs
+				   + kdbreglist[i].reg_offset) = contents;
+		return 0;
+	}
+
+	return KDB_BADREG;
+}
+
+/*
+ * kdba_dumpregs
+ *
+ *	Dump the specified register set to the display.
+ *
+ * Parameters:
+ *	regs		Pointer to structure containing registers.
+ *	type		Character string identifying register set to dump
+ *	extra		string further identifying register (optional)
+ * Outputs:
+ * Returns:
+ *	0		Success
+ * Locking:
+ * 	None.
+ * Remarks:
+ *	This function will dump the general register set if the type
+ *	argument is NULL (struct pt_regs).   The alternate register
+ *	set types supported by this function:
+ *
+ *	d 		Debug registers
+ *	c		Control registers
+ *	u		User registers at most recent entry to kernel
+ *			for the process currently selected with "pid" command.
+ * Following not yet implemented:
+ *	m		Model Specific Registers (extra defines register #)
+ *	r		Memory Type Range Registers (extra defines register)
+ */
+
+int
+kdba_dumpregs(struct pt_regs *regs,
+	    const char *type,
+	    const char *extra)
+{
+	int i;
+	int count = 0;
+
+	if (type
+	 && (type[0] == 'u')) {
+		type = NULL;
+		regs = (struct pt_regs *)
+			(kdb_current_task->thread.esp0 - sizeof(struct pt_regs));
+	}
+
+	if (type == NULL) {
+		struct kdbregs *rlp;
+		kdb_machreg_t contents;
+
+		if (!regs) {
+			kdb_printf("%s: pt_regs not available\n", __FUNCTION__);
+			return KDB_BADREG;
+		}
+
+		for (i=0, rlp=kdbreglist; i<nkdbreglist; i++,rlp++) {
+			kdb_printf("%s = ", rlp->reg_name);
+			kdba_getregcontents(rlp->reg_name, regs, &contents);
+			kdb_printf("0x%08lx ", contents);
+			if ((++count % 4) == 0)
+				kdb_printf("\n");
+		}
+
+		kdb_printf("&regs = 0x%p\n", regs);
+
+		return 0;
+	}
+
+	switch (type[0]) {
+	case 'd':
+	{
+		unsigned long dr[8];
+
+		for(i=0; i<8; i++) {
+			if ((i == 4) || (i == 5)) continue;
+			dr[i] = kdba_getdr(i);
+		}
+		kdb_printf("dr0 = 0x%08lx  dr1 = 0x%08lx  dr2 = 0x%08lx  dr3 = 0x%08lx\n",
+			   dr[0], dr[1], dr[2], dr[3]);
+		kdb_printf("dr6 = 0x%08lx  dr7 = 0x%08lx\n",
+			   dr[6], dr[7]);
+		return 0;
+	}
+	case 'c':
+	{
+		unsigned long cr[5];
+
+		for (i=0; i<5; i++) {
+			cr[i] = kdb_getcr(i);
+		}
+		kdb_printf("cr0 = 0x%08lx  cr1 = 0x%08lx  cr2 = 0x%08lx  cr3 = 0x%08lx\ncr4 = 0x%08lx\n",
+			   cr[0], cr[1], cr[2], cr[3], cr[4]);
+		return 0;
+	}
+	case 'm':
+		break;
+	case 'r':
+		break;
+	default:
+		return KDB_BADREG;
+	}
+
+	/* NOTREACHED */
+	return 0;
+}
+
+kdb_machreg_t
+kdba_getpc(struct pt_regs *regs)
+{
+	return regs ? regs->eip : 0;
+}
+
+int
+kdba_setpc(struct pt_regs *regs, kdb_machreg_t newpc)
+{
+	if (KDB_NULL_REGS(regs))
+		return KDB_BADREG;
+	regs->eip = newpc;
+	KDB_STATE_SET(IP_ADJUSTED);
+	return 0;
+}
+
+/*
+ * kdba_main_loop
+ *
+ *	Do any architecture specific set up before entering the main kdb loop.
+ *	The primary function of this routine is to make all processes look the
+ *	same to kdb, kdb must be able to list a process without worrying if the
+ *	process is running or blocked, so make all process look as though they
+ *	are blocked.
+ *
+ * Inputs:
+ *	reason		The reason KDB was invoked
+ *	error		The hardware-defined error code
+ *	error2		kdb's current reason code.  Initially error but can change
+ *			acording to kdb state.
+ *	db_result	Result from break or debug point.
+ *	regs		The exception frame at time of fault/breakpoint.  If reason
+ *			is KDB_REASON_SILENT then regs is NULL, otherwise it should
+ *			always be valid.
+ * Returns:
+ *	0	KDB was invoked for an event which it wasn't responsible
+ *	1	KDB handled the event for which it was invoked.
+ * Outputs:
+ *	Sets eip and esp in current->thread.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	none.
+ */
+
+int
+kdba_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,
+	       kdb_dbtrap_t db_result, struct pt_regs *regs)
+{
+	int ret;
+	kdb_save_running(regs);
+	ret = kdb_main_loop(reason, reason2, error, db_result, regs);
+	kdb_unsave_running(regs);
+	return ret;
+}
+
+void
+kdba_disableint(kdb_intstate_t *state)
+{
+	int *fp = (int *)state;
+	int   flags;
+
+	__save_flags(flags);
+	__cli();
+
+	*fp = flags;
+}
+
+void
+kdba_restoreint(kdb_intstate_t *state)
+{
+	int flags = *(int *)state;
+	__restore_flags(flags);
+}
+
+void
+kdba_setsinglestep(struct pt_regs *regs)
+{
+	if (KDB_NULL_REGS(regs))
+		return;
+	if (regs->eflags & EF_IE)
+		KDB_STATE_SET(A_IF);
+	else
+		KDB_STATE_CLEAR(A_IF);
+	regs->eflags = (regs->eflags | EF_TF) & ~EF_IE;
+}
+
+void
+kdba_clearsinglestep(struct pt_regs *regs)
+{
+	if (KDB_NULL_REGS(regs))
+		return;
+	if (KDB_STATE(A_IF))
+		regs->eflags |= EF_IE;
+	else
+		regs->eflags &= ~EF_IE;
+}
+
+#ifdef KDB_HAVE_LONGJMP
+int
+kdba_setjmp(kdb_jmp_buf *jb)
+{
+#if defined(CONFIG_FRAME_POINTER)
+	__asm__ ("movl 8(%esp), %eax\n\t"
+		 "movl %ebx, 0(%eax)\n\t"
+		 "movl %esi, 4(%eax)\n\t"
+		 "movl %edi, 8(%eax)\n\t"
+		 "movl (%esp), %ecx\n\t"
+		 "movl %ecx, 12(%eax)\n\t"
+		 "leal 8(%esp), %ecx\n\t"
+		 "movl %ecx, 16(%eax)\n\t"
+		 "movl 4(%esp), %ecx\n\t"
+		 "movl %ecx, 20(%eax)\n\t");
+#else	 /* CONFIG_FRAME_POINTER */
+	__asm__ ("movl 4(%esp), %eax\n\t"
+		 "movl %ebx, 0(%eax)\n\t"
+		 "movl %esi, 4(%eax)\n\t"
+		 "movl %edi, 8(%eax)\n\t"
+		 "movl %ebp, 12(%eax)\n\t"
+		 "leal 4(%esp), %ecx\n\t"
+		 "movl %ecx, 16(%eax)\n\t"
+		 "movl 0(%esp), %ecx\n\t"
+		 "movl %ecx, 20(%eax)\n\t");
+#endif   /* CONFIG_FRAME_POINTER */
+	return 0;
+}
+
+void
+kdba_longjmp(kdb_jmp_buf *jb, int reason)
+{
+#if defined(CONFIG_FRAME_POINTER)
+	__asm__("movl 8(%esp), %ecx\n\t"
+		"movl 12(%esp), %eax\n\t"
+		"movl 20(%ecx), %edx\n\t"
+		"movl 0(%ecx), %ebx\n\t"
+		"movl 4(%ecx), %esi\n\t"
+		"movl 8(%ecx), %edi\n\t"
+		"movl 12(%ecx), %ebp\n\t"
+		"movl 16(%ecx), %esp\n\t"
+		"jmp *%edx\n");
+#else    /* CONFIG_FRAME_POINTER */
+	__asm__("movl 4(%esp), %ecx\n\t"
+		"movl 8(%esp), %eax\n\t"
+		"movl 20(%ecx), %edx\n\t"
+		"movl 0(%ecx), %ebx\n\t"
+		"movl 4(%ecx), %esi\n\t"
+		"movl 8(%ecx), %edi\n\t"
+		"movl 12(%ecx), %ebp\n\t"
+		"movl 16(%ecx), %esp\n\t"
+		"jmp *%edx\n");
+#endif	 /* CONFIG_FRAME_POINTER */
+}
+#endif	/* KDB_HAVE_LONGJMP */
+
+
+/*
+ * kdba_enable_mce
+ *
+ *	This function is called once on each CPU to enable machine
+ *	check exception handling.
+ *
+ * Inputs:
+ *	None.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *
+ */
+
+void
+kdba_enable_mce(void)
+{
+	/* No longer required, arch/i386/kernel/bluesmoke.c does the job now */
+}
+
+/*
+ * kdba_enable_lbr
+ *
+ *	Enable last branch recording.
+ *
+ * Parameters:
+ *	None.
+ * Returns:
+ *	None
+ * Locking:
+ *	None
+ * Remarks:
+ *	None.
+ */
+
+static unsigned char lbr_warned;
+
+void
+kdba_enable_lbr(void)
+{
+	u32  lv, hv;
+
+	if (!test_bit(X86_FEATURE_MCA, boot_cpu_data.x86_capability)) {
+		if (lbr_warned) {
+			kdb_printf("kdb: machine does not support last branch recording\n");
+			lbr_warned = 1;
+		}
+		return;
+	}
+	rdmsr(MSR_IA32_DEBUGCTLMSR, lv, hv);
+	lv |= 0x1;	/* Set LBR enable */
+	wrmsr(MSR_IA32_DEBUGCTLMSR, lv, hv);
+}
+
+/*
+ * kdba_disable_lbr
+ *
+ *	disable last branch recording.
+ *
+ * Parameters:
+ *	None.
+ * Returns:
+ *	None
+ * Locking:
+ *	None
+ * Remarks:
+ *	None.
+ */
+
+void
+kdba_disable_lbr(void)
+{
+	u32  lv, hv;
+
+	if (!test_bit(X86_FEATURE_MCA, boot_cpu_data.x86_capability)) {
+		if (lbr_warned) {
+			kdb_printf("kdb: machine does not support last branch recording\n");
+			lbr_warned = 1;
+		}
+		return;
+	}
+	rdmsr(MSR_IA32_DEBUGCTLMSR, lv, hv);
+	lv &= ~0x1;	/* Set LBR disable */
+	wrmsr(MSR_IA32_DEBUGCTLMSR, lv, hv);
+}
+
+/*
+ * kdba_print_lbr
+ *
+ *	Print last branch and last exception addresses
+ *
+ * Parameters:
+ *	None.
+ * Returns:
+ *	None
+ * Locking:
+ *	None
+ * Remarks:
+ *	None.
+ */
+
+void
+kdba_print_lbr(void)
+{
+	u32  from, to, dummy;
+
+	if (!test_bit(X86_FEATURE_MCA, boot_cpu_data.x86_capability))
+		return;
+
+	rdmsr(MSR_IA32_LASTBRANCHFROMIP, from, dummy);
+	rdmsr(MSR_IA32_LASTBRANCHTOIP, to, dummy);
+	kdb_printf("Last Branch IP, from: ");
+	kdb_symbol_print(from, NULL, KDB_SP_DEFAULT);
+	kdb_printf(" to: ");
+	kdb_symbol_print(to, NULL, KDB_SP_DEFAULT);
+	kdb_printf("\n");
+	rdmsr(MSR_IA32_LASTINTFROMIP, from, dummy);
+	rdmsr(MSR_IA32_LASTINTTOIP, to, dummy);
+	kdb_printf("Last Int IP, from: ");
+	kdb_symbol_print(from, NULL, KDB_SP_DEFAULT);
+	kdb_printf(" to: ");
+	kdb_symbol_print(to, NULL, KDB_SP_DEFAULT);
+	kdb_printf("\n");
+}
+
+/*
+ * kdba_pt_regs
+ *
+ *	Format a struct pt_regs
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ *	If no address is supplied, it uses regs.
+ */
+
+static int
+kdba_pt_regs(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int diag;
+	kdb_machreg_t addr;
+	long offset = 0;
+	int nextarg;
+	struct pt_regs *p;
+	static const char *fmt = "  %-11.11s 0x%lx\n";
+
+	if (argc == 0) {
+		addr = (kdb_machreg_t) regs;
+	} else if (argc == 1) {
+		nextarg = 1;
+		diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+		if (diag)
+			return diag;
+	} else {
+		return KDB_ARGCOUNT;
+	}
+
+	p = (struct pt_regs *) addr;
+	kdb_printf("struct pt_regs %p-%p\n", p, (unsigned char *)p + sizeof(*p) - 1);
+	kdb_print_nameval("ebx", p->ebx);
+	kdb_print_nameval("ecx", p->ecx);
+	kdb_print_nameval("edx", p->edx);
+	kdb_print_nameval("esi", p->esi);
+	kdb_print_nameval("edi", p->edi);
+	kdb_print_nameval("ebp", p->ebp);
+	kdb_print_nameval("eax", p->eax);
+	kdb_printf(fmt, "xds", p->xds);
+	kdb_printf(fmt, "xes", p->xes);
+	kdb_print_nameval("orig_eax", p->orig_eax);
+	kdb_print_nameval("eip", p->eip);
+	kdb_printf(fmt, "xcs", p->xcs);
+	kdb_printf(fmt, "eflags", p->eflags);
+	kdb_printf(fmt, "esp", p->esp);
+	kdb_printf(fmt, "xss", p->xss);
+	return 0;
+}
+
+/*
+ * kdba_init
+ *
+ * 	Architecture specific initialization.
+ *
+ * Parameters:
+ *	None.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	None.
+ */
+
+void __init
+kdba_init(void)
+{
+	kdba_enable_lbr();
+	kdb_register("pt_regs", kdba_pt_regs, "address", "Format struct pt_regs", 0);
+
+	return;
+}
+
+/*
+ * kdba_adjust_ip
+ *
+ * 	Architecture specific adjustment of instruction pointer before leaving
+ *	kdb.
+ *
+ * Parameters:
+ *	reason		The reason KDB was invoked
+ *	error		The hardware-defined error code
+ *	regs		The exception frame at time of fault/breakpoint.  If reason
+ *			is KDB_REASON_SILENT then regs is NULL, otherwise it should
+ *			always be valid.
+ * Returns:
+ *	None.
+ * Locking:
+ *	None.
+ * Remarks:
+ *	noop on ix86.
+ */
+
+void
+kdba_adjust_ip(kdb_reason_t reason, int error, struct pt_regs *regs)
+{
+	return;
+}
Index: 2.4.x-xfs/arch/i386/kernel/bluesmoke.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kernel/bluesmoke.c	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/arch/i386/kernel/bluesmoke.c	Mon Aug  9 13:54:51 2004
@@ -4,6 +4,9 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/config.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif	/* CONFIG_KDB */
 #include <asm/processor.h> 
 #include <asm/msr.h>
 
@@ -109,6 +112,9 @@
 asmlinkage void do_machine_check(struct pt_regs * regs, long error_code)
 {
 	machine_check_vector(regs, error_code);
+#ifdef	CONFIG_KDB
+	(void)kdb(KDB_REASON_NMI, error_code, regs);
+#endif	/* CONFIG_KDB */
 }
 
 /*
Index: 2.4.x-xfs/arch/i386/kernel/entry.S
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kernel/entry.S	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/arch/i386/kernel/entry.S	Mon Aug  9 13:54:51 2004
@@ -192,6 +192,18 @@
 	jne tracesys_exit
 	jmp	ret_from_sys_call
 
+#if defined(CONFIG_KDB)
+ENTRY(kdb_call)
+	pushl %eax              # save orig EAX
+	SAVE_ALL
+	pushl %esp              # struct pt_regs
+	pushl $0                # error_code
+	pushl $7                # KDB_REASON_ENTRY
+	call  SYMBOL_NAME(kdb)
+	addl  $12,%esp          # remove args
+	RESTORE_ALL
+#endif
+
 /*
  * Return to user mode is not as complex as all this looks,
  * but we want the default path for a system call return to
@@ -388,6 +400,22 @@
 	pushl $ SYMBOL_NAME(do_alignment_check)
 	jmp error_code
 
+#if defined(CONFIG_KDB)
+ENTRY(page_fault_mca)
+	pushl %ecx
+	pushl %edx
+	pushl %eax
+	movl  $473,%ecx
+	rdmsr
+	andl  $0xfffffffe,%eax		/* Disable last branch recording */
+	wrmsr
+	popl  %eax
+	popl  %edx
+	popl  %ecx
+	pushl $ SYMBOL_NAME(do_page_fault)
+	jmp error_code
+#endif
+
 ENTRY(page_fault)
 	pushl $ SYMBOL_NAME(do_page_fault)
 	jmp error_code
Index: 2.4.x-xfs/arch/i386/kernel/i8259.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kernel/i8259.c	Mon Aug  9 13:52:18 2004
+++ 2.4.x-xfs/arch/i386/kernel/i8259.c	Mon Aug  9 13:54:51 2004
@@ -457,7 +457,11 @@
 	 */
 	for (i = 0; i < NR_IRQS; i++) {
 		int vector = FIRST_EXTERNAL_VECTOR + i;
-		if (vector != SYSCALL_VECTOR) 
+		if ((vector != SYSCALL_VECTOR) 
+#if defined(CONFIG_KDB)
+		 && (vector != KDBENTER_VECTOR)
+#endif
+						)
 			set_intr_gate(vector, interrupt[i]);
 	}
 
Index: 2.4.x-xfs/arch/i386/kernel/io_apic.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kernel/io_apic.c	Mon Aug  9 13:52:18 2004
+++ 2.4.x-xfs/arch/i386/kernel/io_apic.c	Mon Aug  9 13:54:51 2004
@@ -27,6 +27,9 @@
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/config.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif	/* CONFIG_KDB */
 #include <linux/smp_lock.h>
 #include <linux/mc146818rtc.h>
 #include <linux/acpi.h>
@@ -607,6 +610,10 @@
 	current_vector += 8;
 	if (current_vector == SYSCALL_VECTOR)
 		goto next;
+#ifdef	CONFIG_KDB
+	if (current_vector == KDBENTER_VECTOR)
+		goto next;
+#endif	/* CONFIG_KDB */
 
 	if (current_vector > FIRST_SYSTEM_VECTOR) {
 		offset++;
Index: 2.4.x-xfs/arch/i386/kernel/irq.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kernel/irq.c	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/arch/i386/kernel/irq.c	Mon Aug  9 13:54:51 2004
@@ -33,6 +33,9 @@
 #include <linux/irq.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif	/* CONFIG_KDB */
 
 #include <asm/atomic.h>
 #include <asm/io.h>
@@ -317,6 +320,11 @@
 
 static inline void get_irqlock(int cpu)
 {
+#ifdef	CONFIG_KDB
+	static int kdb_rate;
+	if (KDB_IS_RUNNING() && kdb_rate++ < 10)
+		kdb_printf("Warning: get_irqlock on cpu %d while kdb is running, may hang\n", smp_processor_id());
+#endif	/* CONFIG_KDB */
 	if (test_and_set_bit(0,&global_irq_lock)) {
 		/* do we already hold the lock? */
 		if ((unsigned char) cpu == global_irq_holder)
Index: 2.4.x-xfs/arch/i386/kernel/nmi.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kernel/nmi.c	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/arch/i386/kernel/nmi.c	Mon Aug  9 13:54:51 2004
@@ -20,6 +20,9 @@
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
 #include <linux/kernel_stat.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif	/* CONFIG_KDB */
 
 #include <asm/smp.h>
 #include <asm/mtrr.h>
@@ -364,6 +367,9 @@
 			printk("NMI Watchdog detected LOCKUP on CPU%d, eip %08lx, registers:\n", cpu, regs->eip);
 			show_registers(regs);
 			printk("console shuts up ...\n");
+#ifdef	CONFIG_KDB
+			kdb(KDB_REASON_NMI, 0, regs);
+#endif	/* CONFIG_KDB */
 			console_silent();
 			spin_unlock(&nmi_print_lock);
 			bust_spinlocks(0);
Index: 2.4.x-xfs/arch/i386/kernel/process.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kernel/process.c	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/arch/i386/kernel/process.c	Mon Aug  9 13:54:51 2004
@@ -33,6 +33,9 @@
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/mc146818rtc.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif	/* CONFIG_KDB */
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -400,6 +403,14 @@
 	 * Stop all CPUs and turn off local APICs and the IO-APIC, so
 	 * other OSs see a clean IRQ state.
 	 */
+#ifdef	CONFIG_KDB
+	/*
+	 * If this restart is occuring while kdb is running (e.g. reboot
+	 * command), the other CPU's are already stopped.  Don't try to
+	 * stop them yet again.
+	 */
+	if (!KDB_IS_RUNNING())
+#endif	/* CONFIG_KDB */
 	smp_send_stop();
 #elif CONFIG_X86_LOCAL_APIC
 	if (cpu_has_apic) {
Index: 2.4.x-xfs/arch/i386/kernel/smp.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kernel/smp.c	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/arch/i386/kernel/smp.c	Mon Aug  9 13:54:51 2004
@@ -23,6 +23,11 @@
 #include <asm/pgalloc.h>
 #include <asm/smpboot.h>
 
+#include <linux/config.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif	/* CONFIG_KDB */
+
 /*
  *	Some notes on x86 processor bugs affecting SMP operation:
  *
@@ -144,6 +149,15 @@
 	 */
 	cfg = __prepare_ICR(shortcut, vector);
 
+#ifdef	CONFIG_KDB
+	if (vector == KDB_VECTOR) {
+		/*
+		 * Setup KDB IPI to be delivered as an NMI
+		 */
+		cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+	}
+#endif	/* CONFIG_KDB */
+
 	/*
 	 * Send the IPI. The write to APIC_ICR fires this off.
 	 */
@@ -224,6 +238,15 @@
 			 * program the ICR 
 			 */
 			cfg = __prepare_ICR(0, vector);
+
+#ifdef	CONFIG_KDB
+			if (vector == KDB_VECTOR) {
+				/*
+				 * Setup KDB IPI to be delivered as an NMI
+				 */
+				cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+			}
+#endif	/* CONFIG_KDB */
 			
 			/*
 			 * Send the IPI. The write to APIC_ICR fires this off.
@@ -491,6 +514,15 @@
 	do_flush_tlb_all_local();
 }
 
+#ifdef	CONFIG_KDB
+void
+smp_kdb_stop(void)
+{
+	if (!KDB_FLAG(NOIPI))
+		send_IPI_allbutself(KDB_VECTOR);
+}
+#endif	/* CONFIG_KDB */
+
 /*
  * this function sends a 'reschedule' IPI to another CPU.
  * it goes straight through and wastes no time serializing
Index: 2.4.x-xfs/arch/i386/kernel/smpboot.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kernel/smpboot.c	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/arch/i386/kernel/smpboot.c	Mon Aug  9 13:54:51 2004
@@ -40,6 +40,9 @@
 #include <linux/smp_lock.h>
 #include <linux/irq.h>
 #include <linux/bootmem.h>
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif	/* CONFIG_KDB */
 
 #include <linux/delay.h>
 #include <linux/mc146818rtc.h>
@@ -423,6 +426,11 @@
 	 */
  	smp_store_cpu_info(cpuid);
 
+#ifdef	CONFIG_KDB
+	/* Activate any preset global breakpoints on this cpu */
+	kdb(KDB_REASON_SILENT, 0, 0);
+#endif	/* CONFIG_KDB */
+
 	/*
 	 * Allow the master to continue.
 	 */
Index: 2.4.x-xfs/arch/i386/kernel/traps.c
===================================================================
--- 2.4.x-xfs.orig/arch/i386/kernel/traps.c	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/arch/i386/kernel/traps.c	Mon Aug  9 13:54:51 2004
@@ -30,6 +30,10 @@
 #include <asm/processor.h>
 #endif
 
+#ifdef	CONFIG_KDB
+#include <linux/kdb.h>
+#endif	/* CONFIG_KDB */
+
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -51,6 +55,9 @@
 #include <linux/module.h>
 
 asmlinkage int system_call(void);
+#ifdef	CONFIG_KDB
+asmlinkage int kdb_call(void);
+#endif	/* CONFIG_KDB */
 asmlinkage void lcall7(void);
 asmlinkage void lcall27(void);
 
@@ -79,6 +86,9 @@
 asmlinkage void stack_segment(void);
 asmlinkage void general_protection(void);
 asmlinkage void page_fault(void);
+#ifdef	CONFIG_KDB
+asmlinkage void page_fault_mca(void);
+#endif	/* CONFIG_KDB */
 asmlinkage void coprocessor_error(void);
 asmlinkage void simd_coprocessor_error(void);
 asmlinkage void alignment_check(void);
@@ -139,15 +149,16 @@
 	if (!stack)
 		stack = (unsigned long*)&stack;
 
-	printk("Call Trace:   ");
+	printk("Call Trace:");
+#if CONFIG_KALLSYMS
+	printk("\n");
+#endif
 	i = 1;
 	while (((long) stack & (THREAD_SIZE-1)) != 0) {
 		addr = *stack++;
 		if (kernel_text_address(addr)) {
-			if (i && ((i % 6) == 0))
-				printk("\n ");
-			printk(" [<%08lx>]", addr);
-			i++;
+			printk(" [<%08lx>] ", addr);
+			print_symbol("%s\n", addr);
 		}
 	}
 	printk("\n");
@@ -208,8 +219,11 @@
 		esp = regs->esp;
 		ss = regs->xss & 0xffff;
 	}
+	print_modules();
 	printk("CPU:    %d\nEIP:    %04x:[<%08lx>]    %s\nEFLAGS: %08lx\n",
 		smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags);
+
+	print_symbol("EIP is at %s\n", regs->eip);
 	printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
 		regs->eax, regs->ebx, regs->ecx, regs->edx);
 	printk("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
@@ -227,7 +241,7 @@
 		printk("\nStack: ");
 		show_stack((unsigned long*)esp);
 
-		printk("\nCode: ");
+		printk("Code: ");
 		if(regs->eip < PAGE_OFFSET)
 			goto bad;
 
@@ -292,6 +306,10 @@
 	show_registers(regs);
 	bust_spinlocks(0);
 	spin_unlock_irq(&die_lock);
+#ifdef	CONFIG_KDB
+	kdb_diemsg = str;
+	kdb(KDB_REASON_OOPS, err, regs);
+#endif	/* CONFIG_KDB */
 	do_exit(SIGSEGV);
 }
 
@@ -385,7 +403,9 @@
 }
 
 DO_VM86_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->eip)
+#ifndef	CONFIG_KDB
 DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
+#endif	/* !CONFIG_KDB */
 DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
 DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
 DO_ERROR_INFO( 6, SIGILL,  "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
@@ -462,17 +482,37 @@
 		return;
 	}
 #endif
+#ifdef	CONFIG_KDB
+	(void)kdb(KDB_REASON_NMI, reason, regs);
+#endif	/* CONFIG_KDB */
 	printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
 	printk("Dazed and confused, but trying to continue\n");
 	printk("Do you have a strange power saving mode enabled?\n");
 }
 
+#if defined(CONFIG_SMP) && defined(CONFIG_KDB)
+static void
+do_ack_apic_irq(void)
+{
+	ack_APIC_irq();
+}
+#endif	/* defined(CONFIG_SMP) && defined(CONFIG_KDB) */
+
 asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
 {
 	unsigned char reason = inb(0x61);
 
 	++nmi_count(smp_processor_id());
 
+#if defined(CONFIG_SMP) && defined(CONFIG_KDB)
+	/*
+	 * Call the kernel debugger to see if this NMI is due
+	 * to an KDB requested IPI.  If so, kdb will handle it.
+	 */
+	if (kdb_ipi(regs, do_ack_apic_irq)) {
+		return;
+	}
+#endif	/* defined(CONFIG_SMP) && defined(CONFIG_KDB) */
 	if (!(reason & 0xc0)) {
 #if CONFIG_X86_LOCAL_APIC
 		/*
@@ -532,6 +572,11 @@
 
 	__asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
 
+#ifdef	CONFIG_KDB
+	if (kdb(KDB_REASON_DEBUG, error_code, regs))
+		return;
+#endif	/* CONFIG_KDB */
+
 	/* If the user set TF, it's simplest to clear it right away. */
 	if ((eip >=PAGE_OFFSET) && (regs->eflags & TF_MASK))
 		goto clear_TF;
@@ -597,6 +642,16 @@
 	return;
 }
 
+#ifdef	CONFIG_KDB
+asmlinkage void do_int3(struct pt_regs * regs, long error_code)
+{
+	if (kdb(KDB_REASON_BREAK, error_code, regs))
+		return;
+	do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
+}
+#endif	/* CONFIG_KDB */
+
+
 /*
  * Note that we play around with the 'TS' bit in an attempt to get
  * the correct behaviour even in the presence of the asynchronous
@@ -977,7 +1032,17 @@
 	set_trap_gate(11,&segment_not_present);
 	set_trap_gate(12,&stack_segment);
 	set_trap_gate(13,&general_protection);
+#ifdef	CONFIG_KDB
+	if (test_bit(X86_FEATURE_MCE, boot_cpu_data.x86_capability) &&
+	    test_bit(X86_FEATURE_MCA, boot_cpu_data.x86_capability)) {
+		set_intr_gate(14,&page_fault_mca);
+	}
+	else {
+		set_intr_gate(14,&page_fault);
+	}
+#else	/* !CONFIG_KDB */
 	set_intr_gate(14,&page_fault);
+#endif	/* CONFIG_KDB */
 	set_trap_gate(15,&spurious_interrupt_bug);
 	set_trap_gate(16,&coprocessor_error);
 	set_trap_gate(17,&alignment_check);
@@ -985,6 +1050,14 @@
 	set_trap_gate(19,&simd_coprocessor_error);
 
 	set_system_gate(SYSCALL_VECTOR,&system_call);
+#ifdef	CONFIG_KDB
+	kdb_enablehwfault();
+	/*
+	 * A trap gate, used by the kernel to enter the 
+	 * debugger, preserving all registers.
+	 */
+	set_trap_gate(KDBENTER_VECTOR, &kdb_call);
+#endif	/* CONFIG_KDB */
 
 	/*
 	 * default LDT is a single-entry callgate to lcall7 for iBCS
Index: 2.4.x-xfs/arch/i386/vmlinux.lds
===================================================================
--- 2.4.x-xfs.orig/arch/i386/vmlinux.lds	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/arch/i386/vmlinux.lds	Mon Aug  9 13:54:51 2004
@@ -28,6 +28,10 @@
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___kallsyms = .;	/* All kernel symbols */
+  __kallsyms : { *(__kallsyms) }
+  __stop___kallsyms = .;
+
   .data : {			/* Data */
 	*(.data)
 	CONSTRUCTORS
@@ -46,6 +50,9 @@
   __setup_start = .;
   .setup.init : { *(.setup.init) }
   __setup_end = .;
+  __kdb_initcall_start = .;
+  .kdb_initcall.init : { *(.kdb_initcall.init) }
+  __kdb_initcall_end = .;
   __initcall_start = .;
   .initcall.init : { *(.initcall.init) }
   __initcall_end = .;
@@ -69,6 +76,7 @@
 	*(.text.exit)
 	*(.data.exit)
 	*(.exitcall.exit)
+	*(.kdb_exitcall.exit)
 	}
 
   /* Stabs debugging sections.  */
Index: 2.4.x-xfs/include/asm-i386/hw_irq.h
===================================================================
--- 2.4.x-xfs.orig/include/asm-i386/hw_irq.h	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/include/asm-i386/hw_irq.h	Mon Aug  9 13:54:51 2004
@@ -23,6 +23,7 @@
 #define FIRST_EXTERNAL_VECTOR	0x20
 
 #define SYSCALL_VECTOR		0x80
+#define KDBENTER_VECTOR		0x81
 
 /*
  * Vectors 0x20-0x2f are used for ISA interrupts.
@@ -42,6 +43,7 @@
 #define INVALIDATE_TLB_VECTOR	0xfd
 #define RESCHEDULE_VECTOR	0xfc
 #define CALL_FUNCTION_VECTOR	0xfb
+#define KDB_VECTOR		0xf9
 
 /*
  * Local APIC timer IRQ vector is on a different priority level,
Index: 2.4.x-xfs/include/asm-i386/kdb.h
===================================================================
--- 2.4.x-xfs.orig/include/asm-i386/kdb.h	Thu Jan  1 10:00:00 1970
+++ 2.4.x-xfs/include/asm-i386/kdb.h	Mon Aug  9 13:54:51 2004
@@ -0,0 +1,162 @@
+#ifndef	_ASM_KDB_H
+#define _ASM_KDB_H
+
+/*
+ * Kernel Debugger Architecture Dependent Global Headers
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+	/*
+	 * KDB_ENTER() is a macro which causes entry into the kernel
+	 * debugger from any point in the kernel code stream.  If it
+	 * is intended to be used from interrupt level, it must  use
+	 * a non-maskable entry method.
+	 */
+#define KDB_ENTER()	do {if (kdb_on && !KDB_IS_RUNNING()) { asm("\tint $129\n"); }} while(0)
+
+	/*
+	 * Needed for exported symbols.
+	 */
+typedef unsigned long kdb_machreg_t;
+
+#define kdb_machreg_fmt		"0x%lx"
+#define kdb_machreg_fmt0	"0x%08lx"
+#define kdb_bfd_vma_fmt		"0x%lx"
+#define kdb_bfd_vma_fmt0	"0x%08lx"
+#define kdb_elfw_addr_fmt	"0x%x"
+#define kdb_elfw_addr_fmt0	"0x%08x"
+
+	/*
+	 * Per cpu arch specific kdb state.  Must be in range 0xff000000.
+	 */
+#define KDB_STATE_A_IF		0x01000000	/* Saved IF flag */
+
+	/*
+	 * Functions to safely read and write kernel areas.  The {to,from}_xxx
+	 * addresses are not necessarily valid, these functions must check for
+	 * validity.  If the arch already supports get and put routines with
+	 * suitable validation and/or recovery on invalid addresses then use
+	 * those routines, otherwise check it yourself.
+	 */
+
+	/*
+	 * asm-i386 uaccess.h supplies __copy_to_user which relies on MMU to
+	 * trap invalid addresses in the _xxx fields.  Verify the other address
+	 * of the pair is valid by accessing the first and last byte ourselves,
+	 * then any access violations should only be caused by the _xxx
+	 * addresses,
+	 */
+
+#include <asm/uaccess.h>
+
+extern int kdb_getuserarea_size(void *, unsigned long, size_t);
+extern int kdb_putuserarea_size(unsigned long, void *, size_t);
+
+static inline int
+__kdba_putarea_size(unsigned long to_xxx, void *from, size_t size)
+{
+	mm_segment_t oldfs = get_fs();
+	int r;
+	char c;
+	c = *((volatile char *)from);
+	c = *((volatile char *)from + size - 1);
+	
+	if (to_xxx < PAGE_OFFSET) {
+		return kdb_putuserarea_size(to_xxx, from, size);
+	}
+
+	set_fs(KERNEL_DS);
+	r = __copy_to_user((void *)to_xxx, from, size);
+	set_fs(oldfs);
+	return r;
+}
+
+static inline int
+__kdba_getarea_size(void *to, unsigned long from_xxx, size_t size)
+{
+	mm_segment_t oldfs = get_fs();
+	int r;
+	*((volatile char *)to) = '\0';
+	*((volatile char *)to + size - 1) = '\0';
+
+	if (from_xxx < PAGE_OFFSET) {
+		return kdb_getuserarea_size(to, from_xxx, size);
+	}
+
+	set_fs(KERNEL_DS);
+	switch (size) {
+	case 1:
+		r = __copy_to_user(to, (void *)from_xxx, 1);
+		break;
+	case 2:
+		r = __copy_to_user(to, (void *)from_xxx, 2);
+		break;
+	case 4:
+		r = __copy_to_user(to, (void *)from_xxx, 4);
+		break;
+	case 8:
+		r = __copy_to_user(to, (void *)from_xxx, 8);
+		break;
+	default:
+		r = __copy_to_user(to, (void *)from_xxx, size);
+		break;
+	}
+	set_fs(oldfs);
+	return r;
+}
+
+/* For numa with replicated code/data, the platform must supply its own
+ * kdba_putarea_size and kdba_getarea_size routines.  Without replication kdb
+ * uses the standard architecture routines.
+ */
+#ifdef CONFIG_NUMA_REPLICATE
+extern int kdba_putarea_size(unsigned long to_xxx, void *from, size_t size);
+extern int kdba_getarea_size(void *to, unsigned long from_xxx, size_t size);
+#else
+#define kdba_putarea_size __kdba_putarea_size
+#define kdba_getarea_size __kdba_getarea_size
+#endif
+
+static inline int
+kdba_verify_rw(unsigned long addr, size_t size)
+{
+	unsigned char data[size];
+	return(kdba_getarea_size(data, addr, size) || kdba_putarea_size(addr, data, size));
+}
+
+static inline unsigned long
+kdba_funcptr_value(void *fp)
+{
+	return (unsigned long)fp;
+}
+
+#endif	/* !_ASM_KDB_H */
Index: 2.4.x-xfs/include/asm-i386/kdbprivate.h
===================================================================
--- 2.4.x-xfs.orig/include/asm-i386/kdbprivate.h	Thu Jan  1 10:00:00 1970
+++ 2.4.x-xfs/include/asm-i386/kdbprivate.h	Mon Aug  9 13:54:51 2004
@@ -0,0 +1,209 @@
+#ifndef	_ASM_KDBPRIVATE_H
+#define _ASM_KDBPRIVATE_H
+
+/*
+ * Kernel Debugger Architecture Dependent Private Headers
+ *
+ * Copyright (C) 1999-2003 Silicon Graphics, Inc.  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+typedef unsigned char kdb_machinst_t;
+
+	/*
+	 * KDB_MAXBPT describes the total number of breakpoints
+	 * supported by this architecure.
+	 */
+#define KDB_MAXBPT	16
+
+	/*
+	 * KDB_MAXHARDBPT describes the total number of hardware
+	 * breakpoint registers that exist.
+	 */
+#define KDB_MAXHARDBPT	 4
+
+	/*
+	 * Platform specific environment entries
+	 */
+#define KDB_PLATFORM_ENV	"IDMODE=x86", "BYTESPERWORD=4", "IDCOUNT=16"
+
+	/*
+	 * Define the direction that the stack grows
+	 */
+#define KDB_STACK_DIRECTION	(-1)	/* Stack grows down */
+
+	/*
+	 * Support for ia32 debug registers
+	 */
+typedef struct _kdbhard_bp {
+	kdb_machreg_t	bph_reg;	/* Register this breakpoint uses */
+
+	unsigned int	bph_free:1;	/* Register available for use */
+	unsigned int	bph_data:1;	/* Data Access breakpoint */
+
+	unsigned int	bph_write:1;	/* Write Data breakpoint */
+	unsigned int	bph_mode:2;	/* 0=inst, 1=write, 2=io, 3=read */
+	unsigned int	bph_length:2;	/* 0=1, 1=2, 2=BAD, 3=4 (bytes) */
+} kdbhard_bp_t;
+
+extern kdbhard_bp_t	kdb_hardbreaks[/* KDB_MAXHARDBPT */];
+
+#define IA32_BREAKPOINT_INSTRUCTION	0xcc
+
+#define DR6_BT  0x00008000
+#define DR6_BS  0x00004000
+#define DR6_BD  0x00002000
+
+#define DR6_B3  0x00000008
+#define DR6_B2  0x00000004
+#define DR6_B1  0x00000002
+#define DR6_B0  0x00000001
+#define DR6_DR_MASK  0x0000000F
+
+#define DR7_RW_VAL(dr, drnum) \
+       (((dr) >> (16 + (4 * (drnum)))) & 0x3)
+
+#define DR7_RW_SET(dr, drnum, rw)                              \
+       do {                                                    \
+               (dr) &= ~(0x3 << (16 + (4 * (drnum))));         \
+               (dr) |= (((rw) & 0x3) << (16 + (4 * (drnum)))); \
+       } while (0)
+
+#define DR7_RW0(dr)       DR7_RW_VAL(dr, 0)
+#define DR7_RW0SET(dr,rw)  DR7_RW_SET(dr, 0, rw)
+#define DR7_RW1(dr)       DR7_RW_VAL(dr, 1)
+#define DR7_RW1SET(dr,rw)  DR7_RW_SET(dr, 1, rw)
+#define DR7_RW2(dr)       DR7_RW_VAL(dr, 2)
+#define DR7_RW2SET(dr,rw)  DR7_RW_SET(dr, 2, rw)
+#define DR7_RW3(dr)       DR7_RW_VAL(dr, 3)
+#define DR7_RW3SET(dr,rw)  DR7_RW_SET(dr, 3, rw)
+
+
+#define DR7_LEN_VAL(dr, drnum) \
+       (((dr) >> (18 + (4 * (drnum)))) & 0x3)
+
+#define DR7_LEN_SET(dr, drnum, rw)                             \
+       do {                                                    \
+               (dr) &= ~(0x3 << (18 + (4 * (drnum))));         \
+               (dr) |= (((rw) & 0x3) << (18 + (4 * (drnum)))); \
+       } while (0)
+#define DR7_LEN0(dr)        DR7_LEN_VAL(dr, 0)
+#define DR7_LEN0SET(dr,len)  DR7_LEN_SET(dr, 0, len)
+#define DR7_LEN1(dr)        DR7_LEN_VAL(dr, 1)
+#define DR7_LEN1SET(dr,len)  DR7_LEN_SET(dr, 1, len)
+#define DR7_LEN2(dr)        DR7_LEN_VAL(dr, 2)
+#define DR7_LEN2SET(dr,len)  DR7_LEN_SET(dr, 2, len)
+#define DR7_LEN3(dr)        DR7_LEN_VAL(dr, 3)
+#define DR7_LEN3SET(dr,len)  DR7_LEN_SET(dr, 3, len)
+
+#define DR7_G0(dr)    (((dr)>>1)&0x1)
+#define DR7_G0SET(dr) ((dr) |= 0x2)
+#define DR7_G0CLR(dr) ((dr) &= ~0x2)
+#define DR7_G1(dr)    (((dr)>>3)&0x1)
+#define DR7_G1SET(dr) ((dr) |= 0x8)
+#define DR7_G1CLR(dr) ((dr) &= ~0x8)
+#define DR7_G2(dr)    (((dr)>>5)&0x1)
+#define DR7_G2SET(dr) ((dr) |= 0x20)
+#define DR7_G2CLR(dr) ((dr) &= ~0x20)
+#define DR7_G3(dr)    (((dr)>>7)&0x1)
+#define DR7_G3SET(dr) ((dr) |= 0x80)
+#define DR7_G3CLR(dr) ((dr) &= ~0x80)
+
+#define DR7_L0(dr)    (((dr))&0x1)
+#define DR7_L0SET(dr) ((dr) |= 0x1)
+#define DR7_L0CLR(dr) ((dr) &= ~0x1)
+#define DR7_L1(dr)    (((dr)>>2)&0x1)
+#define DR7_L1SET(dr) ((dr) |= 0x4)
+#define DR7_L1CLR(dr) ((dr) &= ~0x4)
+#define DR7_L2(dr)    (((dr)>>4)&0x1)
+#define DR7_L2SET(dr) ((dr) |= 0x10)
+#define DR7_L2CLR(dr) ((dr) &= ~0x10)
+#define DR7_L3(dr)    (((dr)>>6)&0x1)
+#define DR7_L3SET(dr) ((dr) |= 0x40)
+#define DR7_L3CLR(dr) ((dr) &= ~0x40)
+
+#define DR7_GD          0x00002000              /* General Detect Enable */
+#define DR7_GE          0x00000200              /* Global exact */
+#define DR7_LE          0x00000100              /* Local exact */
+
+#define DR_TYPE_EXECUTE	0x0
+#define DR_TYPE_WRITE	0x1
+#define DR_TYPE_IO	0x2
+#define DR_TYPE_RW	0x3
+
+extern kdb_machreg_t kdba_getdr6(void);
+extern void kdba_putdr6(kdb_machreg_t);
+
+extern kdb_machreg_t kdba_getdr7(void);
+
+extern kdb_machreg_t kdba_getdr(int);
+extern void kdba_putdr(int, kdb_machreg_t);
+
+extern kdb_machreg_t kdb_getcr(int);
+
+#define KDB_HAVE_LONGJMP
+#ifdef KDB_HAVE_LONGJMP
+/*
+ * Support for setjmp/longjmp
+ */
+#define JB_BX   0
+#define JB_SI   1
+#define JB_DI   2
+#define JB_BP   3
+#define JB_SP   4
+#define JB_PC   5
+
+typedef struct __kdb_jmp_buf {
+        unsigned long   regs[6];	/* kdba_setjmp assumes fixed offsets here */
+} kdb_jmp_buf;
+
+extern int kdba_setjmp(kdb_jmp_buf *);
+extern void kdba_longjmp(kdb_jmp_buf *, int);
+
+extern kdb_jmp_buf  *kdbjmpbuf;
+#endif	/* KDB_HAVE_LONGJMP */
+
+/* Arch specific data saved for running processes */
+
+struct kdba_running_process {
+	int dummy[0];	/* Everything is in pt_regs for i386 */
+};
+
+static inline
+void kdba_save_running(struct kdba_running_process *k, struct pt_regs *regs)
+{
+}
+
+static inline
+void kdba_unsave_running(struct kdba_running_process *k, struct pt_regs *regs)
+{
+}
+
+#endif	/* !_ASM_KDBPRIVATE_H */
Index: 2.4.x-xfs/include/asm-i386/keyboard.h
===================================================================
--- 2.4.x-xfs.orig/include/asm-i386/keyboard.h	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/include/asm-i386/keyboard.h	Mon Aug  9 13:54:51 2004
@@ -42,6 +42,7 @@
 #define kbd_sysrq_xlate		pckbd_sysrq_xlate
 
 #define SYSRQ_KEY 0x54
+#define E1_PAUSE   119		/* PAUSE key */
 
 /* resource allocation */
 #define kbd_request_region()
Index: 2.4.x-xfs/include/asm-i386/kmap_types.h
===================================================================
--- 2.4.x-xfs.orig/include/asm-i386/kmap_types.h	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/include/asm-i386/kmap_types.h	Mon Aug  9 13:54:51 2004
@@ -10,6 +10,7 @@
 	KM_BH_IRQ,
 	KM_SOFTIRQ0,
 	KM_SOFTIRQ1,
+	KM_KDB,
 	KM_TYPE_NR
 };
 
Index: 2.4.x-xfs/include/asm-i386/ptrace.h
===================================================================
--- 2.4.x-xfs.orig/include/asm-i386/ptrace.h	Mon Aug  9 13:50:21 2004
+++ 2.4.x-xfs/include/asm-i386/ptrace.h	Mon Aug  9 13:54:51 2004
@@ -54,6 +54,29 @@
 /* options set using PTRACE_SETOPTIONS */
 #define PTRACE_O_TRACESYSGOOD     0x00000001
 
+enum EFLAGS {
+        EF_CF   = 0x00000001,
+        EF_PF   = 0x00000004,
+        EF_AF   = 0x00000010,
+        EF_ZF   = 0x00000040,
+        EF_SF   = 0x00000080,
+        EF_TF   = 0x00000100,
+        EF_IE   = 0x00000200,
+        EF_DF   = 0x00000400,
+        EF_OF   = 0x00000800,
+        EF_IOPL = 0x00003000,
+        EF_IOPL_RING0 = 0x00000000,
+        EF_IOPL_RING1 = 0x00001000,
+        EF_IOPL_RING2 = 0x00002000,
+        EF_NT   = 0x00004000,   /* nested task */
+        EF_RF   = 0x00010000,   /* resume */
+        EF_VM   = 0x00020000,   /* virtual mode */
+        EF_AC   = 0x00040000,   /* alignment */
+        EF_VIF  = 0x00080000,   /* virtual interrupt */
+        EF_VIP  = 0x00100000,   /* virtual interrupt pending */
+        EF_ID   = 0x00200000,   /* id */
+};
+
 #ifdef __KERNEL__
 #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
 #define instruction_pointer(regs) ((regs)->eip)
Index: 2.4.x-xfs/kdb/modules/kdbm_x86.c
===================================================================
--- 2.4.x-xfs.orig/kdb/modules/kdbm_x86.c	Thu Jan  1 10:00:00 1970
+++ 2.4.x-xfs/kdb/modules/kdbm_x86.c	Mon Aug  9 13:54:51 2004
@@ -0,0 +1,913 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Author: Vamsi Krishna S. <vamsi_krishna@in.ibm.com>
+ * (C) 2003 IBM Corporation.
+ */
+
+#include <linux/types.h>
+#include <linux/kdb.h>
+#include <linux/kdbprivate.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/desc.h>
+#include <asm/debugreg.h>
+
+MODULE_AUTHOR("Vamsi Krishna S./IBM");
+MODULE_DESCRIPTION("x86 specific information (gdt/idt/ldt/page tables)");
+MODULE_LICENSE("GPL");
+
+typedef struct _kdb_desc {
+	unsigned short limit;
+	unsigned short base;
+	unsigned char base_h1;
+	unsigned char type:4;
+	unsigned char seg:1;
+	unsigned char dpl:2;
+	unsigned char present:1;
+	unsigned char limit_h:4;
+	unsigned char avl:2;
+	unsigned char db:1;
+	unsigned char g:1; /* granularity */
+	unsigned char base_h2;
+} kdb_desc_t;
+
+typedef struct _kdb_gate_desc {
+	unsigned short offset;
+	unsigned short sel;
+	unsigned char res;
+	unsigned char type:4;
+	unsigned char seg:1;
+	unsigned char dpl:2;
+	unsigned char present:1;
+	unsigned short offset_h;
+} kdb_gate_desc_t;
+
+#define KDB_SEL_MAX 			0x2000
+#define KDB_IDT_MAX 			0x100
+#define KDB_SYS_DESC_TYPE_TSS		0x01
+#define KDB_SYS_DESC_TYPE_LDT		0x02
+#define KDB_SYS_DESC_TYPE_TSSB		0x03
+#define KDB_SYS_DESC_TYPE_CALLG		0x04
+#define KDB_SYS_DESC_TYPE_TASKG		0x05
+#define KDB_SYS_DESC_TYPE_INTG		0x06
+#define KDB_SYS_DESC_TYPE_TRAPG		0x07
+
+#define KDB_SYS_DESC_TYPE_TSS32 	0x09
+#define KDB_SYS_DESC_TYPE_TSS32B	0x0b
+#define KDB_SYS_DESC_TYPE_CALLG32	0x0c
+#define KDB_SYS_DESC_TYPE_INTG32	0x0e
+#define KDB_SYS_DESC_TYPE_TRAPG32	0x0f
+
+#define KDB_SYS_DESC_OFFSET(d) ((unsigned long)(d->offset_h << 16 | d->offset))
+#define KDB_SYS_DESC_CALLG_COUNT(d) ((unsigned int)(d->res & 0x0F))
+
+#define KDB_SEG_DESC_TYPE_CODE		0x08
+#define KDB_SEG_DESC_TYPE_CODE_R	0x02
+#define KDB_SEG_DESC_TYPE_DATA_W	0x02
+#define KDB_SEG_DESC_TYPE_CODE_C	0x02    /* conforming */
+#define KDB_SEG_DESC_TYPE_DATA_D	0x02    /* expand-down */
+#define KDB_SEG_DESC_TYPE_A		0x01	/* accessed */
+
+#define KDB_SEG_DESC_BASE(d) ((unsigned long)(d->base_h2 << 24 | d->base_h1 << 16 | d->base))
+#define _LIMIT(d) ((unsigned long)(d->limit_h << 16 | d->limit))
+#define KDB_SEG_DESC_LIMIT(d) (d->g ? ((_LIMIT(d)+1) << 12) -1 : _LIMIT(d))
+ 
+/* helper functions to display system registers in verbose mode */
+static void display_gdtr(void)
+{
+	struct Xgt_desc_struct gdtr;
+	
+	__asm__ __volatile__ ("sgdt %0\n\t" : "=m"(gdtr));
+	kdb_printf("gdtr.address = 0x%8.8lx, gdtr.size = 0x%x\n", gdtr.address, gdtr.size);
+
+	return;
+}
+
+static void display_ldtr(void)
+{
+	struct Xgt_desc_struct gdtr;
+	unsigned long ldtr;
+	
+	__asm__ __volatile__ ("sgdt %0\n\t" : "=m"(gdtr));
+	__asm__ __volatile__ ("sldt %0\n\t" : "=m"(ldtr));
+	
+	kdb_printf("ldtr = 0x%8.8lx ", ldtr);
+
+	if (ldtr < gdtr.size) {
+		kdb_desc_t *ldt_desc = (kdb_desc_t *)(gdtr.address + (ldtr & ~7));
+		kdb_printf("base=0x%8.8lx, limit=0x%8.8lx\n", KDB_SEG_DESC_BASE(ldt_desc), 
+				KDB_SEG_DESC_LIMIT(ldt_desc)); 
+	} else {
+		kdb_printf("invalid\n");
+	}
+
+	return;
+}
+
+static void display_idtr(void)
+{
+	struct Xgt_desc_struct idtr;
+	__asm__ __volatile__ ("sidt %0\n\t" : "=m"(idtr));
+	kdb_printf("idtr.address = 0x%8.8lx, idtr.size = 0x%x\n", idtr.address, idtr.size);
+	return;	
+}
+
+static char *cr0_flags[] = {
+	"pe", "mp", "em", "ts", "et", "ne", NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	"wp", NULL, "am", NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, "nw", "cd", "pg"};
+
+static void display_cr0(void)
+{
+	kdb_machreg_t cr0;
+	int i;
+	__asm__ ("movl %%cr0,%0\n\t":"=r"(cr0));
+	kdb_printf("cr0=0x%08lx ", cr0);
+	for (i = 0; i < 32; i++) {
+		if (test_bit(i, &cr0) && cr0_flags[i])
+			kdb_printf("%s ", cr0_flags[i]);
+	}
+	kdb_printf("\n");
+	return;
+}
+
+static void display_cr3(void)
+{
+	kdb_machreg_t cr3;
+	__asm__ ("movl %%cr3,%0\n\t":"=r"(cr3));
+	kdb_printf("cr3 = 0x%08lx ", cr3);
+	if (cr3 & 0x08)
+		kdb_printf("pwt ");
+	if (cr3 & 0x10)
+		kdb_printf("pcd ");
+	kdb_printf("pgdir=%8.8lx\n", cr3 & PAGE_MASK);
+	return;
+}
+
+static char *cr4_flags[] = {
+	"vme", "pvi", "tsd", "de", "pse", "pae", "mce", "pge", "pce"};
+
+static void display_cr4(void)
+{
+	kdb_machreg_t cr4;
+	int i;
+	__asm__ ("movl %%cr4,%0\n\t":"=r"(cr4));
+	kdb_printf("cr4 = 0x%08lx ", cr4);
+	for (i = 0; i < 9; i++) {
+		if (test_bit(i, &cr4))
+			kdb_printf("%s ", cr4_flags[i]);
+	}
+	kdb_printf("\n");
+	return;
+}
+
+static char *dr_type_name[] = { "exec", "write", "io", "rw" };
+
+static void display_dr_status(int nr, int enabled, int local, int len, int type)
+{
+	if (!enabled) {
+		kdb_printf("\tdebug register %d: not enabled\n", nr);
+		return;
+	}
+	
+	kdb_printf("\tdebug register %d: %s, len = %d, type = %s\n", 
+			nr,
+			local? " local":"global",
+			len,
+			dr_type_name[type]);
+}
+
+static void display_dr(void)
+{
+	kdb_machreg_t dr0, dr1, dr2, dr3, dr6, dr7;
+	int dbnr, set;
+
+	__asm__ ("movl %%db0,%0\n\t":"=r"(dr0));
+	__asm__ ("movl %%db1,%0\n\t":"=r"(dr1));
+	__asm__ ("movl %%db2,%0\n\t":"=r"(dr2));
+	__asm__ ("movl %%db3,%0\n\t":"=r"(dr3));
+	__asm__ ("movl %%db6,%0\n\t":"=r"(dr6));
+	__asm__ ("movl %%db7,%0\n\t":"=r"(dr7));
+
+	kdb_printf("dr0 = 0x%08lx dr1 = 0x%08lx dr2 = 0x%08lx dr3 = 0x%08lx\n",
+		   dr0, dr1, dr2, dr3);
+	kdb_printf("dr6 = 0x%08lx ", dr6);
+	dbnr = dr6 & DR6_DR_MASK;
+	if (dbnr) {
+		int nr;
+		switch(dbnr) {
+		case 1:
+			nr = 0; break;
+		case 2:
+			nr = 1; break;
+		case 4:
+			nr = 2; break;
+		default:
+			nr = 3; break;
+		}
+		kdb_printf("debug register hit = %d", nr);
+	} else if (dr6 & DR_STEP) {
+		kdb_printf("single step");
+	} else if (dr6 & DR_SWITCH) {
+		kdb_printf("task switch");
+	}
+	kdb_printf("\n");
+
+	kdb_printf("dr7 = 0x%08lx\n", dr7);
+	set = DR7_L0(dr7) || DR7_G0(dr7);
+	display_dr_status(0, set, DR7_L0(dr7), DR7_LEN0(dr7), DR7_RW0(dr7));
+	set = DR7_L1(dr7) || DR7_G1(dr7);
+	display_dr_status(1, set, DR7_L1(dr7), DR7_LEN1(dr7), DR7_RW1(dr7));
+	set = DR7_L2(dr7) || DR7_G2(dr7);
+	display_dr_status(2, set, DR7_L2(dr7), DR7_LEN2(dr7), DR7_RW2(dr7));
+	set = DR7_L3(dr7) || DR7_G3(dr7);
+	display_dr_status(3, set, DR7_L3(dr7), DR7_LEN3(dr7), DR7_RW3(dr7));
+}
+
+static char *set_eflags[] = {
+	"carry", NULL, "parity",  NULL, "adjust",  NULL, "zero", "sign",
+	"trace", "intr-on", "dir", "overflow",  NULL, NULL, "nestedtask", NULL,
+	"resume", "vm", "align", "vif", "vip", "id", NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+
+static void display_eflags(unsigned long ef)
+{
+	int i, iopl;
+	kdb_printf("eflags = 0x%08lx ", ef);
+	for (i = 0; i < 22; i++) {
+		if (test_bit(i, &ef) && set_eflags[i])
+			kdb_printf("%s ", set_eflags[i]);
+	}
+	
+	iopl = ((unsigned long)(ef & 0x00003000)) >> 12;
+	kdb_printf("iopl=%c\n", '0'+iopl);
+	return;
+}
+
+static void display_tss(struct tss_struct *t)
+{
+	kdb_printf("    cs = %04x,  eip = 0x%8.8lx\n", t->es, t->eip);
+	kdb_printf("    ss = %04x,  esp = 0x%8.8lx\n", t->ss, t->esp);
+	kdb_printf("   ss0 = %04x, esp0 = 0x%8.8lx\n", t->ss0, t->esp0);
+	kdb_printf("   ss1 = %04x, esp1 = 0x%8.8lx\n", t->ss1, t->esp1);
+	kdb_printf("   ss2 = %04x, esp2 = 0x%8.8lx\n", t->ss2, t->esp2);
+	kdb_printf("   ldt = %04x, cr3 = 0x%8.8lx\n", t->ldt, t->__cr3);
+	kdb_printf("    ds = %04x, es = %04x fs = %04x gs = %04x\n", 
+			t->ds, t->es, t->fs, t->gs);
+	kdb_printf("   eax = 0x%8.8lx, ebx = 0x%8.8lx ecx = 0x%8.8lx edx = 0x%8.8lx\n", 
+			t->eax, t->ebx, t->ecx, t->edx);
+	kdb_printf("   esi = 0x%8.8lx, edi = 0x%8.8lx ebp = 0x%8.8lx\n", 
+			t->esi, t->edi, t->ebp);
+}
+
+static char *gate_desc_types[] = {
+	"invalid", "tss-avlb", "ldt", "tss-busy", 
+	"callgate", "taskgate", "intgate", "trapgate", 
+	"invalid", "tss32-avlb", "invalid", "tss32-busy", 
+	"callgate32", "invalid", "intgate32", "trapgate32",
+	NULL };
+	
+static int
+display_gate_desc(kdb_gate_desc_t * d)
+{
+	kdb_printf("%-11s ", gate_desc_types[d->type]);
+
+	switch(d->type) {
+	case KDB_SYS_DESC_TYPE_LDT:
+		kdb_printf("base=0x%8.8lx limit=0x%8.8lx dpl=%d\n", 
+			KDB_SEG_DESC_BASE(((kdb_desc_t *)d)), 
+			KDB_SEG_DESC_LIMIT(((kdb_desc_t *)d)), d->dpl);
+		break;
+	case KDB_SYS_DESC_TYPE_TSS32:
+	case KDB_SYS_DESC_TYPE_TSS32B:
+	{
+		struct tss_struct *tss = (struct tss_struct *)KDB_SEG_DESC_BASE(((kdb_desc_t *)d)); 
+		kdb_printf("base=0x%8.8lx limit=0x%8.8lx dpl=%d\n", 
+			(unsigned long)tss, 
+			KDB_SEG_DESC_LIMIT(((kdb_desc_t *)d)), d->dpl);
+		display_tss(tss);	
+		break;
+	}
+	case KDB_SYS_DESC_TYPE_CALLG:
+		kdb_printf("sel=0x%4.4x off=0x%8.8lx dpl=%d wc=%d\n",
+			d->sel, KDB_SYS_DESC_OFFSET(d), d->dpl,
+			KDB_SYS_DESC_CALLG_COUNT(d));
+		break;
+	case KDB_SYS_DESC_TYPE_CALLG32:
+		kdb_printf("sel=0x%4.4x off=0x%8.8lx dpl=%d dwc=%d\n",
+			d->sel, KDB_SYS_DESC_OFFSET(d), d->dpl,
+			KDB_SYS_DESC_CALLG_COUNT(d));
+		break;
+	default:
+		kdb_printf("sel=0x%4.4x off=0x%8.8lx dpl=%d\n",
+			d->sel, KDB_SYS_DESC_OFFSET(d), d->dpl);
+		break;
+	}
+
+	return 0;
+}
+
+static int
+display_seg_desc(kdb_desc_t * d)
+{
+	unsigned char type = d->type;
+
+	if (type & KDB_SEG_DESC_TYPE_CODE) {
+		kdb_printf("%-7s base=0x%8.8lx limit=0x%8.8lx dpl=%d %c%c%c %s %s %s \n",
+			"code",
+			KDB_SEG_DESC_BASE(d), KDB_SEG_DESC_LIMIT(d),
+			d->dpl,
+			(type & KDB_SEG_DESC_TYPE_CODE_R)?'r':'-',
+			'-', 'x',
+			d->db ? "32b" : "16b",
+			(type & KDB_SEG_DESC_TYPE_A)?"ac":"",
+			(type & KDB_SEG_DESC_TYPE_CODE_C)?"conf":"");
+	}
+	else {
+		kdb_printf("%-7s base=0x%8.8lx limit=0x%8.8lx dpl=%d %c%c%c %s %s %s \n",
+			"data",
+			KDB_SEG_DESC_BASE(d), KDB_SEG_DESC_LIMIT(d),
+			d->dpl,
+			'r',
+			(type & KDB_SEG_DESC_TYPE_DATA_W)?'w':'-',
+			'-',
+			d->db ? "32b" : "16b",
+			(type & KDB_SEG_DESC_TYPE_A)?"ac":"",
+			(type & KDB_SEG_DESC_TYPE_DATA_D)?"down":"");
+	}
+
+	return 0;
+}
+
+static int
+kdb_parse_two_numbers(int argc, const char **argv, int *sel, int *count, int *last_sel, int *last_count)
+{
+	int diag;
+
+	if (argc > 2)
+		return KDB_ARGCOUNT;
+
+	kdbgetintenv("MDCOUNT", count);
+
+	if (argc == 0) {
+		*sel = *last_sel;
+		if (*last_count)
+			*count = *last_count;
+	} else {
+		unsigned long val;
+
+		if (argc >= 1) {
+			diag = kdbgetularg(argv[1], &val);
+			if (diag)
+				return diag;
+			*sel = val;
+		}
+		if (argc >= 2) {
+			diag = kdbgetularg(argv[2], &val);
+			if (diag)
+				return diag;
+			*count = (int) val;
+			*last_count = (int) val;
+		} else if (*last_count) {
+			*count = *last_count;
+		}
+	}
+	return 0;
+}
+
+/*
+ * kdb_gdt
+ *
+ *	This function implements the 'gdt' command.
+ *
+ *	gdt [<selector> [<line count>]]
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+static int
+kdb_gdt(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int sel = 0;
+	struct Xgt_desc_struct gdtr;
+	int diag, count = 8;
+	kdb_desc_t * gdt;
+	unsigned int max_sel;
+	static int last_sel = 0, last_count = 0;
+
+	diag = kdb_parse_two_numbers(argc, argv, &sel, &count, &last_sel, &last_count);
+	if (diag)
+		return diag;
+
+	__asm__ __volatile__ ("sgdt %0\n\t" : "=m"(gdtr));
+	gdt = (kdb_desc_t *) gdtr.address;
+
+	max_sel = (gdtr.size + 1) / sizeof(kdb_desc_t);
+	if (sel >= max_sel) {
+		sel = 0;
+	}
+
+	if (sel + count > max_sel)
+		count = max_sel - sel;
+
+	while (count--) {
+		kdb_desc_t * d = &gdt[sel];
+		kdb_printf("0x%4.4x ", sel++);
+
+		if (!d->present) {
+			kdb_printf("not present\n");
+			continue;
+		}
+		if (d->seg)
+			display_seg_desc(d);
+		else
+			display_gate_desc((kdb_gate_desc_t *)d);
+	}
+
+	last_sel = sel;
+	return 0;
+}
+
+/*
+ * kdb_ldt
+ *
+ *	This function implements the 'ldt' command.
+ *
+ *	ldt [<selector> [<line count>]]
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+static int
+kdb_ldt(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int sel = 0;
+	struct Xgt_desc_struct gdtr;
+	unsigned long ldtr = 0;
+	int diag, count = 8;
+	kdb_desc_t * ldt, *ldt_desc;
+	unsigned int max_sel;
+	static int last_sel = 0, last_count = 0;
+
+	diag = kdb_parse_two_numbers(argc, argv, &sel, &count, &last_sel, &last_count);
+	if (diag)
+		return diag;
+
+	if (strcmp(argv[0], "ldtp") == 0) {
+		kdb_printf("pid=%d, process=%s\n", kdb_current_task->pid, kdb_current_task->comm);
+		if (!kdb_current_task->mm || !kdb_current_task->mm->context.ldt) {
+			kdb_printf("no special LDT for this process\n");
+			return 0;
+		}
+		ldt = kdb_current_task->mm->context.ldt;
+		max_sel = kdb_current_task->mm->context.size;
+	} else {
+
+		/* sldt gives the GDT selector for the segment containing LDT */
+		__asm__ __volatile__ ("sgdt %0\n\t" : "=m"(gdtr));
+		__asm__ __volatile__ ("sldt %0\n\t" : "=m"(ldtr));
+
+		if (ldtr > gdtr.size+1) {
+			kdb_printf("invalid ldtr\n");
+			return 0;
+		}
+
+		ldt_desc = (kdb_desc_t *)(gdtr.address + (ldtr & ~7));
+		ldt = (kdb_desc_t *) KDB_SEG_DESC_BASE(ldt_desc);
+		max_sel = (KDB_SEG_DESC_LIMIT(ldt_desc)+1) / sizeof(kdb_desc_t);
+	}
+
+	if (sel >= max_sel) {
+		sel = 0;
+	}
+
+	if (sel + count > max_sel)
+		count = max_sel - sel;
+
+	while (count--) {
+		kdb_desc_t * d = &ldt[sel];
+		kdb_printf("0x%4.4x ", sel++);
+
+		if (d->seg)
+			display_seg_desc(d);
+		else
+			display_gate_desc((kdb_gate_desc_t *)d);
+	}
+
+	last_sel = sel;
+	return 0;
+}
+
+/*
+ * kdb_idt
+ *
+ *	This function implements the 'idt' command.
+ *
+ *	idt [<vector> [<line count>]]
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+static int
+kdb_idt(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	int vec = 0;
+	struct Xgt_desc_struct idtr;
+	int diag, count = 8;
+	kdb_gate_desc_t * idt;
+	unsigned int max_entries;
+	static int last_vec = 0, last_count = 0;
+
+	diag = kdb_parse_two_numbers(argc, argv, &vec, &count, &last_vec, &last_count);
+	if (diag)
+		return diag;
+
+	__asm__ __volatile__ ("sidt %0\n\t" : "=m"(idtr));
+	idt = (kdb_gate_desc_t *) idtr.address;
+
+	max_entries = (idtr.size+1) / sizeof(kdb_gate_desc_t);
+	if (vec >= max_entries) {
+		vec = 0;
+	}
+
+	if (vec + count > max_entries)
+		count = max_entries - vec;
+
+	while (count--) {
+		kdb_gate_desc_t * d = &idt[vec];
+		kdb_printf("0x%4.4x ", vec++);
+		if (!d->present) {
+			kdb_printf("not present\n");
+			continue;
+		}
+		if (d->seg) {
+			kdb_printf("invalid\n");
+			continue;
+		}
+		display_gate_desc(d);
+	}
+
+	last_vec = vec;
+
+	return 0;
+}
+
+#define _PAGE_PSE 0x080
+
+static int
+get_pagetables(unsigned long addr, pgd_t **pgdir, pmd_t **pgmiddle, pte_t **pte)
+{
+	pgd_t * d;
+	pmd_t * m;
+	pte_t * t;
+
+	if (addr > PAGE_OFFSET) {
+		d = pgd_offset_k(addr);
+	} else {
+		kdb_printf("pid=%d, process=%s\n", kdb_current_task->pid, kdb_current_task->comm);
+		d = pgd_offset(kdb_current_task->mm, addr);
+	}
+
+	if (pgd_none(*d) || pgd_bad(*d)) {
+		*pgdir = NULL;
+		*pgmiddle = NULL;
+		*pte = NULL;
+		return 0;
+	} else {
+		*pgdir = d;
+	}
+
+	/* if _PAGE_PSE is set, pgdir points directly to the page. */
+	if (pgd_val(*d) & _PAGE_PSE) {
+		*pgmiddle = NULL;
+		*pte = NULL;
+		return 0;
+	}
+
+	m = pmd_offset(d, addr);
+	if (pmd_none(*m) || pmd_bad(*m)) {
+		*pgmiddle = NULL;
+		*pte = NULL;
+		return 0;
+	} else {
+		*pgmiddle = m;
+	}
+
+	t = pte_offset(m, addr);
+	if (pte_none(*t)) {
+		*pte = NULL;
+		return 0;
+	} else {
+	 	*pte = t;
+	}
+	kdb_printf("\naddr=%08lx, pgd=%08lx, pmd=%08lx, pte=%08lx\n",
+			addr,
+			(unsigned long) pgd_val(*d),
+			(unsigned long) pmd_val(*m),
+			(unsigned long) pte_val(*t));
+	return 0;
+}
+
+#define FORMAT_PGDIR(entry) \
+	kdb_printf("frame=%05lx %c %s %c %c %c %s %c %s %s \n",\
+			(entry >> PAGE_SHIFT), 				\
+			(entry & _PAGE_PRESENT)?'p':'n', 		\
+			(entry & _PAGE_RW)?"rw":"ro", 			\
+			(entry & _PAGE_USER)?'u':'s', 			\
+			(entry & _PAGE_ACCESSED)?'a':' ', 		\
+			' ', 						\
+			(entry & _PAGE_PSE)?"4M":"4K", 			\
+			(entry & _PAGE_GLOBAL)?'g':' ', 		\
+			(entry & _PAGE_PWT)?"wt":"wb", 			\
+			(entry & _PAGE_PCD)?"cd":"  ");
+
+#define FORMAT_PTE(p, entry) \
+	kdb_printf("frame=%05lx %c%c%c %c %c %c %s %c %s %s\n",	\
+			(entry >> PAGE_SHIFT), 			\
+			(pte_read(p))? 'r':'-', 		\
+			(pte_write(p))? 'w':'-', 		\
+			(pte_exec(p))? 'x':'-', 		\
+			(pte_dirty(p))? 'd':' ', 		\
+			(pte_young(p))? 'a':' ', 		\
+			(entry & _PAGE_USER)? 'u':'s', 		\
+			"  ", 					\
+			(entry & _PAGE_GLOBAL)? 'g':' ',	\
+			(entry & _PAGE_PWT)? "wt":"wb", 	\
+			(entry & _PAGE_PCD)? "cd":"  ");
+static int
+display_pgdir(unsigned long addr, pgd_t *pgdir, int count)
+{
+	unsigned long entry;
+	int i;
+	int index = pgdir - ((pgd_t *)(((unsigned long)pgdir) & PAGE_MASK));
+
+	count = min(count, PTRS_PER_PGD - index);
+	addr &= ~(PGDIR_SIZE-1);
+
+        for (i = 0; i < count; i++, pgdir++) {
+		entry = pgd_val(*pgdir);
+		kdb_printf("pgd: addr=%08lx ", addr);
+		if (pgd_none(*pgdir)) {
+			kdb_printf("pgdir not present\n");
+		} else {
+			FORMAT_PGDIR(entry);
+		}
+		addr += PGDIR_SIZE;
+	}
+	return i;
+}
+
+#if 0	/* for now, let's not print pgmiddle. */
+static int
+display_pgmiddle(unsigned long addr, pmd_t *pgmiddle, int count)
+{
+	unsigned long entry;
+	int i;
+	int index = pgmiddle - ((pmd_t *)(((unsigned long)pgmiddle) & PAGE_MASK));
+
+	count = min(count, PTRS_PER_PMD - index);
+	addr &= ~(PMD_SIZE-1);
+
+	for (i = 0; i < count; i++, pgmiddle++) {
+		entry = pmd_val(*pgmiddle);
+		kdb_printf("pmd: addr=%08lx ", addr);
+		if (pmd_none(*pgmiddle)) {
+			kdb_printf("pgmiddle not present\n");
+		} else {
+			FORMAT_PGDIR(entry);
+		}
+		addr += PMD_SIZE;
+	}
+	return i;
+}
+#endif
+
+static int
+display_pte(unsigned long addr, pte_t *pte, int count)
+{
+	unsigned long entry;
+	int i;
+	int index = pte - ((pte_t *)(((unsigned long)pte) & PAGE_MASK));
+
+	count = min(count, PTRS_PER_PTE - index);
+	addr &= PAGE_MASK;
+
+        for (i = 0; i < count; i++, pte++) {
+		entry = pte_val(*pte);
+		kdb_printf("pte: addr=%08lx ", addr);
+		if (pte_none(*pte)) {
+			kdb_printf("pte not present\n");
+		} else if (!pte_present(*pte)) {
+			kdb_printf("page swapped out. swp_offset=%08lx ", SWP_OFFSET(pte_to_swp_entry(*pte)));
+			kdb_printf("swp_type=%8lx", SWP_TYPE(pte_to_swp_entry(*pte)));
+		} else {
+			FORMAT_PTE(*pte, entry);
+		}
+		addr += PAGE_SIZE;
+	}
+	return i;
+}
+
+/*
+ * kdb_pte
+ *
+ *	This function implements the 'pte' command.
+ *
+ *	pte  <addr arg> [<line count>]
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+static int
+kdb_pte(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	static unsigned long last_addr = 0, last_count = 0;
+	int count = 8;
+	unsigned long addr;
+	long	offset = 0;
+	pgd_t * pgdir;
+	pmd_t * pgmiddle;
+	pte_t * pte;
+
+#ifdef CONFIG_X86_PAE
+	kdb_printf("This kernel is compiled with PAE support.");
+	return KDB_NOTIMP;
+#endif
+	kdbgetintenv("MDCOUNT", &count);
+
+	if (argc == 0) {
+		if (last_addr == 0)
+			return KDB_ARGCOUNT;
+		addr = last_addr;
+		if (last_count)
+			count = last_count;
+	} else {
+		kdb_machreg_t val;
+		int diag, nextarg = 1;
+		diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
+		if (diag)
+			return diag;
+		if (argc > nextarg+1)
+			return KDB_ARGCOUNT;
+
+		if (argc >= nextarg) {
+			diag = kdbgetularg(argv[nextarg], &val);
+			if (!diag) {
+				count = (int) val;
+				last_count = count;
+			} else if (last_count) {
+				count = last_count;
+			}
+		}
+	}
+
+	/*
+	 * round off the addr to a page boundary.
+	 */
+        addr &= PAGE_MASK;
+
+        get_pagetables(addr, &pgdir, &pgmiddle, &pte);
+
+	if (pgdir)
+		display_pgdir(addr, pgdir, 1);
+#if 0	/* for now, let's not print pgmiddle. */
+	   if (pgmiddle)
+		display_pgmiddle(addr, pgmiddle, 1);
+#endif
+	if (pte) {
+		int displayed;
+		displayed = display_pte(addr, pte, count);
+		addr += (displayed << PAGE_SHIFT);
+	}
+	last_addr = addr;
+	return 0;
+}
+
+/*
+ * kdb_rdv
+ *
+ *	This function implements the 'rdv' command.
+ *	It displays all registers of the current processor
+ *	included control registers in verbose mode.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ * 	This should have been an option to rd command say "rd v",
+ * 	but it is here as it is a non-essential x86-only command,
+ * 	that need not clutter arch/i386/kdb/kdbasupport.c.
+ */
+static int
+kdb_rdv(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	kdba_dumpregs(regs, NULL, NULL);
+	kdb_printf("\n");
+	display_eflags(regs->eflags);
+	kdb_printf("\n");
+	display_gdtr();
+	display_idtr();
+	display_ldtr();
+	kdb_printf("\n");
+	display_cr0();
+	display_cr3();
+	display_cr4();
+	kdb_printf("\n");
+	display_dr();
+	return 0;
+}
+
+static int __init kdbm_x86_init(void)
+{
+	kdb_register("rdv", kdb_rdv, NULL, "Display registers in verbose mode", 0);
+	kdb_register_repeat("gdt", kdb_gdt, "<sel> [<count>]", "Display GDT", 0, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("idt", kdb_idt, "<int> [<count>]", "Display IDT", 0, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("ldt", kdb_ldt, "<sel> [<count>]", "Display LDT", 0, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("ptex", kdb_pte, "<addr> [<count>]", "Display pagetables", 0, KDB_REPEAT_NO_ARGS);
+	kdb_register_repeat("ldtp", kdb_ldt, "<sel> [<count>]", "Display Process LDT", 0, KDB_REPEAT_NO_ARGS);
+	return 0;
+}
+
+static void __exit kdbm_x86_exit(void)
+{
+	kdb_unregister("rdv");
+	kdb_unregister("gdt");
+	kdb_unregister("ldt");
+	kdb_unregister("idt");
+	kdb_unregister("ptex");
+	kdb_unregister("ldtp");
+}
+
+module_init(kdbm_x86_init)
+module_exit(kdbm_x86_exit)