Index: gnu/gdb/gdb/ChangeLog.linux
diff -u /dev/null gnu/gdb/gdb/ChangeLog.linux:1.6
--- /dev/null	Thu Jun 25 14:09:31 1998
+++ gnu/gdb/gdb/ChangeLog.linux	Thu Jun 25 13:58:24 1998
@@ -0,0 +1,135 @@
+Thu Jun 25 19:09:56 1998  H.J. Lu  <hjl@gnu.org>
+
+	* Makefile.in (VERSION): Changed to "4.17.0.4 with Linux/x86
+	hardware watchpoint and FPU support".
+
+	* i386lnx-nat.c (i386_insert_aligned_watchpoint): Reuse the
+	old lookup address. Ignore large variable.
+
+Mon Jun  1 08:05:07 1998  H.J. Lu  <hjl@gnu.org>
+
+	* Makefile.in (VERSION): Changed to "4.17.0.3 with Linux/x86 FPU
+	support".
+
+	* i386lnx-nat.c (old_fetch_inferior_registers,
+	old_store_inferior_registers): Fake FP registers.
+
+Fri May 29 07:33:08 1998  H.J. Lu  <hjl@gnu.org>
+
+	* Makefile.in (i386lnx-nat.o): Add dependency.
+	(VERSION): Changed to 4.17.0.2.
+
+	* c-exp.y (parse_number): Fix comment.
+
+	* findvar.c (read_register_bytes): Use ARCH_NUM_REGS instead of
+	NUM_REGS.
+	(write_register_bytes): Likewise.
+	* i386-tdep.c (i386_frame_find_saved_regs): Likewise.
+	(i386_push_dummy_frame): Likewise.
+
+	* i386-tdep.c (i386_do_registers_info): Use RUNTIME_NUM_REGS
+	instead of DO_REGISTERS_INFO_NUM_REGS.
+	* i387-tdep.c (i387_float_info): Likewise.
+	* config/i386/tm-i386.h: Likewise.
+	* config/i386/tm-linux.h: Likewise.
+
+	* i386-tdep.c (i386_do_registers_info): Use INFO_REGMAP for
+	read_relative_register_raw_bytes and i387_print_register.
+	* i387-tdep.c (i387_float_info): Likewise.
+
+	* i386-tdep.c (i386_print_register): Fix a typo.
+
+	* i386lnx-nat.c (fetch_register, old_fetch_inferior_registers,
+	store_register, old_store_inferior_registers,
+	new_fetch_inferior_registers, new_store_inferior_registers,
+	i386_register_u_addr, supply_gregset, fill_gregset,
+	supply_fpregset, fill_fpregset, fetch_core_registers): Rewrite.
+	(get_runtime_num_regs): Renamed from get_reg_info_num_regs.
+
+	* config/i386/tm-linux.h (REGISTER_NAMES): Fixed according to
+	gcc register numbering scheme.
+	(SP_REGNUM, PS_REGNUM, FP0_REGNUM, FPC_REGNUM, FPSWD_REGNUM,
+	FPTWD_REGNUM, FPIPO_REGNUM, FPIPS_REGNUM, FPOOS_REGNUM,
+	FPOPS_REGNUM): Rearranged according to REGISTER_NAMES.
+	(REGISTER_CONVERTIBLE, REGISTER_BYTE, REGISTER_RAW_SIZE,
+	REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW): Updated.
+	(GREGISTER, GREGISTER_BYTE, FPREGISTER_BYTE): New.
+
+Mon May 25 22:18:03 1998  H.J. Lu  <hjl@gnu.org>
+
+	* breakpoint.c (VALUE_FIT_IN_REG): New.
+	(can_use_hardware_watchpoint): Use it.
+
+	* config/i386/linux.mh (NATDEPFILES): Remove i386v-nat.o
+	i386v4-nat.o and add i386lnx-nat.o.
+
+	* config/i386/nm-linux.h (FETCH_INFERIOR_REGISTERS): Defined.
+	(NO_SYS_REG_H): Removed.
+	(NO_PTRACE_H): undefined.
+	Include <sys/user.h> if HAVE_SYS_REG_H is not defined.
+
+	* config/i386/tm-i386.h (FPC_REGNUM): Defined as -1.
+	(FPCWD_REGNUM, FPSWD_REGNUM, FPTWD_REGNUM, FPIPO_REGNUM,
+	FPIPS_REGNUM, FPOOS_REGNUM, FPOPS_REGNUM): New.
+	(INFO_REGMAP): New.
+	(DO_REGISTERS_INFO_NUM_REGS): new.
+
+	* config/i386/tm-linux.h (NUM_FREGS, NUM_REGS: New.
+	(INFO_REGMAP): New.
+	(DO_REGISTERS_INFO_NUM_REGS): New.
+	(REGISTER_NAMES): New.
+	(FP_REGNUM, SP_REGNUM, PS_REGNUM, PC_REGNUM, FP0_REGNUM,
+	FPC_REGNUM, FPCWD_REGNUM, FPSWD_REGNUM, FPTWD_REGNUM,
+	FPIPO_REGNUM, FPIPS_REGNUM, FPOOS_REGNUM, FPOPS_REGNUM): New.
+	(GREGISTER_BYTES, gregister_set): New.
+	(FPEGISTER_BYTES, fpregister_set): New.
+	(REGISTER_BYTES): New.
+	(REGISTER_BYTE): New.
+	(VALUE_FIT_IN_REG): New.
+
+	* configure.in (AC_CHECK_HEADERS): Add sys/reg.h.
+	* configure: Regenerated.
+	* config.in: Likewise.
+
+	* i386-tdep.c (i386_print_status_word): New.
+
+	* i386lnx-nat.c: New.
+
+	* target.c (target_read_string): Handle partial read.
+
+	Based on patch from Bill Metzenthen <billm@suburbia.net>:
+	* config/i386/tm-linux.h (I386_LINUX_TARGET): New.
+	(MAX_REGISTER_RAW_SIZE, MAX_REGISTER_VIRTUAL_SIZE): New.
+	(TARGET_LONG_DOUBLE_BIT): New.
+	(HEX_LONG_DOUBLE_INPUT): new.
+	(REGISTER_CONVERTIBLE): New.
+	(REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW): New.
+	(REGISTER_VIRTUAL_TYPE): New.
+	(FLOAT_INFO): New.
+	(DO_REGISTERS_INFO): New.
+
+	* findvar.c (extract_floating): Also check
+	TARGET_LONG_DOUBLE_BIT for long double.
+
+	* i386-tdep.c (i386_extract_return_value): On Linux floating
+	point values are returned in floating registers.
+	(i386_do_registers_info): New.
+	(i386_print_register): New.
+
+	* i387-tdep.c (print_387_control_bits): Renamed from
+	print_387_control_word.
+	(print_387_status_bits: Renamed from print_387_status_word.
+	(print_387_control_word): New.
+	(print_387_status_word): New.
+	(i387_print_register): New.
+	(i387_float_info): New.
+	(i387_hex_long_double_input): New.
+
+	* valprint.c (print_floating): Handle TARGET_LONG_DOUBLE_BIT ==
+	80.
+
+Wed Feb 18 17:11:38 1998 Bill Metzenthen <billm@suburbia.net>
+
+	* c-exp.y (parse_number): Add long double support.
+
+	* config/i386/xm-linux.h (HOST_I386): New.
Index: gnu/gdb/gdb/Makefile.in
diff -u gnu/gdb/gdb/Makefile.in:1.1.1.1 gnu/gdb/gdb/Makefile.in:1.5
--- gnu/gdb/gdb/Makefile.in:1.1.1.1	Fri May 29 06:57:32 1998
+++ gnu/gdb/gdb/Makefile.in	Thu Jun 25 13:58:25 1998
@@ -187,7 +187,7 @@
 ADD_FILES = $(REGEX) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
 ADD_DEPS = $(REGEX1) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
 
-VERSION=4.17
+VERSION=4.17.0.4 with Linux/x86 hardware watchpoint and FPU support
 DIST=gdb
 
 LINT=/usr/5bin/lint
@@ -1097,6 +1097,9 @@
 	language.h $(gdbcore_h) $(floatformat_h) target.h
 
 i386b-nat.o: i386b-nat.c $(defs_h) 
+
+i386lnx-nat.o: i386lnx-nat.c $(floatformat_h) $(defs_h) $(gdbcore_h) \
+	$(inferior_h) language.h target.h
 
 i386ly-nat.o: i386ly-nat.c $(defs_h) $(frame_h) $(inferior_h) target.h
 
Index: gnu/gdb/gdb/breakpoint.c
diff -u gnu/gdb/gdb/breakpoint.c:1.1.1.1 gnu/gdb/gdb/breakpoint.c:1.2
--- gnu/gdb/gdb/breakpoint.c:1.1.1.1	Fri May 29 06:57:32 1998
+++ gnu/gdb/gdb/breakpoint.c	Fri May 29 07:03:27 1998
@@ -2828,6 +2828,11 @@
   mention (b);
 }
 
+#ifndef VALUE_FIT_IN_REG
+#define VALUE_FIT_IN_REG(v) \
+  (TYPE_LENGTH (VALUE_TYPE (v)) <= REGISTER_SIZE)
+#endif
+
 /* Return count of locations need to be watched and can be handled
    in hardware.  If the watchpoint can not be handled
    in hardware return zero.  */
@@ -2846,7 +2851,7 @@
     {
       if (v->lval == lval_memory)
 	{
-	  if (TYPE_LENGTH (VALUE_TYPE (v)) <= REGISTER_SIZE)
+	  if (VALUE_FIT_IN_REG (v))
 	    found_memory_cnt++;
         }
       else if (v->lval != not_lval && v->modifiable == 0)
Index: gnu/gdb/gdb/c-exp.y
diff -u gnu/gdb/gdb/c-exp.y:1.1.1.1 gnu/gdb/gdb/c-exp.y:1.3
--- gnu/gdb/gdb/c-exp.y:1.1.1.1	Fri May 29 06:57:32 1998
+++ gnu/gdb/gdb/c-exp.y	Fri May 29 11:50:22 1998
@@ -997,6 +997,18 @@
 	break;
       }
 
+#ifdef HEX_LONG_DOUBLE_INPUT
+  {
+    long double val;
+    if (HEX_LONG_DOUBLE_INPUT(base, p, len, &val))
+      {
+	putithere->typed_val_float.dval = val;
+	putithere->typed_val_float.type = builtin_type_long_double;
+	return FLOAT;
+      }
+  }
+#endif /* HEX_LONG_DOUBLE_INPUT */
+
   while (len-- > 0)
     {
       c = *p++;
Index: gnu/gdb/gdb/config.in
diff -u gnu/gdb/gdb/config.in:1.1.1.1 gnu/gdb/gdb/config.in:1.2
--- gnu/gdb/gdb/config.in:1.1.1.1	Fri May 29 06:57:33 1998
+++ gnu/gdb/gdb/config.in	Fri May 29 07:03:30 1998
@@ -135,6 +135,9 @@
 /* Define if you have the <sys/procfs.h> header file.  */
 #undef HAVE_SYS_PROCFS_H
 
+/* Define if you have the <sys/reg.h> header file.  */
+#undef HAVE_SYS_REG_H
+
 /* Define if you have the <termio.h> header file.  */
 #undef HAVE_TERMIO_H
 
Index: gnu/gdb/gdb/configure
diff -u gnu/gdb/gdb/configure:1.1.1.1 gnu/gdb/gdb/configure:1.2
--- gnu/gdb/gdb/configure:1.1.1.1	Fri May 29 06:57:33 1998
+++ gnu/gdb/gdb/configure	Fri May 29 07:03:31 1998
@@ -1376,7 +1376,7 @@
 
 fi
 
-for ac_hdr in limits.h memory.h string.h strings.h unistd.h termios.h termio.h sgtty.h stddef.h stdlib.h sys/procfs.h link.h endian.h objlist.h
+for ac_hdr in limits.h memory.h string.h strings.h unistd.h termios.h termio.h sgtty.h stddef.h stdlib.h sys/procfs.h link.h endian.h objlist.h sys/reg.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
Index: gnu/gdb/gdb/configure.in
diff -u gnu/gdb/gdb/configure.in:1.1.1.1 gnu/gdb/gdb/configure.in:1.2
--- gnu/gdb/gdb/configure.in:1.1.1.1	Fri May 29 06:57:33 1998
+++ gnu/gdb/gdb/configure.in	Fri May 29 07:03:32 1998
@@ -63,7 +63,7 @@
 AC_TYPE_SIGNAL
 
 AC_HEADER_STDC
-AC_CHECK_HEADERS(limits.h memory.h string.h strings.h unistd.h termios.h termio.h sgtty.h stddef.h stdlib.h sys/procfs.h link.h endian.h objlist.h)
+AC_CHECK_HEADERS(limits.h memory.h string.h strings.h unistd.h termios.h termio.h sgtty.h stddef.h stdlib.h sys/procfs.h link.h endian.h objlist.h sys/reg.h)
 AC_HEADER_STAT
 
 AC_C_CONST
Index: gnu/gdb/gdb/findvar.c
diff -u gnu/gdb/gdb/findvar.c:1.1.1.1 gnu/gdb/gdb/findvar.c:1.3
--- gnu/gdb/gdb/findvar.c:1.1.1.1	Fri May 29 06:57:34 1998
+++ gnu/gdb/gdb/findvar.c	Fri May 29 11:50:25 1998
@@ -312,7 +312,8 @@
       else
 	floatformat_to_doublest (TARGET_DOUBLE_FORMAT, addr, &dretval);
     }
-  else if (len == sizeof (DOUBLEST))
+  else if (len == sizeof (DOUBLEST)
+	   || len == (TARGET_LONG_DOUBLE_BIT / 8))
     {
       if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
 	{
@@ -360,7 +361,8 @@
       else
 	floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &val, addr);
     }
-  else if (len == sizeof (DOUBLEST))
+  else if (len == sizeof (DOUBLEST)
+	   || len == (TARGET_LONG_DOUBLE_BIT / 8))
     {
       if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
 	memcpy (addr, &val, sizeof (val));
@@ -660,7 +662,7 @@
   /* See if we are trying to read bytes from out-of-date registers.  If so,
      update just those registers.  */
 
-  for (regno = 0; regno < NUM_REGS; regno++)
+  for (regno = 0; regno < ARCH_NUM_REGS; regno++)
     {
       int regstart, regend;
       int startin, endin;
@@ -772,7 +774,7 @@
      like handling threads, and avoiding updates when the new and old contents
      are the same.  */
 
-  for (regno = 0; regno < NUM_REGS; regno++)
+  for (regno = 0; regno < ARCH_NUM_REGS; regno++)
     {
       int regstart, regend;
       int startin, endin;
Index: gnu/gdb/gdb/i386-tdep.c
diff -u gnu/gdb/gdb/i386-tdep.c:1.1.1.1 gnu/gdb/gdb/i386-tdep.c:1.3
--- gnu/gdb/gdb/i386-tdep.c:1.1.1.1	Fri May 29 06:57:34 1998
+++ gnu/gdb/gdb/i386-tdep.c	Fri May 29 11:50:26 1998
@@ -38,6 +38,10 @@
 
 static unsigned char codestream_fill PARAMS ((int));
 
+static void i386_print_register PARAMS ((char *, int, int));
+
+static void i386_print_status_word PARAMS ((char *, char *, long));
+
 /* Stdio style buffering was used to minimize calls to ptrace, but this
    buffering did not take into account that the code section being accessed
    may not be an even number of buffers long (even if the buffer is only
@@ -411,7 +415,7 @@
     {
       /* all regs were saved by push_call_dummy () */
       adr = fip->frame;
-      for (i = 0; i < NUM_REGS; i++) 
+      for (i = 0; i < ARCH_NUM_REGS; i++) 
 	{
 	  adr -= REGISTER_RAW_SIZE (i);
 	  fsrp->regs[i] = adr;
@@ -538,7 +542,7 @@
   sp = push_word (sp, read_register (PC_REGNUM));
   sp = push_word (sp, read_register (FP_REGNUM));
   write_register (FP_REGNUM, sp);
-  for (regnum = 0; regnum < NUM_REGS; regnum++)
+  for (regnum = 0; regnum < ARCH_NUM_REGS; regnum++)
     {
       read_register_gen (regnum, regbuf);
       sp = push_bytes (sp, regbuf, REGISTER_RAW_SIZE (regnum));
@@ -557,7 +561,7 @@
   
   fp = FRAME_FP (frame);
   get_frame_saved_regs (frame, &fsr);
-  for (regnum = 0; regnum < NUM_REGS; regnum++) 
+  for (regnum = 0; regnum < ARCH_NUM_REGS; regnum++) 
     {
       CORE_ADDR adr;
       adr = fsr.regs[regnum];
@@ -614,8 +618,9 @@
      char regbuf[REGISTER_BYTES];
      char *valbuf;
 {
-/* On AIX, floating point values are returned in floating point registers.  */
-#ifdef I386_AIX_TARGET
+  /* On AIX and Linux, floating point values are returned in floating
+     point registers.  */
+#if defined(I386_AIX_TARGET) || defined(I386_LINUX_TARGET)
   if (TYPE_CODE_FLT == TYPE_CODE(type))
     {
       double d;
@@ -626,7 +631,7 @@
       store_floating (valbuf, TYPE_LENGTH (type), d);
     }
   else
-#endif /* I386_AIX_TARGET */
+#endif /* I386_AIX_TARGET || I386_LINUX_TARGET*/
     { 
       memcpy (valbuf, regbuf, TYPE_LENGTH (type)); 
     }
@@ -718,4 +723,97 @@
 {
   tm_print_insn = print_insn_i386;
   tm_print_insn_info.mach = bfd_lookup_arch (bfd_arch_i386, 0)->mach;
+}
+
+/* Print the register regnum, or all registers if regnum is -1 */
+
+void
+i386_do_registers_info (regnum, fpregs)
+     int regnum;
+     int fpregs;
+{
+  char raw_regs [REGISTER_BYTES];
+  int numregs = RUNTIME_NUM_REGS (fpregs);
+  int i;
+
+  for (i = 0; i < numregs; i++)
+    read_relative_register_raw_bytes (INFO_REGMAP (i),
+				      raw_regs + REGISTER_BYTE (INFO_REGMAP (i)));
+
+  i386_print_register (raw_regs, regnum, NUM_REGS - NUM_FREGS);
+
+  if ((regnum == -1) && fpregs)
+    for (i = NUM_REGS - NUM_FREGS; i < numregs; i++)
+      i387_print_register (raw_regs, INFO_REGMAP (i));
+}
+
+static void
+i386_print_status_word (regname, string, status)
+     char *regname;
+     char *string;
+     long status;
+{
+  printf_filtered ("%8.8s: %10.10s IOPL: %d; flags:", regname, string,
+		   (status >> 12) & 0x3);
+  if (status & 0x1)
+    printf_unfiltered (" CF");
+  if (status & 0x4)
+    printf_unfiltered (" PF");
+  if (status & 0x10)
+    printf_unfiltered (" AF");
+  if (status & 0x40)
+    printf_unfiltered (" ZF");
+  if (status & 0x80)
+    printf_unfiltered (" SF");
+  if (status & 0x100)
+    printf_unfiltered (" TF");
+  if (status & 0x200)
+    printf_unfiltered (" IF");
+  if (status & 0x400)
+    printf_unfiltered (" DF");
+  if (status & 0x800)
+    printf_unfiltered (" OF");
+  if (status & 0x4000)
+    printf_unfiltered (" NT");
+  if (status & 0x10000)
+    printf_unfiltered (" RF");
+  if (status & 0x20000)
+    printf_unfiltered (" VM");
+  if (status & 0x40000)
+    printf_unfiltered (" AC");
+  if (status & 0x80000)
+    printf_unfiltered (" VIF");
+  if (status & 0x100000)
+    printf_unfiltered (" VIP");
+  if (status & 0x200000)
+    printf_unfiltered (" ID");
+  printf_unfiltered ("\n");
+}
+
+static void
+i386_print_register (raw_regs, regnum, numregs)
+     char *raw_regs;
+     int regnum;
+     int numregs;
+{
+  int i, j;
+  long val;
+  char string[24];
+
+  for (i = 0; i < numregs; i++)
+    {
+      j = INFO_REGMAP (i);
+
+      if ((regnum != -1) && (j != regnum))
+	continue;
+
+      val = extract_signed_integer (raw_regs + REGISTER_BYTE (j), 4);
+
+      sprintf(string, "0x%x", val);
+      if (j == PS_REGNUM)
+	i386_print_status_word (reg_names[j], string, val);
+      else
+	printf_filtered ("%8.8s: %10.10s %11d\n", reg_names[j],
+			 string, val);
+    }
 }
Index: gnu/gdb/gdb/i386lnx-nat.c
diff -u /dev/null gnu/gdb/gdb/i386lnx-nat.c:1.4
--- /dev/null	Thu Jun 25 14:09:40 1998
+++ gnu/gdb/gdb/i386lnx-nat.c	Thu Jun 25 13:58:27 1998
@@ -0,0 +1,844 @@
+/* Intel 386 native support for Linux
+   Copyright (C) 1998 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.  */
+
+#include "defs.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdb_string.h"
+
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/ptrace.h>
+
+#include "gdbcore.h"
+
+#ifdef HAVE_SYS_REG_H
+#include <sys/reg.h>
+#endif
+
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+#include <sys/debugreg.h>
+#endif
+
+#if !defined (PT_READ_I)
+#define PT_READ_I	1	/* Read word from text space */
+#endif
+#if !defined (PT_READ_D)
+#define	PT_READ_D	2	/* Read word from data space */
+#endif
+#if !defined (PT_READ_U)
+#define PT_READ_U	3	/* Read word from kernel user struct */
+#endif
+#if !defined (PT_WRITE_I)
+#define PT_WRITE_I	4	/* Write word to text space */
+#endif
+#if !defined (PT_WRITE_D)
+#define PT_WRITE_D	5	/* Write word to data space */
+#endif
+#if !defined (PT_WRITE_U)
+#define PT_WRITE_U	6	/* Write word to kernel user struct */
+#endif
+#if !defined (PT_CONTINUE)
+#define PT_CONTINUE	7	/* Continue after signal */
+#endif
+#if !defined (PT_STEP)
+#define PT_STEP		9	/* Set flag for single stepping */
+#endif
+#if !defined (PT_KILL)
+#define PT_KILL		8	/* Send child a SIGKILL signal */
+#endif
+
+#ifndef PT_ATTACH
+#define PT_ATTACH PTRACE_ATTACH
+#endif
+#ifndef PT_DETACH
+#define PT_DETACH PTRACE_DETACH
+#endif
+
+#if !defined(PT_GETREGS) && defined(PTRACE_GETREGS)
+#define PT_GETREGS PTRACE_GETREGS
+#endif
+#if !defined(PT_SETREGS) && defined(PTRACE_SETREGS)
+#define PT_SETREGS PTRACE_SETREGS
+#endif
+#if !defined(PT_GETFPREGS) && defined(PTRACE_GETFPREGS)
+#define PT_GETFPREGS PTRACE_GETFPREGS
+#endif
+#if !defined(PT_SETFPREGS) && defined(PTRACE_SETFPREGS)
+#define PT_SETFPREGS PTRACE_SETFPREGS
+#endif
+
+static void fetch_register PARAMS ((int));
+static void store_register PARAMS ((int));
+
+static void old_fetch_inferior_registers PARAMS ((int));
+static void old_store_inferior_registers PARAMS ((int));
+
+#ifdef PT_GETREGS
+static void new_fetch_inferior_registers PARAMS ((int));
+static void new_store_inferior_registers PARAMS ((int));
+static void init_fetch_inferior_registers PARAMS ((int));
+static void init_store_inferior_registers PARAMS ((int));
+
+static void (*fetch_inferior_registers_p) PARAMS ((int))
+  = init_fetch_inferior_registers;
+static void (*store_inferior_registers_p) PARAMS ((int))
+  = init_store_inferior_registers;
+
+static void set_inferior_registers_p PARAMS ((void));
+#else
+static void (*fetch_inferior_registers_p) PARAMS ((int))
+  = old_fetch_inferior_registers;
+static void (*store_inferior_registers_p) PARAMS ((int))
+  = old_store_inferior_registers;
+#endif
+
+/* Default the type of the ptrace transfer to int.  */
+#ifndef PTRACE_XFER_TYPE
+#define PTRACE_XFER_TYPE int
+#endif
+
+#ifndef PTRACE_ARG4_TYPE
+#define PTRACE_ARG4_TYPE int
+#endif
+
+#if !defined (offsetof)
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+/* U_REGS_OFFSET is the offset of the registers within the u area.  */
+#if !defined (U_REGS_OFFSET)
+#define U_REGS_OFFSET \
+  ptrace (PT_READ_U, inferior_pid, \
+	  (PTRACE_ARG3_TYPE) (offsetof (struct user, u_ar0)), 0) \
+    - KERNEL_U_ADDR
+#endif
+
+/* symbols like 'EAX' come from <sys/reg.h> or <asm/ptrace.h>. */
+#ifndef ORIG_EAX
+#define ORIG_EAX 11
+#endif
+
+#ifndef ST0
+#define ST0 7
+#endif
+
+#ifndef ST1
+#define ST1 8
+#endif
+
+#ifndef ST2
+#define ST2 9
+#endif
+
+#ifndef ST3
+#define ST3 10
+#endif
+
+#ifndef ST4
+#define ST4 11
+#endif
+
+#ifndef ST5
+#define ST5 12
+#endif
+
+#ifndef ST6
+#define ST6 13
+#endif
+
+#ifndef ST7
+#define ST7 14
+#endif
+
+#ifndef CWD
+#define CWD 0
+#endif
+
+#ifndef SWD
+#define SWD 1
+#endif
+
+#ifndef TWD
+#define TWD 2
+#endif
+
+#ifndef FIP
+#define FIP 3
+#endif
+
+#ifndef FCS
+#define FCS 4
+#endif
+
+#ifndef FOO
+#define FOO 5
+#endif
+
+#ifndef FOS
+#define FOS 6
+#endif
+
+/* Used for register mapping in system calls. */
+static int syscall_regmap [] = 
+{
+  EAX,
+  ECX,
+  EDX,
+  EBX,
+  UESP,
+  EBP,
+  ESI,
+  EDI,
+  EIP,
+  EFL,
+  ORIG_EAX,
+  ST0,
+  ST1,
+  ST2,
+  ST3,
+  ST4,
+  ST5,
+  ST6,
+  ST7,
+  CWD,
+  SWD,
+  TWD,
+  FIP,
+  FCS,
+  FOO,
+  FOS,
+  CS,
+  SS,
+  DS,
+  ES,
+  FS,
+  GS,
+};
+
+/* Used for register infomation mapping. */
+int info_regmap [] = 
+{
+  0,
+  1,
+  2,
+  3,
+  4,
+  5,
+  6,
+  7,
+  8,
+  9,
+  10,
+  26,
+  27,
+  28,
+  29,
+  30,
+  31,
+  11,
+  12,
+  13,
+  14,
+  15,
+  16,
+  17,
+  18,
+  19,
+  20,
+  21,
+  22,
+  23,
+  24,
+  25
+};
+
+/* Fetch one register.  */
+static void
+fetch_register (regno)
+     int regno;
+{
+  /* This isn't really an address.  But ptrace thinks of it as one.  */
+  CORE_ADDR regaddr;
+  char mess[128];				/* For messages */
+  register int i;
+  unsigned int offset;  /* Offset of registers within the u area.  */
+  char buf[MAX_REGISTER_RAW_SIZE];
+
+  offset = U_REGS_OFFSET;
+
+  regaddr = register_addr (regno, offset);
+  for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+    {
+      errno = 0;
+      *(PTRACE_XFER_TYPE *) &buf[i] = ptrace (PT_READ_U, inferior_pid,
+					      (PTRACE_ARG3_TYPE) regaddr, 0);
+      regaddr += sizeof (PTRACE_XFER_TYPE);
+      if (errno != 0)
+	{
+	  sprintf (mess, "reading register %s (#%d)", reg_names[regno], regno);
+	  perror_with_name (mess);
+	}
+    }
+  supply_register (regno, buf);
+}
+
+
+/* Fetch register values from the inferior.
+   If REGNO is negative, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time). */
+
+static void
+old_fetch_inferior_registers (regno)
+     int regno;
+{
+  if (regno >= 0)
+    {
+      if (GREGISTER (regno))
+	fetch_register (regno);
+      else
+	supply_register (regno, &registers[REGISTER_BYTE (regno)]);
+    }
+  else
+    {
+      for (regno = 0; regno < NUM_REGS; regno++)
+	{
+	  if (GREGISTER (regno))
+	    fetch_register (regno);
+	  else
+	    supply_register (regno, &registers[REGISTER_BYTE (regno)]);
+	}
+    }
+}
+
+/* Store one register. */
+
+static void
+store_register (regno)
+     int regno;
+{
+  /* This isn't really an address.  But ptrace thinks of it as one.  */
+  CORE_ADDR regaddr;
+  char mess[128];				/* For messages */
+  register int i;
+  unsigned int offset;  /* Offset of registers within the u area.  */
+
+  offset = U_REGS_OFFSET;
+
+  regaddr = register_addr (regno, offset);
+  for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(PTRACE_XFER_TYPE))
+    {
+      errno = 0;
+      ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+	      *(PTRACE_XFER_TYPE *) &registers[REGISTER_BYTE (regno) + i]);
+      regaddr += sizeof (PTRACE_XFER_TYPE);
+      if (errno != 0)
+	{
+	  sprintf (mess, "writing register %s (#%d)", reg_names[regno], regno);
+	  perror_with_name (mess);
+	}
+    }
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is negative, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+static void
+old_store_inferior_registers (regno)
+     int regno;
+{
+  if (regno >= 0)
+    {
+      if (GREGISTER (regno))
+	store_register (regno);
+    }
+  else
+    {
+      for (regno = 0; regno < NUM_REGS; regno++)
+	{
+	  if (GREGISTER (regno))
+	    store_register (regno);
+	}
+    }
+}
+
+#ifdef PT_GETREGS
+static void
+new_fetch_inferior_registers(regno)
+     int regno;
+{
+  char inferior_gregisters [GREGISTER_BYTES];
+  char inferior_fpregisters [FPREGISTER_BYTES];
+  int i;
+
+  ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) 0,
+	  (PTRACE_ARG4_TYPE) &inferior_gregisters [0]);
+  ptrace (PT_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) 0,
+	  (PTRACE_ARG4_TYPE) &inferior_fpregisters [0]);
+  for (i = 0; i < NUM_REGS; i++)
+    if (GREGISTER (i))
+      memcpy (&registers[REGISTER_BYTE (i)],
+	      &inferior_gregisters [GREGISTER_BYTE (syscall_regmap [i])],
+	      REGISTER_RAW_SIZE (i));
+    else
+      memcpy (&registers[REGISTER_BYTE (i)],
+	      &inferior_fpregisters [FPREGISTER_BYTE (syscall_regmap [i])],
+	      REGISTER_RAW_SIZE (i));
+  registers_fetched ();
+}
+
+static void
+new_store_inferior_registers(regno)
+     int regno;
+{
+  char inferior_gregisters [GREGISTER_BYTES];
+  char inferior_fpregisters [FPREGISTER_BYTES];
+  int i;
+
+  for (i = 0; i < NUM_REGS; i++)
+    if (GREGISTER (i))
+      memcpy (&inferior_gregisters [GREGISTER_BYTE (syscall_regmap [i])],
+	      &registers[REGISTER_BYTE (i)],
+	      REGISTER_RAW_SIZE (i));
+    else
+      memcpy (&inferior_fpregisters [FPREGISTER_BYTE (syscall_regmap [i])],
+	      &registers[REGISTER_BYTE (i)],
+	      REGISTER_RAW_SIZE (i));
+  ptrace (PT_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) 0,
+	  (PTRACE_ARG4_TYPE) &inferior_gregisters [0]);
+  ptrace (PT_SETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) 0,
+	  (PTRACE_ARG4_TYPE) &inferior_fpregisters [0]);
+}
+
+static void
+set_inferior_registers_p ()
+{
+  char inferior_registers [GREGISTER_BYTES];
+
+  if (ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) 0,
+	      (PTRACE_ARG4_TYPE) &inferior_registers) < 0)
+    {
+      if (errno == EIO)
+	{
+	  fetch_inferior_registers_p = old_fetch_inferior_registers;
+	  store_inferior_registers_p = old_store_inferior_registers;
+	}
+    }
+  else
+    {
+      fetch_inferior_registers_p = new_fetch_inferior_registers;
+      store_inferior_registers_p = new_store_inferior_registers;
+    }
+}
+
+void
+init_fetch_inferior_registers (regno)
+     int regno;
+{
+  set_inferior_registers_p ();
+  (*fetch_inferior_registers_p) (regno);
+}
+
+void
+init_store_inferior_registers (regno)
+     int regno;
+{
+  set_inferior_registers_p ();
+  (*store_inferior_registers_p) (regno);
+}
+#endif
+
+void
+fetch_inferior_registers(regno)
+{
+  (*fetch_inferior_registers_p) (regno);
+}
+
+void
+store_inferior_registers(regno)
+{
+  (*store_inferior_registers_p) (regno);
+}
+
+int
+get_runtime_num_regs (int fpregs)
+{
+#ifdef PT_GETREGS
+  if (fetch_inferior_registers_p == init_fetch_inferior_registers)
+    set_inferior_registers_p ();
+  if (!fpregs
+      || fetch_inferior_registers_p == old_fetch_inferior_registers)
+    return NUM_REGS - NUM_FREGS;
+  else
+    return NUM_REGS;
+#else
+  return NUM_REGS - NUM_FREGS;
+#endif
+}
+
+/* blockend is the value of u.u_ar0, and points to the
+ * place where GS is stored
+ */
+
+int
+i386_register_u_addr (blockend, regnum)
+     int blockend;
+     int regnum;
+{
+  return GREGISTER (regnum)
+	 ? (blockend + GREGISTER_BYTE (syscall_regmap [regnum])) : -1;
+}
+
+int
+kernel_u_size ()
+{
+  return (sizeof (struct user));
+}
+
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+
+/* Record the value of the debug control register.  */
+static int debug_control_mirror;
+
+/* Record which address associates with which register.  */
+static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1];
+
+static int
+i386_insert_aligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
+					   int));
+
+static int
+i386_insert_nonaligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
+					   int));
+
+/* Insert a watchpoint.  */
+
+int
+i386_insert_watchpoint (pid, addr, len, rw)
+     int pid;
+     CORE_ADDR addr;
+     int len;
+     int rw;
+{
+  return i386_insert_aligned_watchpoint (pid, addr, addr, len, rw);
+}
+
+static int
+i386_insert_aligned_watchpoint (pid, waddr, addr, len, rw)
+     int pid;
+     CORE_ADDR waddr;
+     CORE_ADDR addr;
+     int len;
+     int rw;
+{
+  int i;
+  int read_write_bits, len_bits;
+  int free_debug_register;
+  int register_number;
+  
+  /* Look for a free debug register.  */
+  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+    {
+      if (address_lookup[i - DR_FIRSTADDR] == 0
+	  || address_lookup[i - DR_FIRSTADDR] == addr)
+	break;
+    }
+
+  /* No more debug registers!  */
+  if (i > DR_LASTADDR)
+    return -1;
+
+  read_write_bits = (rw & 1) ? DR_RW_READ : DR_RW_WRITE;
+
+  if (len == 1)
+    len_bits = DR_LEN_1;
+  else if (len == 2)
+    {
+      if (addr % 2)
+	return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
+      len_bits = DR_LEN_2;
+    }
+
+  else if (len == 4)
+    {
+      if (addr % 4)
+	return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
+      len_bits = DR_LEN_4;
+    }
+  else if (len == 8 || len == 10 || len == 12)
+    {
+      /* It should only happen with long long, double or long double.
+	 All should be updated at the same time. We just watch the
+	 first 4 bytes. */
+      len = 4;
+      if (addr % 4)
+	return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
+      len_bits = DR_LEN_4;
+    }
+  else
+#if 1
+    /* Don't bother. x86 cannot handle it anyway. Save the hardware
+       waitpoint for others. We fake it to make gdb happy. */
+    return 0;
+#else
+    return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
+#endif
+  
+  free_debug_register = i;
+  register_number = free_debug_register - DR_FIRSTADDR;
+  debug_control_mirror |=
+    ((read_write_bits | len_bits)
+     << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
+  debug_control_mirror |=
+    (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
+  debug_control_mirror |= DR_LOCAL_SLOWDOWN;
+  debug_control_mirror &= ~DR_CONTROL_RESERVED;
+  
+  ptrace (PT_WRITE_U, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
+	  debug_control_mirror);
+  ptrace (PT_WRITE_U, pid, offsetof (struct user, u_debugreg[free_debug_register]),
+	  addr);
+
+  /* Record where we came from.  */
+  address_lookup[register_number] = addr;
+  return 0;
+}
+
+static int
+i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw)
+     int pid;
+     CORE_ADDR waddr;
+     CORE_ADDR addr;
+     int len;
+     int rw;
+{
+  int align;
+  int size;
+  int rv;
+
+  static int size_try_array[16] = {
+    1, 1, 1, 1,			/* trying size one */
+    2, 1, 2, 1,			/* trying size two */
+    2, 1, 2, 1,			/* trying size three */
+    4, 1, 2, 1			/* trying size four */
+  };
+
+  rv = 0;
+  while (len > 0)
+    {
+      align = addr % 4;
+      /* Four is the maximum length for 386.  */
+      size = (len > 4) ? 3 : len - 1;
+      size = size_try_array[size * 4 + align];
+
+      rv = i386_insert_aligned_watchpoint (pid, waddr, addr, size, rw);
+      if (rv)
+	{
+	  i386_remove_watchpoint (pid, waddr, size);
+	  return rv;
+	}
+      addr += size;
+      len -= size;
+    }
+  return rv;
+}
+
+/* Remove a watchpoint.  */
+
+int
+i386_remove_watchpoint (pid, addr, len)
+     int pid;
+     CORE_ADDR addr;
+     int len;
+{
+  int i;
+  int register_number;
+
+  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+    {
+      register_number = i - DR_FIRSTADDR;
+      if (address_lookup[register_number] == addr)
+	{
+	  debug_control_mirror &=
+	    ~(1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
+	  address_lookup[register_number] = 0;
+	}
+    }
+  ptrace (PT_WRITE_U, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
+	  debug_control_mirror);
+  ptrace (PT_WRITE_U, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+
+  return 0;
+}
+
+/* Check if stopped by a watchpoint.  */
+
+CORE_ADDR
+i386_stopped_by_watchpoint (pid)
+    int pid;
+{
+  int i;
+  int status;
+
+  status = ptrace (PT_READ_U, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+  ptrace (PT_WRITE_U, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+
+  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+    {
+      if (status & (1 << (i - DR_FIRSTADDR)))
+	return address_lookup[i - DR_FIRSTADDR];
+    }
+
+  return 0;
+}
+
+#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
+
+#ifdef HAVE_SYS_PROCFS_H
+
+#include <sys/procfs.h>
+
+#ifdef HAVE_GREGSET_T
+
+/*  Given a pointer to a general register set in /proc format (gregset_t *),
+    unpack the register contents and supply them as gdb's idea of the current
+    register values. */
+
+void
+supply_gregset (gregsetp)
+     gregset_t *gregsetp;
+{
+  char *g = (char *) gregsetp;
+  int i;
+
+  for (i = 0; i < NUM_REGS; i++)
+    if (GREGISTER (i))
+      *(greg_t *) &registers[REGISTER_BYTE (i)]
+	= *(greg_t *) &g [GREGISTER_BYTE (syscall_regmap [i])];
+}
+
+void
+fill_gregset (gregsetp, regno)
+     gregset_t *gregsetp;
+     int regno;
+{
+  char *g = (char *) gregsetp;
+
+  if (regno == -1)
+    {
+      int i;
+      for (i = 0; i < NUM_REGS; i++)
+	if (GREGISTER (i))
+	  *(greg_t *) &g [GREGISTER_BYTE (syscall_regmap [i])]
+	    = *(greg_t *) &registers[REGISTER_BYTE (i)];
+    }
+  else
+    {
+      *(greg_t *) &g [GREGISTER_BYTE (syscall_regmap [regno])]
+	= *(greg_t *) &registers[REGISTER_BYTE (regno)];
+    }
+}
+
+#endif	/* HAVE_GREGSET_T */
+
+#if defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T)
+
+/*  Given a pointer to a floating point register set in /proc format
+    (fpregset_t *), unpack the register contents and supply them as gdb's
+    idea of the current floating point register values. */
+
+void
+supply_fpregset (fpregsetp)
+     fpregset_t *fpregsetp;
+{
+  char *fp = (char *) fpregsetp;
+  int i;
+
+  for (i = 0; i < NUM_REGS; i++)
+    if (!GREGISTER (i))
+      memcpy (&registers[REGISTER_BYTE (i)],
+	      &fp [FPREGISTER_BYTE (syscall_regmap [i])],
+	      REGISTER_RAW_SIZE (i));
+}
+
+/*  Given a pointer to a floating point register set in /proc format
+    (fpregset_t *), update the register specified by REGNO from gdb's idea
+    of the current floating point register set.  If REGNO is -1, update
+    them all. */
+
+void
+fill_fpregset (fpregsetp, regno)
+     fpregset_t *fpregsetp;
+     int regno;
+{
+  char *fp = (char *) fpregsetp;
+
+  if (regno == -1)
+    {
+      int i;
+
+      for (i = 0; i < NUM_REGS; i++)
+	if (!GREGISTER (i))
+	  memcpy (&fp [FPREGISTER_BYTE (syscall_regmap [i])],
+		  &registers[REGISTER_BYTE (i)],
+		  REGISTER_RAW_SIZE (i));
+    }
+  else
+    {
+      memcpy (&fp [FPREGISTER_BYTE (syscall_regmap [regno])],
+	      &registers[REGISTER_BYTE (regno)],
+	      REGISTER_RAW_SIZE (regno));
+    }
+}
+
+#endif	/* defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T) */
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, ignored)
+     char *core_reg_sect;
+     unsigned core_reg_size;
+     int which;
+     CORE_ADDR ignored;
+{
+  if (core_reg_size == GREGISTER_BYTES)
+    supply_gregset (core_reg_sect);
+#if defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T)
+  else if (core_reg_size == FPREGISTER_BYTES)
+    supply_fpregset (core_reg_sect);
+#endif
+  else
+    fprintf_unfiltered (gdb_stderr, "Unknown core size: %d",
+			core_reg_size);
+}
+
+static struct core_fns elf_core_fns =
+{
+  bfd_target_elf_flavour,
+  fetch_core_registers,
+  NULL
+};
+
+void
+_initialize_i386linux_nat ()
+{
+  add_core_fns (&elf_core_fns);
+}
+
+#endif	/* HAVE_SYS_PROCFS_H */
Index: gnu/gdb/gdb/i387-tdep.c
diff -u gnu/gdb/gdb/i387-tdep.c:1.1.1.1 gnu/gdb/gdb/i387-tdep.c:1.3
--- gnu/gdb/gdb/i387-tdep.c:1.1.1.1	Fri May 29 06:57:35 1998
+++ gnu/gdb/gdb/i387-tdep.c	Fri May 29 11:50:28 1998
@@ -1,5 +1,5 @@
 /* Intel 387 floating point stuff.
-   Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1989, 1991-98 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -43,65 +43,257 @@
   floatformat_from_double (&floatformat_i387_ext, (double *)from, to);
 }
 
-void
-print_387_control_word (control)
+static void
+print_387_control_bits (control)
      unsigned int control;
 {
-  printf_unfiltered ("control %s: ", local_hex_string(control));
-  printf_unfiltered ("compute to ");
   switch ((control >> 8) & 3) 
     {
-    case 0: printf_unfiltered ("24 bits; "); break;
-    case 1: printf_unfiltered ("(bad); "); break;
-    case 2: printf_unfiltered ("53 bits; "); break;
-    case 3: printf_unfiltered ("64 bits; "); break;
+    case 0: puts_unfiltered (" 24 bit; "); break;
+    case 1: puts_unfiltered (" (bad); "); break;
+    case 2: puts_unfiltered (" 53 bit; "); break;
+    case 3: puts_unfiltered (" 64 bit; "); break;
     }
-  printf_unfiltered ("round ");
   switch ((control >> 10) & 3) 
     {
-    case 0: printf_unfiltered ("NEAREST; "); break;
-    case 1: printf_unfiltered ("DOWN; "); break;
-    case 2: printf_unfiltered ("UP; "); break;
-    case 3: printf_unfiltered ("CHOP; "); break;
+    case 0: puts_unfiltered ("NEAR; "); break;
+    case 1: puts_unfiltered ("DOWN; "); break;
+    case 2: puts_unfiltered ("UP; "); break;
+    case 3: puts_unfiltered ("CHOP; "); break;
     }
   if (control & 0x3f) 
     {
-      printf_unfiltered ("mask:");
-      if (control & 0x0001) printf_unfiltered (" INVALID");
-      if (control & 0x0002) printf_unfiltered (" DENORM");
-      if (control & 0x0004) printf_unfiltered (" DIVZ");
-      if (control & 0x0008) printf_unfiltered (" OVERF");
-      if (control & 0x0010) printf_unfiltered (" UNDERF");
-      if (control & 0x0020) printf_unfiltered (" LOS");
-      printf_unfiltered (";");
+      puts_unfiltered ("mask");
+      if (control & 0x0001) puts_unfiltered (" INVAL");
+      if (control & 0x0002) puts_unfiltered (" DENOR");
+      if (control & 0x0004) puts_unfiltered (" DIVZ");
+      if (control & 0x0008) puts_unfiltered (" OVERF");
+      if (control & 0x0010) puts_unfiltered (" UNDER");
+      if (control & 0x0020) puts_unfiltered (" LOS");
+      puts_unfiltered (";");
     }
-  printf_unfiltered ("\n");
-  if (control & 0xe080) warning ("reserved bits on: %s\n",
+  if (control & 0xe080) warning ("\nreserved bits on: %s",
 				local_hex_string(control & 0xe080));
 }
 
 void
-print_387_status_word (status)
+print_387_control_word (control)
+     unsigned int control;
+{
+  printf_filtered ("control %s:", local_hex_string(control & 0xffff));
+  print_387_control_bits (control);
+  puts_unfiltered ("\n");
+}
+
+static void
+print_387_status_bits (status)
      unsigned int status;
 {
-  printf_unfiltered ("status %s: ", local_hex_string (status));
-  if (status & 0xff) 
-    {
-      printf_unfiltered ("exceptions:");
-      if (status & 0x0001) printf_unfiltered (" INVALID");
-      if (status & 0x0002) printf_unfiltered (" DENORM");
-      if (status & 0x0004) printf_unfiltered (" DIVZ");
-      if (status & 0x0008) printf_unfiltered (" OVERF");
-      if (status & 0x0010) printf_unfiltered (" UNDERF");
-      if (status & 0x0020) printf_unfiltered (" LOS");
-      if (status & 0x0040) printf_unfiltered (" FPSTACK");
-      printf_unfiltered ("; ");
-    }
-  printf_unfiltered ("flags: %d%d%d%d; ",
+  printf_unfiltered (" flags %d%d%d%d; ",
 	  (status & 0x4000) != 0,
 	  (status & 0x0400) != 0,
 	  (status & 0x0200) != 0,
 	  (status & 0x0100) != 0);
+  printf_unfiltered ("top %d; ", (status >> 11) & 7);
+  if (status & 0xff) 
+    {
+      puts_unfiltered ("excep");
+      if (status & 0x0001) puts_unfiltered (" INVAL");
+      if (status & 0x0002) puts_unfiltered (" DENOR");
+      if (status & 0x0004) puts_unfiltered (" DIVZ");
+      if (status & 0x0008) puts_unfiltered (" OVERF");
+      if (status & 0x0010) puts_unfiltered (" UNDER");
+      if (status & 0x0020) puts_unfiltered (" LOS");
+      if (status & 0x0040) puts_unfiltered (" STACK");
+    }
+}
 
-  printf_unfiltered ("top %d\n", (status >> 11) & 7);
+void
+print_387_status_word (status)
+     unsigned int status;
+{
+  printf_filtered ("status %s:", local_hex_string (status & 0xffff));
+  print_387_status_bits (status);
+  puts_unfiltered ("\n");
+}
+
+
+void
+i387_print_register (raw_regs, regnum)
+     char *raw_regs;
+     int regnum;
+{
+  unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+  unsigned long val;
+  int j, sign, special;
+  unsigned swd, tags, expon, top, norm, ls, ms;
+  char string[12];
+
+  printf_filtered ("%8.8s: ", reg_names[regnum]);
+  if (REGISTER_RAW_SIZE (regnum) == 4)
+    {
+      val = extract_unsigned_integer (raw_regs + REGISTER_BYTE (regnum), 4);
+      switch (regnum)
+	{
+	case FPCWD_REGNUM:
+	case FPSWD_REGNUM:
+	case FPTWD_REGNUM:
+	case FPOPS_REGNUM:
+	  /* Don't print the un-modifiable bytes. */
+	  sprintf(string, "0x%04x", val & 0xffff);
+	  break;
+
+	default:
+	  sprintf(string, "0x%08x", val);
+	  break;
+	}
+
+      printf_unfiltered ("%10.10s", string);
+
+      if ( regnum == FPCWD_REGNUM)
+	print_387_control_bits (val);
+      else if ( regnum == FPSWD_REGNUM)
+	print_387_status_bits (val);
+    }
+  else
+    {
+      /* Put the data in the buffer.  No conversions are ever necessary. */
+      memcpy (virtual_buffer, raw_regs + REGISTER_BYTE (regnum), 10);
+
+      swd = extract_signed_integer (raw_regs + REGISTER_BYTE (FP0_REGNUM+1),
+				    4);
+      top = (swd >> 11) & 7;
+      tags = extract_signed_integer (raw_regs + REGISTER_BYTE (FP0_REGNUM+2),
+				     4);
+
+      puts_unfiltered ("0x");
+      for (j = 0; j < 10; j++)
+	printf_unfiltered ("%02x",
+			   (unsigned char)raw_regs[REGISTER_BYTE (regnum)
+						  + 9 - j]);
+      
+      puts_unfiltered ("  ");
+      special = 0;
+      switch ((tags >> (((regnum - FP0_REGNUM + top) & 7) * 2)) & 3) 
+	{
+	case 0: puts_unfiltered ("Valid "); break;
+	case 1: puts_unfiltered ("Zero  "); break;
+	case 2: puts_unfiltered ("Spec  ");
+	  special = 1;
+	  break;
+	case 3: puts_unfiltered ("Empty "); break;
+	}
+
+      expon = extract_unsigned_integer (raw_regs + REGISTER_BYTE (regnum)
+					+ 8, 2);
+      sign = expon & 0x8000;
+      expon &= 0x7fff;
+      ms = extract_unsigned_integer (raw_regs + REGISTER_BYTE (regnum) + 4, 4);
+      ls = extract_signed_integer (raw_regs + REGISTER_BYTE (regnum), 4);
+      norm = ms & 0x80000000;
+
+      if ( expon == 0 )
+	{
+	  if ( ms | ls )
+	    {
+	      /* Denormal or Pseudodenormal. */
+	      if ( norm )
+		puts_unfiltered ("Pseudo ");
+	      else
+		puts_unfiltered ("Denorm ");
+	    }
+	  else
+	    {
+	      /* Zero. */
+	      puts_unfiltered ("Zero   ");
+	    }
+	}
+      else if ( expon == 0x7fff )
+	{
+	  /* Infinity, NaN or unsupported. */
+	  if ( (ms == 0x80000000) &&
+	       (ls == 0) )
+	    {
+              puts_unfiltered ("Infty  ");
+	    }
+	  else if ( norm )
+	    {
+	      if ( ms & 0x40000000 )
+		puts_unfiltered ("QNaN   ");
+	      else
+		puts_unfiltered ("SNaN   ");
+	    }
+	  else
+	    {
+              puts_unfiltered ("Unsupp ");
+	    }
+	}
+      else
+	{
+	  /* Normal or unsupported. */
+	  if ( norm )
+	    puts_unfiltered ("Normal ");
+	  else
+	    puts_unfiltered ("Unsupp ");
+	}
+
+      val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0,
+		 gdb_stdout, 0,
+		 1, 0, Val_pretty_default);
+    }
+  puts_filtered ("\n");
+}
+
+void
+i387_float_info ()
+{
+  char raw_regs [REGISTER_BYTES];
+  int numregs = RUNTIME_NUM_REGS (1);
+  int i;
+
+  if (numregs != NUM_REGS)
+    {
+      printf_filtered ("No floating point info available for this run-time environment.\n");
+      return;
+    }
+
+  for (i = NUM_REGS - NUM_FREGS; i < numregs; i++)
+    read_relative_register_raw_bytes (INFO_REGMAP (i),
+				      raw_regs + REGISTER_BYTE (INFO_REGMAP (i)));
+
+  for (i = NUM_REGS - NUM_FREGS; i < numregs; i++)
+    i387_print_register (raw_regs, INFO_REGMAP (i));
+}
+
+int
+i387_hex_long_double_input(p, val)
+     char *p;
+     DOUBLEST *val;
+{
+  int c, n, len = 20;
+
+  n = 0;
+  for (len = 20-1; len >= 0; len--)
+    {
+      c = *p++;
+      if (c >= 'A' && c <= 'Z')
+	c += 'a' - 'A';
+      n *= 16;
+      if (c >= '0' && c <= '9')
+	{
+	  n += c - '0';
+	}
+      else if (c >= 'a' && c <= 'f')
+	{
+	  n += c - 'a' + 10;
+	}
+      else
+	return 0;	/* Char not a digit */
+      if ( ! (len & 1) )
+	{
+	  ((unsigned char *)val)[len/2] = n;
+	  n = 0;
+	}
+    }
+  return 1;
 }
Index: gnu/gdb/gdb/target.c
diff -u gnu/gdb/gdb/target.c:1.1.1.1 gnu/gdb/gdb/target.c:1.2
--- gnu/gdb/gdb/target.c:1.1.1.1	Fri May 29 06:57:38 1998
+++ gnu/gdb/gdb/target.c	Fri May 29 07:03:38 1998
@@ -656,11 +656,11 @@
 
   while (len > 0)
     {
-      tlen = MIN (len, 4 - (memaddr & 3));
       offset = memaddr & 3;
 
-      errcode = target_xfer_memory (memaddr & ~3, buf, 4, 0, NULL);
-      if (errcode != 0)
+      tlen = target_read_memory_partial (memaddr & ~3, buf, 4,
+					 &errcode);
+      if (tlen == 0 && errcode != 0)
 	goto done;
 
       if (bufptr - buffer + tlen > buffer_allocated)
@@ -678,6 +678,7 @@
 	  if (buf[i + offset] == '\000')
 	    {
 	      nbytes_read += i + 1;
+	      errcode = 0;
 	      goto done;
 	    }
 	}
Index: gnu/gdb/gdb/valprint.c
diff -u gnu/gdb/gdb/valprint.c:1.1.1.1 gnu/gdb/gdb/valprint.c:1.2
--- gnu/gdb/gdb/valprint.c:1.1.1.1	Fri May 29 06:57:39 1998
+++ gnu/gdb/gdb/valprint.c	Fri May 29 07:03:39 1998
@@ -517,10 +517,25 @@
 	high &= 0xfffff;
       }
     else
-      /* Extended.  We can't detect NaNs for extendeds yet.  Also note
-	 that currently extendeds get nuked to double in
-	 REGISTER_CONVERTIBLE.  */
-      is_nan = 0;
+      {
+#if TARGET_LONG_DOUBLE_BIT == 80
+	unsigned expon;
+
+	low = extract_unsigned_integer (valaddr, 4);
+	high = extract_unsigned_integer (valaddr + 4, 4);
+	expon = extract_unsigned_integer (valaddr + 8, 2);
+
+	nonnegative = ((expon & 0x8000) == 0);
+	is_nan = ((expon & 0x7fff) == 0x7fff)
+	  && ((high & 0x80000000) == 0x80000000)
+	  && (((high & 0x7fffffff) | low) != 0);
+#else
+	/* Extended.  We can't detect NaNs for extendeds yet.  Also note
+	   that currently extendeds get nuked to double in
+	   REGISTER_CONVERTIBLE.  */
+	is_nan = 0;
+#endif
+      }
 
     if (is_nan)
       {
@@ -551,7 +566,12 @@
     fprintf_filtered (stream, "%.17g", (double) doub);
   else
 #ifdef PRINTF_HAS_LONG_DOUBLE
+#if TARGET_LONG_DOUBLE_BIT == 80
+    /* Looks like it is a 10 byte long double */
+    fprintf_filtered (stream, "%.22Lg", doub);
+#else
     fprintf_filtered (stream, "%.35Lg", doub);
+#endif
 #else
     /* This at least wins with values that are representable as doubles */
     fprintf_filtered (stream, "%.17g", (double) doub);
Index: gnu/gdb/gdb/config/i386/linux.mh
diff -u gnu/gdb/gdb/config/i386/linux.mh:1.1.1.1 gnu/gdb/gdb/config/i386/linux.mh:1.2
--- gnu/gdb/gdb/config/i386/linux.mh:1.1.1.1	Fri May 29 06:57:44 1998
+++ gnu/gdb/gdb/config/i386/linux.mh	Fri May 29 07:03:43 1998
@@ -4,4 +4,5 @@
 XDEPFILES= ser-tcp.o
 
 NAT_FILE= nm-linux.h
-NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o core-aout.o core-regset.o i386v-nat.o i386v4-nat.o
+NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o \
+  core-aout.o core-regset.o i386lnx-nat.o
Index: gnu/gdb/gdb/config/i386/nm-linux.h
diff -u gnu/gdb/gdb/config/i386/nm-linux.h:1.1.1.1 gnu/gdb/gdb/config/i386/nm-linux.h:1.2
--- gnu/gdb/gdb/config/i386/nm-linux.h:1.1.1.1	Fri May 29 06:57:44 1998
+++ gnu/gdb/gdb/config/i386/nm-linux.h	Fri May 29 07:03:45 1998
@@ -31,12 +31,10 @@
 /* Tell gdb that we can attach and detach other processes */
 #define ATTACH_DETACH
 
-#define U_REGS_OFFSET 0
+#define FETCH_INFERIOR_REGISTERS
 
-/* GNU/Linux uses the SYSV i386v-nat.c support, but doesn't have <sys/reg.h> */
+#define U_REGS_OFFSET 0
 
-#define NO_SYS_REG_H
- 
 /* GNU/Linux supports the 386 hardware debugging registers.  */
 
 #define TARGET_HAS_HARDWARE_WATCHPOINTS
@@ -73,5 +71,13 @@
 i386_insert_watchpoint PARAMS ((int pid, CORE_ADDR addr, int len, int rw));
 extern int
 i386_remove_watchpoint PARAMS ((int pid, CORE_ADDR addr, int len));
+
+/* That is a kludge to work around a bug in glibc header files. */
+
+#ifndef HAVE_SYS_REG_H
+#include <sys/user.h>
+#endif
+
+#undef NO_PTRACE_H
 
 #endif /* #ifndef NM_LINUX_H */
Index: gnu/gdb/gdb/config/i386/tm-i386.h
diff -u gnu/gdb/gdb/config/i386/tm-i386.h:1.1.1.1 gnu/gdb/gdb/config/i386/tm-i386.h:1.3
--- gnu/gdb/gdb/config/i386/tm-i386.h:1.1.1.1	Fri May 29 06:57:44 1998
+++ gnu/gdb/gdb/config/i386/tm-i386.h	Fri May 29 11:50:32 1998
@@ -112,7 +112,19 @@
 #define PS_REGNUM 9	/* (ps)  Contains processor status */
 
 #define FP0_REGNUM 16   /* (st0) 387 register */
-#define FPC_REGNUM 25	/* 80387 control register */
+#define FPC_REGNUM -1	/* 80387 control register */
+
+#define FPCWD_REGNUM FPC_REGNUM
+#define FPSWD_REGNUM -1	/* 80387 status register */
+#define FPTWD_REGNUM -1	/* 80387 tag register */
+#define FPIPO_REGNUM -1	/* 80387 instruction pointer offset register */
+#define FPIPS_REGNUM -1	/* 80387 instruction pointer selector egister */
+#define FPOOS_REGNUM -1	/* 80387 operand pointer offset register */
+#define FPOPS_REGNUM -1	/* 80387 operand pointer selector register */
+
+#define INFO_REGMAP(regno) regno
+
+#define RUNTIME_NUM_REGS(fp) NUM_REGS
 
 /* Total amount of space needed to store our copies of the machine's register
    state, the array `registers'. */
Index: gnu/gdb/gdb/config/i386/tm-linux.h
diff -u gnu/gdb/gdb/config/i386/tm-linux.h:1.1.1.1 gnu/gdb/gdb/config/i386/tm-linux.h:1.3
--- gnu/gdb/gdb/config/i386/tm-linux.h:1.1.1.1	Fri May 29 06:57:45 1998
+++ gnu/gdb/gdb/config/i386/tm-linux.h	Fri May 29 11:50:33 1998
@@ -20,10 +20,239 @@
 #ifndef TM_LINUX_H
 #define TM_LINUX_H
 
-/* FIXME:  If nothing else gets added to this file, it could be removed
-   and configure could just use tm-i386.h instead. -fnf */
+#define I386_LINUX_TARGET
 
 #include "i386/tm-i386.h"
+
+#undef NUM_FREGS
+#define NUM_FREGS 15
+
+#undef NUM_REGS
+#define NUM_REGS 32
+
+extern int info_regmap [];
+
+#undef INFO_REGMAP
+#define INFO_REGMAP(regno) info_regmap [(regno)]
+
+extern int get_runtime_num_regs PARAMS ((int));
+
+#undef RUNTIME_NUM_REGS 
+#define RUNTIME_NUM_REGS(fp) get_runtime_num_regs ((fp))
+
+/* Initializer for an array of names of registers. The order of the
+   first 19 registers, 8 general purpose registers, %eip, %eflags,
+   dummy, and 8 floating point registers, must match the compiler's
+   numbering scheme. There should be NUM_REGS strings in this
+   initializer. */
+
+#undef  REGISTER_NAMES
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx",		\
+			 "esp", "ebp", "esi", "edi",		\
+			 "eip", "eflags", "orig_eax",		\
+			 "st0", "st1", "st2", "st3",		\
+			 "st4", "st5", "st6", "st7",		\
+			 "fctrl", "fstat", "ftag", "fip",	\
+			 "fcs", "fopoff", "fopsel",		\
+			 "cs", "ss", "ds", "es", "fs", "gs"	\
+			}
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#undef FP_REGNUM
+#define FP_REGNUM 5	/* (ebp) Contains address of executing stack frame */
+#undef  SP_REGNUM
+#define SP_REGNUM  4	/* (usp) Contains address of top of stack */
+#undef  PS_REGNUM
+#define PS_REGNUM  9	/* (ps)  Contains processor status */
+#undef  PC_REGNUM
+#define PC_REGNUM  8	/* (eip) Contains program counter */
+#undef  FP0_REGNUM
+#define FP0_REGNUM 11	/* Floating point register 0 */
+#undef  FPC_REGNUM
+#define FPC_REGNUM 19	/* 80387 control register */
+#undef  FPCWD_REGNUM
+#define FPCWD_REGNUM FPC_REGNUM
+#undef  FPSWD_REGNUM
+#define FPSWD_REGNUM 20	/* 80387 status register */
+#undef  FPTWD_REGNUM
+#define FPTWD_REGNUM 21 /* 80387 tag register */
+#undef  FPIPO_REGNUM
+#define FPIPO_REGNUM 22	/* 80387 instruction pointer offset register */
+#undef  FPIPS_REGNUM
+#define FPIPS_REGNUM 23	/* 80387 instruction pointer selector egister */
+#undef  FPOOS_REGNUM
+#define FPOOS_REGNUM 24	/* 80387 operand pointer offset register */
+#undef  FPOPS_REGNUM
+#define FPOPS_REGNUM 25 /* 80387 operand pointer selector register */
+
+/* Nonzero if register N requires conversion from raw format to virtual
+   format.  */
+#undef REGISTER_CONVERTIBLE
+#define REGISTER_CONVERTIBLE(N) (((unsigned)((N) - FP0_REGNUM)) < 8)
+
+/* Amount of bytes needed for general purpose registers. */
+#undef GREGISTER_BYTES
+#define GREGISTER_BYTES (17*4)
+
+/* Amount of bytes needed for floating point registers. */
+#undef FPREGISTER_BYTES
+#define FPREGISTER_BYTES (7*4 + 8*10)
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+
+#undef  REGISTER_BYTES
+#define REGISTER_BYTES (GREGISTER_BYTES + FPREGISTER_BYTES)
+
+/* Is register N a general purpose register? */
+
+#undef GREGISTER
+#define GREGISTER(N) ((N) < FP0_REGNUM || (N) >= FP0_REGNUM + NUM_FREGS)
+
+/* Index for general purpose register in system calls. */
+
+#undef  GREGISTER_BYTE
+#define GREGISTER_BYTE(N) ((N) * 4)
+
+/* Index for floating point register in system calls. */
+
+#undef  FPREGISTER_BYTE
+#define FPREGISTER_BYTE(N) \
+ ((N) < 7 ? (N) * 4 : (((N) - 7) * 10) + 28)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#undef  REGISTER_BYTE
+#define REGISTER_BYTE(N) \
+ ((N) < FP0_REGNUM ? (N) * 4 : REGISTER_CONVERTIBLE (N) \
+  ? (((N) - FP0_REGNUM) * 10) + 44 : (((N) - FP0_REGNUM - 8) * 4) + 124)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  */
+
+#undef  REGISTER_RAW_SIZE
+#define REGISTER_RAW_SIZE(N) (REGISTER_CONVERTIBLE (N) ? 10 : 4)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+#undef MAX_REGISTER_RAW_SIZE
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+#undef  MAX_REGISTER_VIRTUAL_SIZE
+#define MAX_REGISTER_VIRTUAL_SIZE 10
+
+#undef TARGET_LONG_DOUBLE_BIT
+#define TARGET_LONG_DOUBLE_BIT 80
+
+/* Does a value fit in a register? Although a long long, double or long
+   double doesn't fit in a register, since x86 has to update all bytes
+   at once, it should be ok to just watch the first few bytes. */
+#undef VALUE_FIT_IN_REG
+#define VALUE_FIT_IN_REG(v) \
+  (TYPE_LENGTH (VALUE_TYPE (v)) <= REGISTER_SIZE \
+   || TYPE_CODE (VALUE_TYPE (v)) == TYPE_CODE_INT \
+   || TYPE_CODE (VALUE_TYPE (v)) == TYPE_CODE_FLT)
+
+#if defined(HAVE_LONG_DOUBLE) && defined(HOST_I386)
+/* The host and target are i386 machines and the compiler supports
+   long doubles. Long doubles on the host therefore have the same
+   layout as a 387 FPU stack register. */
+#undef LD_I387
+#define LD_I387
+#endif
+
+#ifdef LD_I387
+/* Allow floating point numbers to be specified by
+   a raw long double 10 hex bytes number,
+   e.g. 1.0 can be input as 0x3fff8000000000000000
+   */
+extern int i387_hex_long_double_input(char *p, long double *putithere);
+#define HEX_LONG_DOUBLE_INPUT(base,p,len,target) \
+  ((base) == 16 && (len) == 20 \
+   && i387_hex_long_double_input ((p), (target)))
+#endif
+
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#ifdef LD_I387
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+  if (TYPE == REGISTER_VIRTUAL_TYPE (REGNUM)) \
+    { \
+      memcpy (TO, FROM, TYPE_LENGTH (TYPE)); \
+    } \
+  else \
+    { \
+      long double val = *((long double *)FROM); \
+      store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+    } \
+}
+#else
+/* Convert data from raw format for register REGNUM in buffer FROM
+   to virtual format with type TYPE in buffer TO.  */
+extern void i387_to_double PARAMS ((char *, char *));
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+  double val; \
+  i387_to_double ((FROM), (char *)&val); \
+  store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+#endif
+
+#undef REGISTER_CONVERT_TO_RAW
+#ifdef LD_I387
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+  if (TYPE == REGISTER_VIRTUAL_TYPE (REGNUM)) \
+    { \
+      memcpy (TO, FROM, TYPE_LENGTH (TYPE)); \
+    } \
+  else \
+    { \
+      long double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+      *((long double *)TO) = val; \
+    } \
+}
+#else
+extern void double_to_i387 PARAMS ((char *, char *));
+
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+  double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+  double_to_i387((char *)&val, (TO)); \
+}
+#endif
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#undef REGISTER_VIRTUAL_TYPE
+#ifdef LD_I387
+#define REGISTER_VIRTUAL_TYPE(N) \
+  ((N < FP0_REGNUM) ? builtin_type_int : builtin_type_long_double)
+#else
+#define REGISTER_VIRTUAL_TYPE(N) \
+  ((N < FP0_REGNUM) ? builtin_type_int : builtin_type_double)
+#endif
+
+#define FLOAT_INFO { i387_float_info (); }
+
+/* Define DO_REGISTERS_INFO() to do machine-specific formatting
+   of register dumps. */
+
+#define DO_REGISTERS_INFO(_regnum, fp) i386_do_registers_info(_regnum, fp)
+extern void i386_do_registers_info PARAMS ((int, int));
+
+extern void i387_print_register PARAMS ((char *, int));
+
+extern void i387_float_info PARAMS ((void));
 
 /* Offset to saved PC in sigcontext, from <linux/signal.h>.  */
 #define SIGCONTEXT_PC_OFFSET 38
Index: gnu/gdb/gdb/config/i386/xm-linux.h
diff -u gnu/gdb/gdb/config/i386/xm-linux.h:1.1.1.1 gnu/gdb/gdb/config/i386/xm-linux.h:1.2
--- gnu/gdb/gdb/config/i386/xm-linux.h:1.1.1.1	Fri May 29 06:57:45 1998
+++ gnu/gdb/gdb/config/i386/xm-linux.h	Fri May 29 07:03:48 1998
@@ -20,6 +20,8 @@
 #ifndef XM_LINUX_H
 #define XM_LINUX_H
 
+#define HOST_I386
+
 #define HOST_BYTE_ORDER LITTLE_ENDIAN
 
 #define HAVE_TERMIOS
Index: gnu/gdb/gdb/testsuite/ChangeLog.linux
diff -u /dev/null gnu/gdb/gdb/testsuite/ChangeLog.linux:1.1
--- /dev/null	Thu Jun 25 14:09:51 1998
+++ gnu/gdb/gdb/testsuite/ChangeLog.linux	Thu Jun 25 13:58:31 1998
@@ -0,0 +1,3 @@
+Thu Jun 25 19:09:56 1998  H.J. Lu  <hjl@gnu.org>
+
+	* default.exp: Check "No registers." for "info float".
Index: gnu/gdb/gdb/testsuite/gdb.base/default.exp
diff -u gnu/gdb/gdb/testsuite/gdb.base/default.exp:1.1.1.1 gnu/gdb/gdb/testsuite/gdb.base/default.exp:1.2
--- gnu/gdb/gdb/testsuite/gdb.base/default.exp:1.1.1.1	Fri May 29 06:58:01 1998
+++ gnu/gdb/gdb/testsuite/gdb.base/default.exp	Thu Jun 25 13:58:31 1998
@@ -274,7 +274,7 @@
 if [istarget "arm-*-coff"] then {
     gdb_test "info float" "Software FPU type.*mask:.*flags:.*" "info float"
 } else {
-    gdb_test "info float" "No floating point info available for this processor." "info float"
+    gdb_test "info float" "No registers.|No floating point info available for this processor." "info float"
 }
 #test info functions
 gdb_test "info functions" "All defined functions:" "info functions"
