This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[RFA]: x86_64 target


Hello,

  Here are the related files for the new target x86-64 with applied changes
which you recommended. This is split to two patches. The first one is changes to
i386-nat.c which is required to use in x86-64 target and includes a correction from
Eli Zaretskii. (I have already asked for approval but nobody answered)
  In the second part the use of watchpoints is rewritten,
struct gdbarch_tdep is reduced and necessary registers are defined as
recommended by Mark Kettenis
  + /* FPU status word.  */
  + #define FSTAT_REGNUM (FIRST_FPU_CTRL_REGNUM + 1)
  ...
  (the use of enum as prefered by Andrew Cagney is impossible because
  FIRST_FPU_CTRL_REGNUM is not constant)


Index: ChangeLog
from  Jiri Smid   <smid@suse.cz>
	* i386-nat.c (TARGET_HAS_DR_LEN_8, DR_LEN_8): Declare.
	(i386_length_and_rw_bits, i386_handle_nonaligned_watchpoint,
	i386_insert_watchpoint, i386_remove_watchpoint):  Add support for
	8-byte wide watchpoints.
	(i386_show_dr): Debug message format string change.

Index: i386-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-nat.c,v
retrieving revision 1.3
diff -c -3 -p -r1.3 i386-nat.c
*** i386-nat.c	2001/04/18 00:37:49	1.3
--- i386-nat.c	2001/09/12 08:01:19
***************
*** 60,65 ****
--- 60,70 ----
  
  #ifdef I386_USE_GENERIC_WATCHPOINTS
  
+ /* Support for 8-byte wide hw watchpoints.  */
+ #ifndef TARGET_HAS_DR_LEN_8
+ #define TARGET_HAS_DR_LEN_8 0
+ #endif
+ 
  /* Debug registers' indices.  */
  #define DR_NADDR		4  /* the number of debug address registers */
  #define DR_STATUS		6  /* index of debug status register (DR6) */
***************
*** 89,94 ****
--- 94,100 ----
  #define DR_LEN_1		(0x0 << 2) /* 1-byte region watch or breakpt */
  #define DR_LEN_2		(0x1 << 2) /* 2-byte region watch */
  #define DR_LEN_4		(0x3 << 2) /* 4-byte region watch */
+ #define DR_LEN_8		(0x2 << 2) /* 8-byte region watch (x86-64) */
  
  /* Local and Global Enable flags in DR7.
  
*************** i386_show_dr (const char *func, CORE_ADD
*** 252,260 ****
  		     dr_control_mirror, dr_status_mirror);
    ALL_DEBUG_REGISTERS(i)
      {
!       printf_unfiltered ("\tDR%d: addr=%08lx, ref.count=%d  DR%d: addr=%08lx, ref.count=%d\n",
! 			 i, dr_mirror[i], dr_ref_count[i],
! 			 i+1, dr_mirror[i+1], dr_ref_count[i+1]);
        i++;
      }
  }
--- 258,266 ----
  		     dr_control_mirror, dr_status_mirror);
    ALL_DEBUG_REGISTERS(i)
      {
!       printf_unfiltered ("\tDR%d: addr=0x%s, ref.count=%d  DR%d: addr=0x%s, ref.count=%d\n",
! 			 i, paddr(dr_mirror[i]), dr_ref_count[i],
! 			 i+1, paddr(dr_mirror[i+1]), dr_ref_count[i+1]);
        i++;
      }
  }
*************** Invalid hw breakpoint type %d in i386_le
*** 291,302 ****
  
    switch (len)
      {
-       case 4:
- 	return (DR_LEN_4 | rw);
-       case 2:
- 	return (DR_LEN_2 | rw);
        case 1:
  	return (DR_LEN_1 | rw);
        default:
  	internal_error (__FILE__, __LINE__, "\
  Invalid hw breakpoint length %d in i386_length_and_rw_bits.\n", len);
--- 297,311 ----
  
    switch (len)
      {
        case 1:
  	return (DR_LEN_1 | rw);
+       case 2:
+ 	return (DR_LEN_2 | rw);
+       case 4:
+ 	return (DR_LEN_4 | rw);
+       case 8:
+         if (TARGET_HAS_DR_LEN_8)
+  	  return (DR_LEN_8 | rw);
        default:
  	internal_error (__FILE__, __LINE__, "\
  Invalid hw breakpoint length %d in i386_length_and_rw_bits.\n", len);
*************** i386_handle_nonaligned_watchpoint (i386_
*** 407,426 ****
    int align;
    int size;
    int rv = 0, status = 0;
  
!   static int size_try_array[4][4] =
    {
!     { 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 */
    };
  
    while (len > 0)
      {
!       align = addr % 4;
!       /* Four is the maximum length an x86 debug register can watch.  */
!       size = size_try_array[len > 4 ? 3 : len - 1][align];
        if (what == WP_COUNT)
  	/* size_try_array[] is defined so that each iteration through
  	   the loop is guaranteed to produce an address and a size
--- 416,441 ----
    int align;
    int size;
    int rv = 0, status = 0;
+   int max_wp_len = TARGET_HAS_DR_LEN_8 ? 8 : 4;
  
!   static int size_try_array[8][8] =
    {
!     {1, 1, 1, 1, 1, 1, 1, 1},	/* trying size one */
!     {2, 1, 2, 1, 2, 1, 2, 1},	/* trying size two */
!     {2, 1, 2, 1, 2, 1, 2, 1},	/* trying size three */
!     {4, 1, 2, 1, 4, 1, 2, 1},	/* trying size four */
!     {4, 1, 2, 1, 4, 1, 2, 1},	/* trying size five */
!     {4, 1, 2, 1, 4, 1, 2, 1},	/* trying size six */
!     {4, 1, 2, 1, 4, 1, 2, 1},	/* trying size seven */
!     {8, 1, 2, 1, 4, 1, 2, 1},	/* trying size eight */
    };
  
    while (len > 0)
      {
!       align = addr % max_wp_len;
!       /* Four(eigth on x86_64) is the maximum length an x86 debug register
! 	 can watch.  */
!       size = size_try_array[len > max_wp_len ? (max_wp_len - 1) : len - 1][align];
        if (what == WP_COUNT)
  	/* size_try_array[] is defined so that each iteration through
  	   the loop is guaranteed to produce an address and a size
*************** i386_insert_watchpoint (CORE_ADDR addr, 
*** 466,472 ****
  {
    int retval;
  
!   if (len == 3 || len > 4 || addr % len != 0)
      retval = i386_handle_nonaligned_watchpoint (WP_INSERT, addr, len, type);
    else
      {
--- 481,488 ----
  {
    int retval;
  
!   if (((len != 1 && len !=2 && len !=4) && !(TARGET_HAS_DR_LEN_8 && len == 8))
!       || addr % len != 0)
      retval = i386_handle_nonaligned_watchpoint (WP_INSERT, addr, len, type);
    else
      {
*************** i386_remove_watchpoint (CORE_ADDR addr, 
*** 489,495 ****
  {
    int retval;
  
!   if (len == 3 || len > 4 || addr % len != 0)
      retval = i386_handle_nonaligned_watchpoint (WP_REMOVE, addr, len, type);
    else
      {
--- 505,512 ----
  {
    int retval;
  
!   if (((len != 1 && len !=2 && len !=4) && !(TARGET_HAS_DR_LEN_8 && len == 8))
!       || addr % len != 0)
      retval = i386_handle_nonaligned_watchpoint (WP_REMOVE, addr, len, type);
    else
      {


Index: ChangeLog
from  Jiri Smid   <smid@suse.cz>
	* configure.tgt: Recognize x86_64-*-linux* as a x86_64linux.
	* configure.host: Recognize x86_64-*-linux* as a x86_64linux.
	* NEWS: New target x86-64.
	* config/i386/x86_64linux.mh: New file.
	* config/i386/x86_64linux.mt: New file.
	* config/i386/nm-x86_64.h: New file.
	* x86_64-linux-tdep.c: New file.
	* x86_64-linux-nat.c: New file.
	* x86_64-nat.c: New file.
	* x86_64-tdep.c: New file.
	* x86_64-tdep.h: New file.
	* i386-tdep.h: New file.
	* i387-nat.c: Include i386-tdep.h when multiarch.
	* i387-tdep.c: Ditto.
	* config/djgpp/fnchange.lst: Add entries for x86_64-linux-tdep.c
	and x86_64-linux-nat.c
	* Makefile.in: Add x86_64-linux-tdep.o, x86_64-tdep.o,
	x86_64-linux-tdep.o, x86_64-nat.o, update dependencies.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.115
diff -c -3 -p -r1.115 Makefile.in
*** Makefile.in	2001/09/07 21:27:35	1.115
--- Makefile.in	2001/09/18 11:24:40
*************** i386-linux-tdep.o: i386-linux-tdep.c $(d
*** 1552,1558 ****
  i386v4-nat.o: i386v4-nat.c $(defs_h) $(regcache_h)
  
  i387-tdep.o: i387-tdep.c $(floatformat_h) $(defs_h) $(gdbcore_h) \
! 	$(inferior_h) language.h $(regcache_h) $(doublest_h)
  
  i960-tdep.o: i960-tdep.c $(floatformat_h) $(defs_h) $(expression_h) \
  	$(frame_h) $(gdbtypes_h) $(symtab_h) $(value_h) $(gdbcore_h) \
--- 1556,1562 ----
  i386v4-nat.o: i386v4-nat.c $(defs_h) $(regcache_h)
  
  i387-tdep.o: i387-tdep.c $(floatformat_h) $(defs_h) $(gdbcore_h) \
! 	$(inferior_h) language.h $(regcache_h) $(doublest_h) i386-tdep.h
  
  i960-tdep.o: i960-tdep.c $(floatformat_h) $(defs_h) $(expression_h) \
  	$(frame_h) $(gdbtypes_h) $(symtab_h) $(value_h) $(gdbcore_h) \
*************** values.o: values.c $(defs_h) $(expressio
*** 2076,2081 ****
--- 2080,2097 ----
  vax-tdep.o: vax-tdep.c $(OP_INCLUDE)/vax.h $(defs_h) $(symtab_h)
  
  w65-tdep.o : w65-tdep.c $(gdbcore_h) $(regcache_h)
+ 
+ x86-64-linux-tdep.o : x86-64-linux-tdep.c $(defs_h) $(inferior_h) $(gdbcore_h) \
+ 	$(regcache_h) x86-64-tdep.h i386-tdep.h
+ 
+ x86-64-tdep.o : x86-64-tdep.c $(defs_h) $(inferior_h) $(gdbcore_h) $(gdbcmd_h) \
+ 	$(arch_utils_h) $(regcache_h) $(symfile_h) x86-64-tdep.h i386-tdep.h
+ 
+ x86-64-linux-tdep.o : x86-64-linux-tdep.c $(defs_h) $(inferior_h) $(gdbcore_h) \
+ 	$(regcache_h) i387-nat.h x86-64-tdep.h i386-tdep.h
+ 
+ x86-64-nat.o : x86-64-nat.c $(defs_h) x86-64-tdep.h i386-tdep.h
  
  win32-nat.o: win32-nat.c $(gdbcmd_h) $(gdbcore_h) $(inferior_h) $(defs_h) \
  	$(gdb_string_h) $(regcache_h) $(completer_h)
Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.33
diff -c -3 -p -r1.33 NEWS
*** NEWS	2001/09/10 18:13:17	1.33
--- NEWS	2001/09/18 11:24:41
*************** ia64 AIX					ia64-*-aix*
*** 16,21 ****
--- 16,22 ----
  Motorola 68HC11 and 68HC12			m68hc11-elf
  CRIS						cris-axis
  UltraSparc running Linux			sparc64-*-linux*
+ Amd x86-64 running Linux			x86_64-*-linux-*
  
  * OBSOLETE configurations and files
  
Index: configure.host
===================================================================
RCS file: /cvs/src/src/gdb/configure.host,v
retrieving revision 1.23
diff -c -3 -p -r1.23 configure.host
*** configure.host	2001/07/10 20:41:54	1.23
--- configure.host	2001/09/18 11:24:41
*************** mips*)			gdb_host_cpu=mips ;;
*** 20,25 ****
--- 20,26 ----
  powerpc*)		gdb_host_cpu=powerpc ;;
  sparc64)		gdb_host_cpu=sparc ;;
  s390*)			gdb_host_cpu=s390 ;;
+ x86_64*)		gdb_host_cpu=i386 ;;
  *)			gdb_host_cpu=$host_cpu ;;
  
  esac
*************** xscale-*-*)		gdb_host=arm ;;
*** 162,166 ****
--- 163,169 ----
  vax-*-bsd*)		gdb_host=vaxbsd ;;
  vax-*-ultrix2*)		gdb_host=vaxult2 ;;
  vax-*-ultrix*)		gdb_host=vaxult ;;
+ 
+ x86_64-*-linux*)	gdb_host=x86-64linux ;;
  
  esac
Index: configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.35
diff -c -3 -p -r1.35 configure.tgt
*** configure.tgt	2001/08/12 03:39:11	1.35
--- configure.tgt	2001/09/18 11:24:41
*************** s390*)			gdb_target_cpu=s390 ;;
*** 27,32 ****
--- 27,33 ----
  strongarm*)		gdb_target_cpu=arm ;;
  xscale*)		gdb_target_cpu=arm ;;
  v850*)			gdb_target_cpu=v850 ;;
+ x86_64*)		gdb_target_cpu=i386 ;;
  *)			gdb_target_cpu=$target_cpu ;;
  
  esac
*************** v850*-*-*)		gdb_target=v850
*** 313,318 ****
--- 314,322 ----
  
  # OBSOLETE w65-*-*)		gdb_target=w65 ;;
  
+ x86_64-*-linux*)	gdb_target=x86-64linux
+  		configdirs="${configdirs} gdbserver" ;;
+ 
  z8k-*-coff*)		gdb_target=z8k ;;
  
  esac
*************** cris)		gdb_multi_arch=yes ;;
*** 325,328 ****
--- 329,333 ----
  d10v)		gdb_multi_arch=yes ;;
  m68hc11)	gdb_multi_arch=yes ;;
  mn10300)	gdb_multi_arch=yes ;;
+ x86-64linux)    gdb_multi_arch=yes ;;
  esac
Index: i386-tdep.h
===================================================================
RCS file: i386-tdep.h
diff -N i386-tdep.h
*** /dev/null	Tue May  5 13:32:27 1998
--- i386-tdep.h	Tue Sep 18 04:24:42 2001
***************
*** 0 ****
--- 1,73 ----
+ /* Target-dependent code for GDB, the GNU debugger.
+    Copyright 2001
+    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.  */
+ 
+ #ifndef I386_TDEP_H
+ #define I386_TDEP_H
+ 
+ #define FPU_REG_RAW_SIZE 10
+ 
+ #define XMM0_REGNUM FIRST_XMM_REGNUM
+ #define FIRST_FPU_REGNUM FP0_REGNUM
+ #define LAST_FPU_REGNUM (gdbarch_tdep (current_gdbarch)->last_fpu_regnum)
+ #define FIRST_XMM_REGNUM (gdbarch_tdep (current_gdbarch)->first_xmm_regnum)
+ #define LAST_XMM_REGNUM (gdbarch_tdep (current_gdbarch)->last_xmm_regnum)
+ #define MXCSR_REGNUM (gdbarch_tdep (current_gdbarch)->mxcsr_regnum)
+ #define FIRST_FPU_CTRL_REGNUM (gdbarch_tdep (current_gdbarch)->first_fpu_ctrl_regnum)
+ #define LAST_FPU_CTRL_REGNUM (FIRST_FPU_CTRL_REGNUM + 7)
+ 
+ /* All of these control registers (except for FCOFF and FDOFF) are
+    sixteen bits long (at most) in the FPU, but are zero-extended to
+    thirty-two bits in GDB's register file.  This makes it easier to
+    compute the size of the control register file, and somewhat easier
+    to convert to and from the FSAVE instruction's 32-bit format.  */
+ /* FPU control word.  */
+ #define FCTRL_REGNUM (FIRST_FPU_CTRL_REGNUM)
+ /* FPU status word.  */
+ #define FSTAT_REGNUM (FIRST_FPU_CTRL_REGNUM + 1)
+ /* FPU register tag word.  */
+ #define FTAG_REGNUM  (FIRST_FPU_CTRL_REGNUM + 2)
+ /* FPU instruction's code segment selector 16 bits, called "FPU Instruction
+    Pointer Selector" in the x86 manuals.  */
+ #define FCS_REGNUM   (FIRST_FPU_CTRL_REGNUM + 3)
+ /* FPU instruction's offset within segment ("Fpu Code OFFset").  */
+ #define FCOFF_REGNUM (FIRST_FPU_CTRL_REGNUM + 4)
+ /* FPU operand's data segment.  */
+ #define FDS_REGNUM   (FIRST_FPU_CTRL_REGNUM + 5)
+ /* FPU operand's offset within segment.  */
+ #define FDOFF_REGNUM (FIRST_FPU_CTRL_REGNUM + 6)
+ /* FPU opcode, bottom eleven bits.  */
+ #define FOP_REGNUM   (FIRST_FPU_CTRL_REGNUM + 7)
+ 
+ /* i386 architecture specific information.  */
+ struct gdbarch_tdep
+ {
+   int last_fpu_regnum;
+   int first_xmm_regnum;
+   int last_xmm_regnum;
+   int mxcsr_regnum;		/* Streaming SIMD Extension control/status.  */
+   int first_fpu_ctrl_regnum;
+ };
+ 
+ #define IS_FP_REGNUM(n) (FIRST_FPU_REGNUM <= (n) && (n) <= LAST_FPU_REGNUM)
+ #define IS_FPU_CTRL_REGNUM(n) (FIRST_FPU_CTRL_REGNUM <= (n) && (n) <= LAST_FPU_CTRL_REGNUM)
+ #define IS_SSE_REGNUM(n) (FIRST_XMM_REGNUM <= (n) && (n) <= LAST_XMM_REGNUM)
+ 
+ #endif
Index: i387-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/i387-nat.c,v
retrieving revision 1.5
diff -c -3 -p -r1.5 i387-nat.c
*** i387-nat.c	2001/04/27 16:06:53	1.5
--- i387-nat.c	2001/09/18 11:24:42
***************
*** 25,30 ****
--- 25,34 ----
  
  #include "i387-nat.h"
  
+ #if GDB_MULTI_ARCH > 0
+ #include "i386-tdep.h"
+ #endif
+ 
  /* FIXME: kettenis/2000-05-21: Right now more than a few i386 targets
     define their own routines to manage the floating-point registers in
     GDB's register array.  Most (if not all) of these targets use the
Index: i387-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i387-tdep.c,v
retrieving revision 1.13
diff -c -3 -p -r1.13 i387-tdep.c
*** i387-tdep.c	2001/08/01 18:39:23	1.13
--- i387-tdep.c	2001/09/18 11:24:42
***************
*** 30,35 ****
--- 30,38 ----
  #include "gdb_assert.h"
  #include "doublest.h"
  
+ #if GDB_MULTI_ARCH >0
+ #include "i386-tdep.h"
+ #endif
  
  /* FIXME: Eliminate the next two functions when we have the time to
     change all the callers.  */
Index: x86-64-linux-nat.c
===================================================================
RCS file: x86-64-linux-nat.c
diff -N x86-64-linux-nat.c
*** /dev/null	Tue May  5 13:32:27 1998
--- x86-64-linux-nat.c	Tue Sep 18 04:24:42 2001
***************
*** 0 ****
--- 1,577 ----
+ /* Native-dependent code for Linux/x86-64.
+    Copyright 2001
+    Free Software Foundation, Inc.
+    Contributed by Jiri Smid, SuSE Labs.
+ 
+    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 "gdbcore.h"
+ #include "regcache.h"
+ #include "i387-nat.h"
+ #include "gdb_assert.h"
+ #include "x86-64-tdep.h"
+ 
+ #include <sys/ptrace.h>
+ #include <sys/debugreg.h>
+ #include <sys/syscall.h>
+ #include <sys/procfs.h>
+ 
+ static unsigned long
+ x86_64_linux_dr_get (int regnum)
+ {
+   int tid;
+   unsigned long value;
+ 
+   /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
+      multi-threaded processes here.  For now, pretend there is just
+      one thread.  */
+   tid = PIDGET (inferior_ptid);
+ 
+   /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
+      ptrace call fails breaks debugging remote targets.  The correct
+      way to fix this is to add the hardware breakpoint and watchpoint
+      stuff to the target vectore.  For now, just return zero if the
+      ptrace call fails.  */
+   errno = 0;
+   value = ptrace (PT_READ_U, tid,
+ 		  offsetof (struct user, u_debugreg[regnum]), 0);
+   if (errno != 0)
+ #if 0
+     perror_with_name ("Couldn't read debug register");
+ #else
+     return 0;
+ #endif
+ 
+   return value;
+ }
+ 
+ static void
+ x86_64_linux_dr_set (int regnum, unsigned long value)
+ {
+   int tid;
+ 
+   /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
+      multi-threaded processes here.  For now, pretend there is just
+      one thread.  */
+   tid = PIDGET (inferior_ptid);
+ 
+   errno = 0;
+   ptrace (PT_WRITE_U, tid,
+ 	  offsetof (struct user, u_debugreg[regnum]), value);
+   if (errno != 0)
+     perror_with_name ("Couldn't write debug register");
+ }
+ 
+ void
+ x86_64_linux_dr_set_control (unsigned long control)
+ {
+   x86_64_linux_dr_set (DR_CONTROL, control);
+ }
+ 
+ void
+ x86_64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
+ {
+   gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
+ 
+   x86_64_linux_dr_set (DR_FIRSTADDR + regnum, addr);
+ }
+ 
+ void
+ x86_64_linux_dr_reset_addr (int regnum)
+ {
+   gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
+ 
+   x86_64_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
+ }
+ 
+ unsigned long
+ x86_64_linux_dr_get_status (void)
+ {
+   return x86_64_linux_dr_get (DR_STATUS);
+ }
+ 
+ 
+ /* The register sets used in Linux ELF core-dumps are identical to the
+    register sets in `struct user' that is used for a.out core-dumps,
+    and is also used by `ptrace'.  The corresponding types are
+    `elf_gregset_t' for the general-purpose registers (with
+    `elf_greg_t' the type of a single GP register) and `elf_fpregset_t'
+    for the floating-point registers.
+ 
+    Those types used to be available under the names `gregset_t' and
+    `fpregset_t' too, and this file used those names in the past.  But
+    those names are now used for the register sets used in the
+    `mcontext_t' type, and have a different size and layout.  */
+ 
+ /* Which ptrace request retrieves which registers?
+    These apply to the corresponding SET requests as well.  */
+ #define GETREGS_SUPPLIES(regno) \
+   (0 <= (regno) && (regno) <= 17)
+ #define GETFPREGS_SUPPLIES(regno) \
+   (FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
+ 
+ #define PTRACE_XFER_TYPE unsigned long
+ 
+ 
+ /* Transfering the general-purpose registers between GDB, inferiors
+    and core files.  */
+ 
+ /* Fill GDB's register array with the general-purpose register values
+    in *GREGSETP.  */
+ 
+ void
+ supply_gregset (elf_gregset_t * gregsetp)
+ {
+   elf_greg_t *regp = (elf_greg_t *) gregsetp;
+   int i;
+ 
+   for (i = 0; i < X86_64_NUM_GREGS; i++)
+     supply_register (i, (char *) (regp + x86_64_regmap[i]));
+ }
+ 
+ /* Fill register REGNO (if it is a general-purpose register) in
+    *GREGSETPS with the value in GDB's register array.  If REGNO is -1,
+    do this for all registers.  */
+ 
+ void
+ fill_gregset (elf_gregset_t * gregsetp, int regno)
+ {
+   elf_greg_t *regp = (elf_greg_t *) gregsetp;
+   int i;
+ 
+   for (i = 0; i < X86_64_NUM_GREGS; i++)
+     if ((regno == -1 || regno == i))
+       *(regp + x86_64_regmap[i]) =
+ 	*(elf_greg_t *) & registers[REGISTER_BYTE (i)];
+ }
+ 
+ /* Fetch all general-purpose registers from process/thread TID and
+    store their values in GDB's register array.  */
+ 
+ static void
+ fetch_regs (int tid)
+ {
+   elf_gregset_t regs;
+ 
+   if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
+       perror_with_name ("Couldn't get registers");
+ 
+   supply_gregset (&regs);
+ }
+ 
+ /* Store all valid general-purpose registers in GDB's register array
+    into the process/thread specified by TID.  */
+ 
+ static void
+ store_regs (int tid, int regno)
+ {
+   elf_gregset_t regs;
+ 
+   if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
+     perror_with_name ("Couldn't get registers");
+ 
+   fill_gregset (&regs, regno);
+ 
+   if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
+     perror_with_name ("Couldn't write registers");
+ }
+ 
+ 
+ /* Transfering floating-point registers between GDB, inferiors and cores.  */
+ 
+ /* Fill GDB's register array with the floating-point register values in
+    *FPREGSETP.  */
+ 
+ void
+ supply_fpregset (elf_fpregset_t * fpregsetp)
+ {
+   i387_supply_fxsave ((char *) fpregsetp);
+ }
+ 
+ /* Fill register REGNO (if it is a floating-point register) in
+    *FPREGSETP with the value in GDB's register array.  If REGNO is -1,
+    do this for all registers.  */
+ 
+ void
+ fill_fpregset (elf_fpregset_t * fpregsetp, int regno)
+ {
+   i387_fill_fxsave ((char *) fpregsetp, regno);
+ }
+ 
+ /* Fetch all floating-point registers from process/thread TID and store
+    thier values in GDB's register array.  */
+ 
+ static void
+ fetch_fpregs (int tid)
+ {
+   elf_fpregset_t fpregs;
+ 
+   if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
+     perror_with_name ("Couldn't get floating point status");
+ 
+   supply_fpregset (&fpregs);
+ }
+ 
+ /* Store all valid floating-point registers in GDB's register array
+    into the process/thread specified by TID.  */
+ 
+ static void
+ store_fpregs (int tid, int regno)
+ {
+   elf_fpregset_t fpregs;
+ 
+   if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
+     perror_with_name ("Couldn't get floating point status");
+ 
+   fill_fpregset (&fpregs, regno);
+ 
+   if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
+     perror_with_name ("Couldn't write floating point status");
+ }
+ 
+ 
+ /* Transferring arbitrary registers between GDB and inferior.  */
+ 
+ /* Fetch register REGNO from the child process.  If REGNO is -1, do
+    this for all registers (including the floating point and SSE
+    registers).  */
+ 
+ void
+ fetch_inferior_registers (int regno)
+ {
+   int tid;
+ 
+   /* Linux LWP ID's are process ID's.  */
+   if ((tid = TIDGET (inferior_ptid)) == 0)
+     tid = PIDGET (inferior_ptid);	/* Not a threaded program.  */
+ 
+   if (regno == -1)
+     {
+       fetch_regs (tid);
+       fetch_fpregs (tid);
+       return;
+     }
+ 
+   if (GETREGS_SUPPLIES (regno))
+     {
+       fetch_regs (tid);
+       return;
+     }
+ 
+   if (GETFPREGS_SUPPLIES (regno))
+     {
+       fetch_fpregs (tid);
+       return;
+     }
+ 
+   internal_error (__FILE__, __LINE__,
+ 		  "Got request for bad register number %d.", regno);
+ }
+ 
+ /* Store register REGNO back into the child process.  If REGNO is -1,
+    do this for all registers (including the floating point and SSE
+    registers).  */
+ void
+ store_inferior_registers (int regno)
+ {
+   int tid;
+ 
+   /* Linux LWP ID's are process ID's.  */
+   if ((tid = TIDGET (inferior_ptid)) == 0)
+     tid = PIDGET (inferior_ptid);	/* Not a threaded program.  */
+ 
+   /* Use the PTRACE_SETFPXREGS requests whenever possible, since it
+      transfers more registers in one system call.  But remember that
+      store_fpxregs can fail, and return zero.  */
+   if (regno == -1)
+     {
+       store_regs (tid, regno);
+       store_fpregs (tid, regno);
+       return;
+     }
+ 
+   if (GETREGS_SUPPLIES (regno))
+     {
+       store_regs (tid, regno);
+       return;
+     }
+ 
+   if (GETFPREGS_SUPPLIES (regno))
+     {
+       store_fpregs (tid, regno);
+       return;
+     }
+ 
+   internal_error (__FILE__, __LINE__,
+ 		  "Got request to store bad register number %d.", regno);
+ }
+ 
+ 
+ static const unsigned char linux_syscall[] = { 0x0f, 0x05 };
+ 
+ #define LINUX_SYSCALL_LEN (sizeof linux_syscall)
+ 
+ /* The system call number is stored in the %rax register.  */
+ #define LINUX_SYSCALL_REGNUM 0	/* %rax */
+ 
+ /* We are specifically interested in the sigreturn and rt_sigreturn
+    system calls.  */
+ 
+ #ifndef SYS_sigreturn
+ #define SYS_sigreturn		__NR_sigreturn
+ #endif
+ #ifndef SYS_rt_sigreturn
+ #define SYS_rt_sigreturn	__NR_rt_sigreturn
+ #endif
+ 
+ /* Offset to saved processor flags, from <asm/sigcontext.h>.  */
+ #define LINUX_SIGCONTEXT_EFLAGS_OFFSET (152)
+ /* Offset to saved processor registers from <asm/ucontext.h> */
+ #define LINUX_UCONTEXT_SIGCONTEXT_OFFSET (36)
+ 
+ /* Resume execution of the inferior process.
+    If STEP is nonzero, single-step it.
+    If SIGNAL is nonzero, give it that signal.  */
+ 
+ void
+ child_resume (ptid_t ptid, int step, enum target_signal signal)
+ {
+   int pid = PIDGET (ptid);
+   int request = PTRACE_CONT;
+ 
+   if (pid == -1)
+     /* Resume all threads.  */
+     /* I think this only gets used in the non-threaded case, where "resume
+        all threads" and "resume inferior_ptid" are the same.  */
+     pid = PIDGET (inferior_ptid);
+ 
+   if (step)
+     {
+       CORE_ADDR pc = read_pc_pid (pid_to_ptid (pid));
+       unsigned char buf[LINUX_SYSCALL_LEN];
+ 
+       request = PTRACE_SINGLESTEP;
+ 
+       /* Returning from a signal trampoline is done by calling a
+          special system call (sigreturn or rt_sigreturn, see
+          i386-linux-tdep.c for more information).  This system call
+          restores the registers that were saved when the signal was
+          raised, including %eflags.  That means that single-stepping
+          won't work.  Instead, we'll have to modify the signal context
+          that's about to be restored, and set the trace flag there.  */
+ 
+       /* First check if PC is at a system call.  */
+       if (read_memory_nobpt (pc, (char *) buf, LINUX_SYSCALL_LEN) == 0
+ 	  && memcmp (buf, linux_syscall, LINUX_SYSCALL_LEN) == 0)
+ 	{
+ 	  int syscall =
+ 	    read_register_pid (LINUX_SYSCALL_REGNUM, pid_to_ptid (pid));
+ 
+ 	  /* Then check the system call number.  */
+ 	  if (syscall == SYS_rt_sigreturn)
+ 	    {
+ 	      CORE_ADDR sp = read_register (SP_REGNUM);
+ 	      CORE_ADDR addr = sp;
+ 	      unsigned long int eflags;
+ 
+ 	      addr +=
+ 		sizeof (struct siginfo) + LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
+ 
+ 	      /* Set the trace flag in the context that's about to be
+ 	         restored.  */
+ 	      addr += LINUX_SIGCONTEXT_EFLAGS_OFFSET;
+ 	      read_memory (addr, (char *) &eflags, 8);
+ 	      eflags |= 0x0100;
+ 	      write_memory (addr, (char *) &eflags, 8);
+ 	    }
+ 	}
+     }
+ 
+   if (ptrace (request, pid, 0, target_signal_to_host (signal)) == -1)
+     perror_with_name ("ptrace");
+ }
+ 
+ 
+ /* Copy LEN bytes to or from inferior's memory starting at MEMADDR
+    to debugger memory starting at MYADDR.   Copy to inferior if
+    WRITE is nonzero.  TARGET is ignored.
+ 
+    Returns the length copied, which is either the LEN argument or zero.
+    This xfer function does not do partial moves, since child_ops
+    doesn't allow memory operations to cross below us in the target stack
+    anyway.  */
+ 
+ int
+ child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
+ 		   struct mem_attrib *attrib ATTRIBUTE_UNUSED,
+ 		   struct target_ops *target)
+ {
+   register int i;
+   /* Round starting address down to longword boundary.  */
+   register CORE_ADDR addr = memaddr & -sizeof (PTRACE_XFER_TYPE);
+   /* Round ending address up; get number of longwords that makes.  */
+   register int count
+     = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
+     / sizeof (PTRACE_XFER_TYPE);
+   /* Allocate buffer of that many longwords.  */
+   register PTRACE_XFER_TYPE *buffer
+     = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
+ 
+   if (write)
+     {
+       /* Fill start and end extra bytes of buffer with existing memory data.  */
+       if (addr != memaddr || len < (int) sizeof (PTRACE_XFER_TYPE))
+ 	{
+ 	  /* Need part of initial word -- fetch it.  */
+ 	  ptrace (PT_READ_I, PIDGET (inferior_ptid),
+ 		  (PTRACE_ARG3_TYPE) addr, buffer);
+ 	}
+ 
+       if (count > 1)		/* FIXME, avoid if even boundary */
+ 	{
+ 	  ptrace (PT_READ_I, PIDGET (inferior_ptid),
+ 		  ((PTRACE_ARG3_TYPE)
+ 		   (addr + (count - 1) * sizeof (PTRACE_XFER_TYPE))),
+ 		  buffer + count - 1);
+ 	}
+ 
+       /* Copy data to be written over corresponding part of buffer */
+ 
+       memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+ 	      myaddr, len);
+ 
+       /* Write the entire buffer.  */
+ 
+       for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+ 	{
+ 	  errno = 0;
+ 	  ptrace (PT_WRITE_D, PIDGET (inferior_ptid),
+ 		  (PTRACE_ARG3_TYPE) addr, buffer[i]);
+ 	  if (errno)
+ 	    {
+ 	      /* Using the appropriate one (I or D) is necessary for
+ 	         Gould NP1, at least.  */
+ 	      errno = 0;
+ 	      ptrace (PT_WRITE_I, PIDGET (inferior_ptid),
+ 		      (PTRACE_ARG3_TYPE) addr, buffer[i]);
+ 	    }
+ 	  if (errno)
+ 	    return 0;
+ 	}
+ #ifdef CLEAR_INSN_CACHE
+       CLEAR_INSN_CACHE ();
+ #endif
+     }
+   else
+     {
+       /* Read all the longwords */
+       for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+ 	{
+ 	  errno = 0;
+ 	  ptrace (PT_READ_I, PIDGET (inferior_ptid),
+ 		  (PTRACE_ARG3_TYPE) addr, buffer + i);
+ 	  if (errno)
+ 	    return 0;
+ 	}
+ 
+       /* Copy appropriate bytes out of the buffer.  */
+       memcpy (myaddr,
+ 	      (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+ 	      len);
+     }
+   return len;
+ }
+ 
+ /* Interpreting register set info found in core files.  */
+ 
+ /* Provide registers to GDB from a core file.
+ 
+    CORE_REG_SECT points to an array of bytes, which are the contents
+    of a `note' from a core file which BFD thinks might contain
+    register contents.  CORE_REG_SIZE is its size.
+ 
+    WHICH says which register set corelow suspects this is:
+      0 --- the general-purpose register set, in elf_gregset_t format
+      2 --- the floating-point register set, in elf_fpregset_t format
+ 
+    REG_ADDR isn't used on Linux.  */
+ 
+ static void
+ fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
+ 		      int which, CORE_ADDR reg_addr)
+ {
+   elf_gregset_t gregset;
+   elf_fpregset_t fpregset;
+   switch (which)
+     {
+     case 0:
+       if (core_reg_size != sizeof (gregset))
+ 	warning ("Wrong size gregset in core file.");
+       else
+ 	{
+ 	  memcpy (&gregset, core_reg_sect, sizeof (gregset));
+ 	  supply_gregset (&gregset);
+ 	}
+       break;
+ 
+     case 2:
+       if (core_reg_size != sizeof (fpregset))
+ 	warning ("Wrong size fpregset in core file.");
+       else
+ 	{
+ 	  memcpy (&fpregset, core_reg_sect, sizeof (fpregset));
+ 	  supply_fpregset (&fpregset);
+ 	}
+       break;
+ 
+     default:
+       /* We've covered all the kinds of registers we know about here,
+          so this must be something we wouldn't know what to do with
+          anyway.  Just ignore it.  */
+       break;
+     }
+ }
+ 
+ /* Register that we are able to handle Linux ELF core file formats.  */
+ 
+ static struct core_fns linux_elf_core_fns = {
+   bfd_target_elf_flavour,	/* core_flavour */
+   default_check_format,		/* check_format */
+   default_core_sniffer,		/* core_sniffer */
+   fetch_core_registers,		/* core_read_registers */
+   NULL				/* next */
+ };
+ 
+ 
+ #if !defined (offsetof)
+ #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+ #endif
+ 
+ /* Record the value of the debug control register.  */
+ static long debug_control_mirror;
+ 
+ /* Record which address associates with which register.  */
+ static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1];
+ 
+ void
+ _initialize_x86_64_linux_nat (void)
+ {
+   add_core_fns (&linux_elf_core_fns);
+ }
Index: x86-64-linux-tdep.c
===================================================================
RCS file: x86-64-linux-tdep.c
diff -N x86-64-linux-tdep.c
*** /dev/null	Tue May  5 13:32:27 1998
--- x86-64-linux-tdep.c	Tue Sep 18 04:24:42 2001
***************
*** 0 ****
--- 1,136 ----
+ /* Target-dependent code for Linux running on x86-64, for GDB.
+    Copyright 2001
+    Free Software Foundation, Inc.
+    Contributed by Jiri Smid, SuSE Labs.
+ 
+    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 "gdbcore.h"
+ #include "regcache.h"
+ #include "x86-64-tdep.h"
+ #include "dwarf2cfi.h"
+ 
+ #define STRUCT_OFFSET(struct_type, member)    \
+     ((long) ((char*) &((struct_type*) 0)->member))
+ 
+ #define LINUX_SIGTRAMP_INSN0 (0x48)	/* mov $NNNNNNNN,%rax */
+ #define LINUX_SIGTRAMP_OFFSET0 (0)
+ #define LINUX_SIGTRAMP_INSN1 (0x0f)	/* syscall */
+ #define LINUX_SIGTRAMP_OFFSET1 (7)
+ 
+ static const unsigned char linux_sigtramp_code[] = {
+   LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x89, 0x00, 0x00, 0x00,	/*  mov $0x89,%rax */
+   LINUX_SIGTRAMP_INSN1, 0x05	/* syscall */
+ };
+ 
+ #define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
+ 
+ /* If PC is in a sigtramp routine, return the address of the start of
+    the routine.  Otherwise, return 0.  */
+ 
+ static CORE_ADDR
+ x86_64_linux_sigtramp_start (CORE_ADDR pc)
+ {
+   unsigned char buf[LINUX_SIGTRAMP_LEN];
+   if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
+     return 0;
+ 
+   if (buf[0] != LINUX_SIGTRAMP_INSN0)
+     {
+       if (buf[0] != LINUX_SIGTRAMP_INSN1)
+ 	return 0;
+ 
+       pc -= LINUX_SIGTRAMP_OFFSET1;
+ 
+       if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
+ 	return 0;
+     }
+ 
+   if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
+     return 0;
+ 
+   return pc;
+ }
+ 
+ /* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>.  */
+ #define LINUX_UCONTEXT_SIGCONTEXT_OFFSET (36)
+ 
+ /* Assuming FRAME is for a Linux sigtramp routine, return the address
+    of the associated sigcontext structure.  */
+ CORE_ADDR
+ x86_64_linux_sigcontext_addr (struct frame_info *frame)
+ {
+   CORE_ADDR pc;
+ 
+   pc = x86_64_linux_sigtramp_start (frame->pc);
+   if (pc)
+     {
+       if (frame->next)
+ 	/* If this isn't the top frame, the next frame must be for the
+ 	   signal handler itself.  The sigcontext structure is part of
+ 	   the user context. */
+ 	return frame->next->frame + sizeof (struct siginfo) +
+ 	  LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
+ 
+ 
+       /* This is the top frame. */
+       return read_register (SP_REGNUM) + sizeof (struct siginfo) +
+ 	LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
+ 
+     }
+ 
+   error ("Couldn't recognize signal trampoline.");
+   return 0;
+ }
+ 
+ /* Offset to saved PC in sigcontext, from <asm/sigcontext.h>.  */
+ #define LINUX_SIGCONTEXT_PC_OFFSET (136)
+ 
+ /* Assuming FRAME is for a Linux sigtramp routine, return the saved
+    program counter.  */
+ 
+ CORE_ADDR
+ x86_64_linux_sigtramp_saved_pc (struct frame_info *frame)
+ {
+   CORE_ADDR addr;
+ 
+   addr = x86_64_linux_sigcontext_addr (frame);
+   return read_memory_integer (addr + LINUX_SIGCONTEXT_PC_OFFSET, 8);
+ }
+ 
+ /* Immediately after a function call, return the saved pc.  */
+ 
+ CORE_ADDR
+ x86_64_linux_saved_pc_after_call (struct frame_info *frame)
+ {
+   if (frame->signal_handler_caller)
+     return x86_64_linux_sigtramp_saved_pc (frame);
+ 
+   return read_memory_integer (read_register (SP_REGNUM), 8);
+ }
+ 
+ /* Saved Pc.  Get it from sigcontext if within sigtramp.  */
+ CORE_ADDR
+ x86_64_linux_frame_saved_pc (struct frame_info *frame)
+ {
+   if (frame->signal_handler_caller)
+     return x86_64_linux_sigtramp_saved_pc (frame);
+   return cfi_get_ra (frame);
+ }
Index: x86-64-nat.c
===================================================================
RCS file: x86-64-nat.c
diff -N x86-64-nat.c
*** /dev/null	Tue May  5 13:32:27 1998
--- x86-64-nat.c	Tue Sep 18 04:24:42 2001
***************
*** 0 ****
--- 1,57 ----
+ /* AMD x86_64 native support.
+    Copyright 2001
+    Free Software Foundation, Inc.
+    Contributed by Jiri Smid, SuSE Labs.
+ 
+    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 <sys/user.h>
+ #include "x86-64-tdep.h"
+ 
+ /* blockend is the value of u.u_ar0, and points to the
+    place where GS is stored.  */
+ 
+ CORE_ADDR
+ x86_64_register_u_addr (CORE_ADDR blockend, int regnum)
+ {
+   struct user u;
+   CORE_ADDR fpstate;
+   CORE_ADDR ubase;
+   ubase = blockend;
+   if (IS_FP_REGNUM (regnum))
+     {
+       fpstate = ubase + ((char *) &u.i387.st_space - (char *) &u);
+       return (fpstate + 16 * (regnum - FP0_REGNUM));
+     }
+   else if (IS_SSE_REGNUM (regnum))
+     {
+       fpstate = ubase + ((char *) &u.i387.xmm_space - (char *) &u);
+       return (fpstate + 16 * (regnum - XMM0_REGNUM));
+     }
+   else
+     return (ubase + 8 * x86_64_regmap[regnum]);
+ }
+ 
+ 
+ int
+ kernel_u_size (void)
+ {
+   return (sizeof (struct user));
+ }
Index: x86-64-tdep.c
===================================================================
RCS file: x86-64-tdep.c
diff -N x86-64-tdep.c
*** /dev/null	Tue May  5 13:32:27 1998
--- x86-64-tdep.c	Tue Sep 18 04:24:42 2001
***************
*** 0 ****
--- 1,1010 ----
+ /* Target-dependent code for the x86-64 for GDB, the GNU debugger.
+    Copyright 2001
+    Free Software Foundation, Inc.
+    Contributed by Jiri Smid, SuSE Labs.
+ 
+    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 "gdbcore.h"
+ #include "gdbcmd.h"
+ #include "arch-utils.h"
+ #include "regcache.h"
+ #include "symfile.h"
+ #include "x86-64-tdep.h"
+ #include "dwarf2cfi.h"
+ 
+ 
+ /* Register numbers of various important registers.  */
+ #define RAX_REGNUM 0
+ #define RDX_REGNUM 1
+ #define RDI_REGNUM 5
+ #define EFLAGS_REGNUM 17
+ #define XMM1_REGNUM  35
+ 
+ /* x86_64_register_raw_size_table[i] is the number of bytes of storage in
+    GDB's register array occupied by register i.  */
+ int x86_64_register_raw_size_table[X86_64_NUM_REGS] = {
+   8, 8, 8, 8,
+   8, 8, 8, 8,
+   8, 8, 8, 8,
+   8, 8, 8, 8,
+   8, 4,
+   10, 10, 10, 10,
+   10, 10, 10, 10,
+   4, 4, 4, 4,
+   4, 4, 4, 4,
+   16, 16, 16, 16,
+   16, 16, 16, 16,
+   16, 16, 16, 16,
+   16, 16, 16, 16,
+   4
+ };
+ 
+ /* Number of bytes of storage in the actual machine representation for
+    register REGNO.  */
+ int
+ x86_64_register_raw_size (int regno)
+ {
+   return x86_64_register_raw_size_table[regno];
+ }
+ 
+ /* x86_64_register_byte_table[i] is the offset into the register file of the
+    start of register number i.  We initialize this from
+    x86_64_register_raw_size_table.  */
+ int x86_64_register_byte_table[X86_64_NUM_REGS];
+ 
+ /* Index within `registers' of the first byte of the space for register REGNO.  */
+ int
+ x86_64_register_byte (int regno)
+ {
+   return x86_64_register_byte_table[regno];
+ }
+ 
+ /* Return the GDB type object for the "standard" data type of data in
+    register N. */
+ static struct type *
+ x86_64_register_virtual_type (int regno)
+ {
+   if (regno == PC_REGNUM || regno == SP_REGNUM)
+     return lookup_pointer_type (builtin_type_void);
+   if (IS_FP_REGNUM (regno))
+     return builtin_type_long_double;
+   if (IS_SSE_REGNUM (regno))
+     return builtin_type_v4sf;
+   if (IS_FPU_CTRL_REGNUM (regno) || regno == MXCSR_REGNUM
+       || regno == EFLAGS_REGNUM)
+     return builtin_type_int;
+   return builtin_type_long;
+ }
+ 
+ /* Number of bytes of storage in the program's representation
+    for register REGNO.  */
+ int
+ x86_64_register_virtual_size (int regno)
+ {
+   return (TYPE_LENGTH (x86_64_register_virtual_type (regno)));
+ }
+ 
+ /* x86_64_register_convertible is true if register N's virtual format is
+    different from its raw format.  Note that this definition assumes
+    that the host supports IEEE 32-bit floats, since it doesn't say
+    that SSE registers need conversion.  Even if we can't find a
+    counterexample, this is still sloppy.  */
+ int
+ x86_64_register_convertible (int regno)
+ {
+   return IS_FP_REGNUM (regno);
+ }
+ 
+ /* Convert data from raw format for register REGNUM in buffer FROM to
+    virtual format with type TYPE in buffer TO.  In principle both
+    formats are identical except that the virtual format has two extra
+    bytes appended that aren't used.  We set these to zero.  */
+ void
+ x86_64_register_convert_to_virtual (int regnum, struct type *type,
+ 				    char *from, char *to)
+ {
+ /* Copy straight over, but take care of the padding.  */
+   memcpy (to, from, FPU_REG_RAW_SIZE);
+   memset (to + FPU_REG_RAW_SIZE, 0, TYPE_LENGTH (type) - FPU_REG_RAW_SIZE);
+ }
+ 
+ /* Convert data from virtual format with type TYPE in buffer FROM to
+    raw format for register REGNUM in buffer TO.  Simply omit the two
+    unused bytes.  */
+ 
+ void
+ x86_64_register_convert_to_raw (struct type *type, int regnum,
+ 				char *from, char *to)
+ {
+   memcpy (to, from, FPU_REG_RAW_SIZE);
+ }
+ 
+ 
+ /* This is the variable that is set with "set disassembly-flavour", and
+    its legitimate values.  */
+ static const char att_flavour[] = "att";
+ static const char intel_flavour[] = "intel";
+ static const char *valid_flavours[] = {
+   att_flavour,
+   intel_flavour,
+   NULL
+ };
+ static const char *disassembly_flavour = att_flavour;
+ 
+ static CORE_ADDR
+ x86_64_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
+ {
+   char buf[8];
+ 
+   store_unsigned_integer (buf, 8, CALL_DUMMY_ADDRESS ());
+ 
+   write_memory (sp - 8, buf, 8);
+   return sp - 8;
+ }
+ 
+ void
+ x86_64_pop_frame (void)
+ {
+   generic_pop_current_frame (cfi_pop_frame);
+ }
+ 
+ 
+ /* The returning of values is done according to the special algorithm.
+    Some types are returned in registers an some (big structures) in memory.
+    See ABI for details.
+  */
+ 
+ #define MAX_CLASSES 4
+ 
+ enum x86_64_reg_class
+ {
+   X86_64_NO_CLASS,
+   X86_64_INTEGER_CLASS,
+   X86_64_INTEGERSI_CLASS,
+   X86_64_SSE_CLASS,
+   X86_64_SSESF_CLASS,
+   X86_64_SSEDF_CLASS,
+   X86_64_SSEUP_CLASS,
+   X86_64_X87_CLASS,
+   X86_64_X87UP_CLASS,
+   X86_64_MEMORY_CLASS
+ };
+ 
+ /* Return the union class of CLASS1 and CLASS2.
+    See the x86-64 ABI for details.  */
+ 
+ static enum x86_64_reg_class
+ merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
+ {
+   /* Rule #1: If both classes are equal, this is the resulting class.  */
+   if (class1 == class2)
+     return class1;
+ 
+   /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
+      the other class.  */
+   if (class1 == X86_64_NO_CLASS)
+     return class2;
+   if (class2 == X86_64_NO_CLASS)
+     return class1;
+ 
+   /* Rule #3: If one of the classes is MEMORY, the result is MEMORY.  */
+   if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
+     return X86_64_MEMORY_CLASS;
+ 
+   /* Rule #4: If one of the classes is INTEGER, the result is INTEGER.  */
+   if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
+       || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
+     return X86_64_INTEGERSI_CLASS;
+   if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
+       || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
+     return X86_64_INTEGER_CLASS;
+ 
+   /* Rule #5: If one of the classes is X87 or X87UP class, MEMORY is used.  */
+   if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS
+       || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS)
+     return X86_64_MEMORY_CLASS;
+ 
+   /* Rule #6: Otherwise class SSE is used.  */
+   return X86_64_SSE_CLASS;
+ }
+ 
+ 
+ /* Classify the argument type.
+    CLASSES will be filled by the register class used to pass each word
+    of the operand.  The number of words is returned.  In case the parameter
+    should be passed in memory, 0 is returned. As a special case for zero
+    sized containers, classes[0] will be NO_CLASS and 1 is returned.
+ 
+    See the x86-64 PS ABI for details.
+ */
+ 
+ static int
+ classify_argument (struct type *type,
+ 		   enum x86_64_reg_class classes[MAX_CLASSES], int bit_offset)
+ {
+   int bytes = TYPE_LENGTH (type);
+   int words = (bytes + 8 - 1) / 8;
+ 
+   switch (TYPE_CODE (type))
+     {
+     case TYPE_CODE_ARRAY:
+     case TYPE_CODE_STRUCT:
+     case TYPE_CODE_UNION:
+       {
+ 	int i;
+ 	enum x86_64_reg_class subclasses[MAX_CLASSES];
+ 
+ 	/* On x86-64 we pass structures larger than 16 bytes on the stack.  */
+ 	if (bytes > 16)
+ 	  return 0;
+ 
+ 	for (i = 0; i < words; i++)
+ 	  classes[i] = X86_64_NO_CLASS;
+ 
+ 	/* Zero sized arrays or structures are NO_CLASS.  We return 0 to
+ 	   signalize memory class, so handle it as special case.  */
+ 	if (!words)
+ 	  {
+ 	    classes[0] = X86_64_NO_CLASS;
+ 	    return 1;
+ 	  }
+ 	switch (TYPE_CODE (type))
+ 	  {
+ 	  case TYPE_CODE_STRUCT:
+ 	    {
+ 	      int j;
+ 	      for (j = 0; j < type->nfields; ++j)
+ 		{
+ 		  int num = classify_argument (type->fields[j].type,
+ 					       subclasses,
+ 					       (type->fields[j].loc.bitpos
+ 						+ bit_offset) % 256);
+ 		  if (!num)
+ 		    return 0;
+ 		  for (i = 0; i < num; i++)
+ 		    {
+ 		      int pos =
+ 			(type->fields[j].loc.bitpos + bit_offset) / 8 / 8;
+ 		      classes[i + pos] =
+ 			merge_classes (subclasses[i], classes[i + pos]);
+ 		    }
+ 		}
+ 	    }
+ 	    break;
+ 	  case TYPE_CODE_ARRAY:
+ 	    {
+ 	      int num;
+ 
+ 	      num = classify_argument (type->target_type,
+ 				       subclasses, bit_offset);
+ 	      if (!num)
+ 		return 0;
+ 
+ 	      /* The partial classes are now full classes.  */
+ 	      if (subclasses[0] == X86_64_SSESF_CLASS && bytes != 4)
+ 		subclasses[0] = X86_64_SSE_CLASS;
+ 	      if (subclasses[0] == X86_64_INTEGERSI_CLASS && bytes != 4)
+ 		subclasses[0] = X86_64_INTEGER_CLASS;
+ 
+ 	      for (i = 0; i < words; i++)
+ 		classes[i] = subclasses[i % num];
+ 	    }
+ 	    break;
+ 	  case TYPE_CODE_UNION:
+ 	    {
+ 	      int j;
+ 	      {
+ 		for (j = 0; j < type->nfields; ++j)
+ 		  {
+ 		    int num;
+ 		    num = classify_argument (type->fields[j].type,
+ 					     subclasses, bit_offset);
+ 		    if (!num)
+ 		      return 0;
+ 		    for (i = 0; i < num; i++)
+ 		      classes[i] = merge_classes (subclasses[i], classes[i]);
+ 		  }
+ 	      }
+ 	    }
+ 	    break;
+ 	  }
+ 	/* Final merger cleanup.  */
+ 	for (i = 0; i < words; i++)
+ 	  {
+ 	    /* If one class is MEMORY, everything should be passed in
+ 	       memory.  */
+ 	    if (classes[i] == X86_64_MEMORY_CLASS)
+ 	      return 0;
+ 
+ 	    /* The X86_64_SSEUP_CLASS should be always preceeded by
+ 	       X86_64_SSE_CLASS.  */
+ 	    if (classes[i] == X86_64_SSEUP_CLASS
+ 		&& (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
+ 	      classes[i] = X86_64_SSE_CLASS;
+ 
+ 	    /*  X86_64_X87UP_CLASS should be preceeded by X86_64_X87_CLASS.  */
+ 	    if (classes[i] == X86_64_X87UP_CLASS
+ 		&& (i == 0 || classes[i - 1] != X86_64_X87_CLASS))
+ 	      classes[i] = X86_64_SSE_CLASS;
+ 	  }
+ 	return words;
+       }
+       break;
+     case TYPE_CODE_FLT:
+       switch (bytes)
+ 	{
+ 	case 4:
+ 	  if (!(bit_offset % 64))
+ 	    classes[0] = X86_64_SSESF_CLASS;
+ 	  else
+ 	    classes[0] = X86_64_SSE_CLASS;
+ 	  return 1;
+ 	case 8:
+ 	  classes[0] = X86_64_SSEDF_CLASS;
+ 	  return 1;
+ 	case 16:
+ 	  classes[0] = X86_64_X87_CLASS;
+ 	  classes[1] = X86_64_X87UP_CLASS;
+ 	  return 2;
+ 	}
+       break;
+     case TYPE_CODE_INT:
+     case TYPE_CODE_PTR:
+       switch (bytes)
+ 	{
+ 	case 1:
+ 	case 2:
+ 	case 4:
+ 	case 8:
+ 	  if (bytes * 8 + bit_offset <= 32)
+ 	    classes[0] = X86_64_INTEGERSI_CLASS;
+ 	  else
+ 	    classes[0] = X86_64_INTEGER_CLASS;
+ 	  return 1;
+ 	case 16:
+ 	  classes[0] = classes[1] = X86_64_INTEGER_CLASS;
+ 	  return 2;
+ 	default:
+ 	  break;
+ 	}
+     case TYPE_CODE_VOID:
+       return 0;
+     }
+   internal_error (__FILE__, __LINE__, "classify_argument: unknown argument type");
+ }
+ 
+ /* Examine the argument and return set number of register required in each
+    class.  Return 0 ifif parameter should be passed in memory.  */
+ 
+ static int
+ examine_argument (enum x86_64_reg_class classes[MAX_CLASSES],
+ 		  int n, int *int_nregs, int *sse_nregs)
+ {
+   *int_nregs = 0;
+   *sse_nregs = 0;
+   if (!n)
+     return 0;
+   for (n--; n >= 0; n--)
+     switch (classes[n])
+       {
+       case X86_64_INTEGER_CLASS:
+       case X86_64_INTEGERSI_CLASS:
+ 	(*int_nregs)++;
+ 	break;
+       case X86_64_SSE_CLASS:
+       case X86_64_SSESF_CLASS:
+       case X86_64_SSEDF_CLASS:
+ 	(*sse_nregs)++;
+ 	break;
+       case X86_64_NO_CLASS:
+       case X86_64_SSEUP_CLASS:
+       case X86_64_X87_CLASS:
+       case X86_64_X87UP_CLASS:
+ 	break;
+       case X86_64_MEMORY_CLASS:
+ 	internal_error (__FILE__, __LINE__, "examine_argument: unexpected memory class");
+       }
+   return 1;
+ }
+ 
+ #define RET_INT_REGS 2
+ #define RET_SSE_REGS 2
+ 
+ /* Check if the structure in value_type is returned in registers or in
+    memory. If this function returns 1, gdb will call STORE_STRUCT_RETURN and
+    EXTRACT_STRUCT_VALUE_ADDRESS else STORE_RETURN_VALUE and EXTRACT_RETURN_VALUE
+    will be used.  */
+ int
+ x86_64_use_struct_convention (int gcc_p, struct type *value_type)
+ {
+   enum x86_64_reg_class class[MAX_CLASSES];
+   int n = classify_argument (value_type, class, 0);
+   int needed_intregs;
+   int needed_sseregs;
+ 
+   return (!n ||
+ 	  !examine_argument (class, n, &needed_intregs, &needed_sseregs) ||
+ 	  needed_intregs > RET_INT_REGS || needed_sseregs > RET_SSE_REGS);
+ }
+ 
+ 
+ /* Extract from an array REGBUF containing the (raw) register state, a
+    function return value of TYPE, and copy that, in virtual format,
+    into VALBUF.  */
+ 
+ void
+ x86_64_extract_return_value (struct type *type, char *regbuf, char *valbuf)
+ {
+   enum x86_64_reg_class class[MAX_CLASSES];
+   int n = classify_argument (type, class, 0);
+   int needed_intregs;
+   int needed_sseregs;
+   int intreg = 0;
+   int ssereg = 0;
+   int offset = 0;
+   int ret_int_r[RET_INT_REGS] = { RAX_REGNUM, RDX_REGNUM };
+   int ret_sse_r[RET_SSE_REGS] = { XMM0_REGNUM, XMM1_REGNUM };
+ 
+   if (!n ||
+       !examine_argument (class, n, &needed_intregs, &needed_sseregs) ||
+       needed_intregs > RET_INT_REGS || needed_sseregs > RET_SSE_REGS)
+     {				/* memory class */
+       CORE_ADDR addr;
+       memcpy (&addr, regbuf, REGISTER_RAW_SIZE (RAX_REGNUM));
+       read_memory (addr, valbuf, TYPE_LENGTH (type));
+       return;
+     }
+   else
+     {
+       int i;
+       for (i = 0; i < n; i++)
+ 	{
+ 	  switch (class[i])
+ 	    {
+ 	    case X86_64_NO_CLASS:
+ 	      break;
+ 	    case X86_64_INTEGER_CLASS:
+ 	      memcpy (valbuf + offset,
+ 		      regbuf + REGISTER_BYTE (ret_int_r[(intreg + 1) / 2]),
+ 		      8);
+ 	      offset += 8;
+ 	      intreg += 2;
+ 	      break;
+ 	    case X86_64_INTEGERSI_CLASS:
+ 	      memcpy (valbuf + offset,
+ 		      regbuf + REGISTER_BYTE (ret_int_r[intreg / 2]), 4);
+ 	      offset += 8;
+ 	      intreg++;
+ 	      break;
+ 	    case X86_64_SSEDF_CLASS:
+ 	    case X86_64_SSESF_CLASS:
+ 	    case X86_64_SSE_CLASS:
+ 	      memcpy (valbuf + offset,
+ 		      regbuf + REGISTER_BYTE (ret_sse_r[(ssereg + 1) / 2]),
+ 		      8);
+ 	      offset += 8;
+ 	      ssereg += 2;
+ 	      break;
+ 	    case X86_64_SSEUP_CLASS:
+ 	      memcpy (valbuf + offset + 8,
+ 		      regbuf + REGISTER_BYTE (ret_sse_r[ssereg / 2]), 8);
+ 	      offset += 8;
+ 	      ssereg++;
+ 	      break;
+ 	    case X86_64_X87_CLASS:
+ 	      memcpy (valbuf + offset, regbuf + REGISTER_BYTE (FP0_REGNUM),
+ 		      8);
+ 	      offset += 8;
+ 	      break;
+ 	    case X86_64_X87UP_CLASS:
+ 	      memcpy (valbuf + offset,
+ 		      regbuf + REGISTER_BYTE (FP0_REGNUM) + 8, 8);
+ 	      offset += 8;
+ 	      break;
+ 	    case X86_64_MEMORY_CLASS:
+ 	    default:
+ 	      internal_error (__FILE__, __LINE__,
+ 			      "Unexpected argument class");
+ 	    }
+ 	}
+     }
+ }
+ 
+ /* Handled by unwind informations.  */
+ static void
+ x86_64_frame_init_saved_regs (struct frame_info *fi)
+ {
+ }
+ 
+ #define INT_REGS 6
+ #define SSE_REGS 16
+ 
+ /* Push onto the stack the specified value VALUE.  Pad it correctly for
+    it to be an argument to a function.  */
+ 
+ static CORE_ADDR
+ value_push (register CORE_ADDR sp, value_ptr arg)
+ {
+   register int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg));
+   register int container_len = len;
+ 
+   /* How big is the container we're going to put this value in?  */
+   if (PARM_BOUNDARY)
+     container_len = ((len + PARM_BOUNDARY / TARGET_CHAR_BIT - 1)
+ 		     & ~(PARM_BOUNDARY / TARGET_CHAR_BIT - 1));
+ 
+   sp -= container_len;
+   write_memory (sp, VALUE_CONTENTS_ALL (arg), len);
+ 
+   return sp;
+ }
+ 
+ CORE_ADDR
+ x86_64_push_arguments (int nargs, value_ptr *args, CORE_ADDR sp,
+ 		       int struct_return, CORE_ADDR struct_addr)
+ {
+   int intreg = 0;
+   int ssereg = 0;
+   int i;
+   static int int_parameter_registers[INT_REGS] = {5 /*RDI*/, 4 /*RSI*/,
+ 						  1 /*RDX*/, 2 /*RCX*/,
+ 						  8 /*R8 */, 9 /*R9 */};
+   /* XMM0 - XMM15  */
+   static int sse_parameter_registers[SSE_REGS] = {34, 35, 36, 37,
+ 						  38, 39, 40, 41,
+ 						  42, 43, 44, 45,
+ 						  46, 47, 48, 49};
+   for (i = 0; i < nargs; i++)
+     {
+       enum x86_64_reg_class class[MAX_CLASSES];
+       int n = classify_argument (args[i]->type, class, 0);
+       int needed_intregs;
+       int needed_sseregs;
+ 
+       if (!n ||
+ 	  !examine_argument (class, n, &needed_intregs, &needed_sseregs)
+ 	  || intreg + needed_intregs > INT_REGS
+ 	  || ssereg + needed_sseregs > SSE_REGS)
+ 	{				/* memory class */
+ 	  sp = value_push (sp, args[i]);
+ 	}
+       else
+ 	{
+ 	  int j;
+ 	  for (j = 0; j < n; j++)
+ 	    {
+ 	      int offset = 0;
+ 	      switch (class[j])
+ 		{
+ 		case X86_64_NO_CLASS:
+ 		  break;
+ 		case X86_64_INTEGER_CLASS:
+ 		  write_register_gen (int_parameter_registers[(intreg + 1) / 2],
+ 				      VALUE_CONTENTS_ALL (args[i]) + offset);
+ 		  offset += 8;
+ 		  intreg += 2;
+ 		  break;
+ 		case X86_64_INTEGERSI_CLASS:
+ 		  write_register_gen (int_parameter_registers[intreg / 2],
+ 				      VALUE_CONTENTS_ALL (args[i]) + offset);
+ 		  offset += 8;
+ 		  intreg++;
+ 		  break;
+ 		case X86_64_SSEDF_CLASS:
+ 		case X86_64_SSESF_CLASS:
+ 		case X86_64_SSE_CLASS:
+ 		  write_register_gen (sse_parameter_registers[(ssereg + 1) / 2],
+ 				      VALUE_CONTENTS_ALL (args[i]) + offset);
+ 		  offset += 8;
+ 		  ssereg += 2;
+ 		  break;
+ 		case X86_64_SSEUP_CLASS:
+ 		  write_register_gen (sse_parameter_registers[ssereg / 2],
+ 				      VALUE_CONTENTS_ALL (args[i]) + offset);
+ 		  offset += 8;
+ 		  ssereg++;
+ 		  break;
+ 		case X86_64_X87_CLASS:
+ 		case X86_64_X87UP_CLASS:
+ 		case X86_64_MEMORY_CLASS:
+ 		  sp = value_push (sp, args[i]);
+ 		  break;
+ 		default:
+ 		  internal_error (__FILE__, __LINE__,
+ 				  "Unexpected argument class");
+ 		}
+ 	      intreg += intreg % 2;
+ 	      ssereg += ssereg % 2;
+ 	    }
+ 	}
+     }
+   return sp;
+ }
+ 
+ /* Write into the appropriate registers a function return value stored
+    in VALBUF of type TYPE, given in virtual format.  */
+ void
+ x86_64_store_return_value (struct type *type, char *valbuf)
+ {
+   int len = TYPE_LENGTH (type);
+ 
+   if (TYPE_CODE_FLT == TYPE_CODE (type))
+     {
+       /* Floating-point return values can be found in %st(0).  */
+       if (len == TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT
+ 	  && TARGET_LONG_DOUBLE_FORMAT == &floatformat_i387_ext)
+ 	{
+ 	  /* Copy straight over.  */
+ 	  write_register_bytes (REGISTER_BYTE (FP0_REGNUM), valbuf,
+ 				FPU_REG_RAW_SIZE);
+ 	}
+       else
+ 	{
+ 	  char buf[FPU_REG_RAW_SIZE];
+ 	  DOUBLEST val;
+ 
+ 	  /* Convert the value found in VALBUF to the extended
+ 	     floating point format used by the FPU.  This is probably
+ 	     not exactly how it would happen on the target itself, but
+ 	     it is the best we can do.  */
+ 	  val = extract_floating (valbuf, TYPE_LENGTH (type));
+ 	  floatformat_from_doublest (&floatformat_i387_ext, &val, buf);
+ 	  write_register_bytes (REGISTER_BYTE (FP0_REGNUM), buf,
+ 				FPU_REG_RAW_SIZE);
+ 	}
+     }
+   else
+     {
+       int low_size = REGISTER_RAW_SIZE (0);
+       int high_size = REGISTER_RAW_SIZE (1);
+ 
+       if (len <= low_size)
+ 	write_register_bytes (REGISTER_BYTE (0), valbuf, len);
+       else if (len <= (low_size + high_size))
+ 	{
+ 	  write_register_bytes (REGISTER_BYTE (0), valbuf, low_size);
+ 	  write_register_bytes (REGISTER_BYTE (1),
+ 				valbuf + low_size, len - low_size);
+ 	}
+       else
+ 	internal_error (__FILE__, __LINE__,
+ 			"Cannot store return value of %d bytes long.", len);
+     }
+ }
+ 
+ 
+ static char *
+ x86_64_register_name (int reg_nr)
+ {
+   static char *register_names[] = {
+     "rax", "rdx", "rcx", "rbx",
+     "rsi", "rdi", "rbp", "rsp",
+     "r8", "r9", "r10", "r11",
+     "r12", "r13", "r14", "r15",
+     "rip", "eflags",
+     "st0", "st1", "st2", "st3",
+     "st4", "st5", "st6", "st7",
+     "fctrl", "fstat", "ftag", "fiseg",
+     "fioff", "foseg", "fooff", "fop",
+     "xmm0", "xmm1", "xmm2", "xmm3",
+     "xmm4", "xmm5", "xmm6", "xmm7",
+     "xmm8", "xmm9", "xmm10", "xmm11",
+     "xmm12", "xmm13", "xmm14", "xmm15",
+     "mxcsr"
+   };
+   if (reg_nr < 0)
+     return NULL;
+   if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
+     return NULL;
+   return register_names[reg_nr];
+ }
+ 
+ 
+ 
+ /* We have two flavours of disassembly.  The machinery on this page
+    deals with switching between those.  */
+ 
+ static int
+ gdb_print_insn_x86_64 (bfd_vma memaddr, disassemble_info * info)
+ {
+   if (disassembly_flavour == att_flavour)
+     return print_insn_i386_att (memaddr, info);
+   else if (disassembly_flavour == intel_flavour)
+     return print_insn_i386_intel (memaddr, info);
+   /* Never reached -- disassembly_flavour is always either att_flavour
+      or intel_flavour.  */
+   internal_error (__FILE__, __LINE__, "failed internal consistency check");
+ }
+ 
+ 
+ /* Store the address of the place in which to copy the structure the
+    subroutine will return.  This is called from call_function. */
+ void
+ x86_64_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+ {
+   write_register (RDI_REGNUM, addr);
+ }
+ 
+ int
+ x86_64_frameless_function_invocation (struct frame_info *frame)
+ {
+   return 0;
+ }
+ 
+ /* On x86_64 there are no reasonable prologs.  */
+ CORE_ADDR
+ x86_64_skip_prologue (CORE_ADDR pc)
+ {
+   return pc;
+ }
+ 
+ /* Sequence of bytes for breakpoint instruction.  */
+ static unsigned char *
+ x86_64_breakpoint_from_pc (CORE_ADDR *pc, int *lenptr)
+ {
+   static unsigned char breakpoint[] = { 0xcc };
+   *lenptr = 1;
+   return breakpoint;
+ }
+ 
+ static struct gdbarch *
+ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ {
+   struct gdbarch *gdbarch;
+   struct gdbarch_tdep *tdep;
+ 
+   /* Find a candidate among the list of pre-declared architectures. */
+   for (arches = gdbarch_list_lookup_by_info (arches, &info);
+        arches != NULL;
+        arches = gdbarch_list_lookup_by_info (arches->next, &info))
+     {
+       switch (info.bfd_arch_info->mach)
+ 	{
+ 	case bfd_mach_x86_64:
+ 	case bfd_mach_x86_64_intel_syntax:
+ 	  switch (gdbarch_bfd_arch_info (arches->gdbarch)->mach)
+ 	    {
+ 	    case bfd_mach_x86_64:
+ 	    case bfd_mach_x86_64_intel_syntax:
+ 	      return arches->gdbarch;
+ 	    case bfd_mach_i386_i386:
+ 	    case bfd_mach_i386_i8086:
+ 	    case bfd_mach_i386_i386_intel_syntax:
+ 	      break;
+ 	    default:
+ 	      internal_error (__FILE__, __LINE__,
+ 			      "i386_gdbarch_init: unknown machine type");
+ 	    }
+ 	  break;
+ 	case bfd_mach_i386_i386:
+ 	case bfd_mach_i386_i8086:
+ 	case bfd_mach_i386_i386_intel_syntax:
+ 	  switch (gdbarch_bfd_arch_info (arches->gdbarch)->mach)
+ 	    {
+ 	    case bfd_mach_x86_64:
+ 	    case bfd_mach_x86_64_intel_syntax:
+ 	      break;
+ 	    case bfd_mach_i386_i386:
+ 	    case bfd_mach_i386_i8086:
+ 	    case bfd_mach_i386_i386_intel_syntax:
+ 	      return arches->gdbarch;
+ 	    default:
+ 	      internal_error (__FILE__, __LINE__,
+ 			      "i386_gdbarch_init: unknown machine type");
+ 	    }
+ 	  break;
+ 	default:
+ 	  internal_error (__FILE__, __LINE__,
+ 			  "i386_gdbarch_init: unknown machine type");
+ 	}
+     }
+ 
+   tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
+   gdbarch = gdbarch_alloc (&info, tdep);
+ 
+   switch (info.bfd_arch_info->mach)
+     {
+     case bfd_mach_x86_64:
+     case bfd_mach_x86_64_intel_syntax:
+       tdep->last_fpu_regnum = 25;
+       tdep->first_xmm_regnum = 34;
+       tdep->last_xmm_regnum = 49;
+       tdep->mxcsr_regnum = 50;
+       tdep->first_fpu_ctrl_regnum = 26;
+       break;
+     case bfd_mach_i386_i386:
+     case bfd_mach_i386_i8086:
+     case bfd_mach_i386_i386_intel_syntax:
+       /* This is place for definition of i386 target vector.  */
+       break;
+     default:
+       internal_error (__FILE__, __LINE__,
+ 		      "i386_gdbarch_init: unknown machine type");
+     }
+ 
+   set_gdbarch_long_bit (gdbarch, 64);
+   set_gdbarch_long_long_bit (gdbarch, 64);
+   set_gdbarch_ptr_bit (gdbarch, 64);
+ 
+   set_gdbarch_long_double_format (gdbarch, &floatformat_i387_ext);
+   set_gdbarch_ieee_float (gdbarch, 1);
+ 
+ 
+   set_gdbarch_num_regs (gdbarch, X86_64_NUM_REGS);
+   set_gdbarch_register_name (gdbarch, x86_64_register_name);
+   set_gdbarch_register_size (gdbarch, 8);
+   set_gdbarch_register_raw_size (gdbarch, x86_64_register_raw_size);
+   set_gdbarch_max_register_raw_size (gdbarch, 16);
+   set_gdbarch_register_byte (gdbarch, x86_64_register_byte);
+   /* Total amount of space needed to store our copies of the machine's register
+      (SIZEOF_GREGS + SIZEOF_FPU_REGS + SIZEOF_FPU_CTRL_REGS + SIZEOF_SSE_REGS) */
+   set_gdbarch_register_bytes (gdbarch,
+ 			      (18 * 8) + (8 * 10) + (8 * 4) + (8 * 16 + 4));
+   set_gdbarch_register_virtual_size (gdbarch, x86_64_register_virtual_size);
+   set_gdbarch_max_register_virtual_size (gdbarch, 16);
+ 
+   set_gdbarch_register_virtual_type (gdbarch, x86_64_register_virtual_type);
+ 
+   set_gdbarch_register_convertible (gdbarch, x86_64_register_convertible);
+   set_gdbarch_register_convert_to_virtual (gdbarch,
+ 					   x86_64_register_convert_to_virtual);
+   set_gdbarch_register_convert_to_raw (gdbarch,
+ 				       x86_64_register_convert_to_raw);
+ 
+ /* Register numbers of various important registers.  */
+   set_gdbarch_sp_regnum (gdbarch, 7);	/* (rsp) Contains address of top of stack.  */
+   set_gdbarch_fp_regnum (gdbarch, 6);	/* (rbp) */
+   set_gdbarch_pc_regnum (gdbarch, 16);	/* (rip) Contains program counter.  */
+ 
+   set_gdbarch_fp0_regnum (gdbarch, 18);	/* First FPU floating-point register.  */
+ 
+   set_gdbarch_read_fp (gdbarch, cfi_read_fp);
+   set_gdbarch_write_fp (gdbarch, cfi_write_fp);
+ 
+ /* Discard from the stack the innermost frame, restoring all registers.  */
+   set_gdbarch_pop_frame (gdbarch, x86_64_pop_frame);
+ 
+   /* FRAME_CHAIN takes a frame's nominal address and produces the frame's
+      chain-pointer.  */
+   set_gdbarch_frame_chain (gdbarch, cfi_frame_chain);
+ 
+   set_gdbarch_frameless_function_invocation (gdbarch,
+ 					     x86_64_frameless_function_invocation);
+   set_gdbarch_frame_saved_pc (gdbarch, x86_64_linux_frame_saved_pc);
+ 
+   set_gdbarch_frame_args_address (gdbarch, default_frame_address);
+   set_gdbarch_frame_locals_address (gdbarch, default_frame_address);
+ 
+ /* Return number of bytes at start of arglist that are not really args.  */
+   set_gdbarch_frame_args_skip (gdbarch, 8);
+ 
+   set_gdbarch_frame_init_saved_regs (gdbarch, x86_64_frame_init_saved_regs);
+ 
+ /* Frame pc initialization is handled by unwind informations.  */
+   set_gdbarch_init_frame_pc (gdbarch, cfi_init_frame_pc);
+ 
+ /* Initialization of unwind informations.  */
+   set_gdbarch_init_extra_frame_info (gdbarch, cfi_init_extra_frame_info);
+ 
+ /* Getting saved registers is handled by unwind informations.  */
+   set_gdbarch_get_saved_register (gdbarch, cfi_get_saved_register);
+ 
+   set_gdbarch_frame_init_saved_regs (gdbarch, x86_64_frame_init_saved_regs);
+ 
+ /* Cons up virtual frame pointer for trace */
+   set_gdbarch_virtual_frame_pointer (gdbarch, cfi_virtual_frame_pointer);
+ 
+ 
+   set_gdbarch_frame_chain_valid (gdbarch, generic_file_frame_chain_valid);
+ 
+   set_gdbarch_use_generic_dummy_frames (gdbarch, 1);
+   set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
+   set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
+   set_gdbarch_call_dummy_length (gdbarch, 0);
+   set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
+   set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
+   set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
+   set_gdbarch_call_dummy_words (gdbarch, 0);
+   set_gdbarch_sizeof_call_dummy_words (gdbarch, 0);
+   set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+   set_gdbarch_call_dummy_p (gdbarch, 1);
+   set_gdbarch_call_dummy_start_offset (gdbarch, 0);
+   set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
+   set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
+   set_gdbarch_push_return_address (gdbarch, x86_64_push_return_address);
+   set_gdbarch_push_arguments (gdbarch, x86_64_push_arguments);
+ 
+ /* Return number of args passed to a frame, no way to tell.  */
+   set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
+ /* Don't use default structure extract routine */
+   set_gdbarch_extract_struct_value_address (gdbarch, 0);
+ 
+ /* If USE_STRUCT_CONVENTION retruns 0, then gdb uses STORE_RETURN_VALUE
+    and EXTRACT_RETURN_VALUE to store/fetch the functions return value.  It is
+    the case when structure is returned in registers.  */
+   set_gdbarch_use_struct_convention (gdbarch, x86_64_use_struct_convention);
+ 
+ /* Store the address of the place in which to copy the structure the
+    subroutine will return.  This is called from call_function. */
+   set_gdbarch_store_struct_return (gdbarch, x86_64_store_struct_return);
+ 
+ /* Extract from an array REGBUF containing the (raw) register state
+    a function return value of type TYPE, and copy that, in virtual format,
+    into VALBUF.  */
+   set_gdbarch_extract_return_value (gdbarch, x86_64_extract_return_value);
+ 
+ 
+ /* Write into the appropriate registers a function return value stored
+    in VALBUF of type TYPE, given in virtual format.  */
+   set_gdbarch_store_return_value (gdbarch, x86_64_store_return_value);
+ 
+ 
+ /* Offset from address of function to start of its code.  */
+   set_gdbarch_function_start_offset (gdbarch, 0);
+ 
+   set_gdbarch_skip_prologue (gdbarch, x86_64_skip_prologue);
+ 
+   set_gdbarch_saved_pc_after_call (gdbarch, x86_64_linux_saved_pc_after_call);
+ 
+   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ 
+   set_gdbarch_breakpoint_from_pc (gdbarch, x86_64_breakpoint_from_pc);
+ 
+ 
+ /* Amount PC must be decremented by after a breakpoint.  This is often the
+    number of bytes in BREAKPOINT but not always.  */
+   set_gdbarch_decr_pc_after_break (gdbarch, 1);
+ 
+   return gdbarch;
+ }
+ 
+ void
+ _initialize_x86_64_tdep (void)
+ {
+   register_gdbarch_init (bfd_arch_i386, i386_gdbarch_init);
+ 
+   /* Initialize the table saying where each register starts in the
+      register file.  */
+   {
+     int i, offset;
+ 
+     offset = 0;
+     for (i = 0; i < X86_64_NUM_REGS; i++)
+       {
+ 	x86_64_register_byte_table[i] = offset;
+ 	offset += x86_64_register_raw_size_table[i];
+       }
+   }
+ 
+   tm_print_insn = gdb_print_insn_x86_64;
+   tm_print_insn_info.mach = bfd_lookup_arch (bfd_arch_i386, 3)->mach;
+ 
+   /* Add the variable that controls the disassembly flavour.  */
+   {
+     struct cmd_list_element *new_cmd;
+ 
+     new_cmd = add_set_enum_cmd ("disassembly-flavour", no_class,
+ 				valid_flavours, &disassembly_flavour, "\
+ Set the disassembly flavour, the valid values are \"att\" and \"intel\", \
+ and the default value is \"att\".", &setlist);
+     add_show_from_set (new_cmd, &showlist);
+   }
+ }
Index: x86-64-tdep.h
===================================================================
RCS file: x86-64-tdep.h
diff -N x86-64-tdep.h
*** /dev/null	Tue May  5 13:32:27 1998
--- x86-64-tdep.h	Tue Sep 18 04:24:42 2001
***************
*** 0 ****
--- 1,49 ----
+ /* Target-dependent code for GDB, the GNU debugger.
+    Copyright 2001
+    Free Software Foundation, Inc.
+    Contributed by Jiri Smid, SuSE Labs.
+ 
+    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.  */
+ 
+ #ifndef X86_64_TDEP_H
+ #define X86_64_TDEP_H
+ 
+ #include "i386-tdep.h"
+ #include <sys/reg.h>
+ 
+ /* Mapping between the general-purpose registers in `struct user'
+    format and GDB's register array layout.  */
+ 
+ static int x86_64_regmap[] = {
+   RAX, RDX, RCX, RBX,
+   RSI, RDI, RBP, RSP,
+   R8, R9, R10, R11,
+   R12, R13, R14, R15,
+   RIP, EFLAGS
+ };
+ 
+ /* Number of all registers */
+ #define X86_64_NUM_REGS (51)
+ 
+ /* Number of general registers.  */
+ #define X86_64_NUM_GREGS (18)
+ 
+ gdbarch_frame_saved_pc_ftype x86_64_linux_frame_saved_pc;
+ gdbarch_saved_pc_after_call_ftype x86_64_linux_saved_pc_after_call;
+ 
+ #endif
Index: config/djgpp/fnchange.lst
===================================================================
RCS file: /cvs/src/src/gdb/config/djgpp/fnchange.lst,v
retrieving revision 1.19
diff -c -3 -p -r1.19 fnchange.lst
*** fnchange.lst	2001/08/24 05:00:06	1.19
--- fnchange.lst	2001/09/18 11:24:42
***************
*** 202,207 ****
--- 202,209 ----
  @V@/gdb/testsuite/gdb.mi/mi0-var-display.exp @V@/gdb/testsuite/gdb.mi/mi0vardisplay.exp
  @V@/gdb/tui/tuiSourceWin.c @V@/gdb/tui/tuiWinSource.c
  @V@/gdb/tui/tuiSourceWin.h @V@/gdb/tui/tuiWinSource.h
+ @V@/gdb/x86-64-linux-tdep.c @V@/gdb/x8664-ltdep.c
+ @V@/gdb/x86-64-linux-nat.c @V@/gdb/x8664-lnat.c
  @V@/intl/intlh.inst.in @V@/intl/intlh_inst.in
  @V@/intl/po2tbl.sed.in @V@/intl/po2tblsed.in
  @V@/itcl/itcl/itclConfig.sh.in @V@/itcl/itcl/itclConfig.sh-in
Index: config/i386/nm-x86-64.h
===================================================================
RCS file: nm-x86-64.h
diff -N nm-x86-64.h
*** /dev/null	Tue May  5 13:32:27 1998
--- nm-x86-64.h	Tue Sep 18 04:24:42 2001
***************
*** 0 ****
--- 1,102 ----
+ /* Native support for Linux/x86-64.
+    Copyright 2001
+    Free Software Foundation, Inc.
+    Contributed by Jiri Smid, SuSE Labs.
+ 
+    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.  */
+ 
+ #ifndef NM_X86_64_H
+ #define NM_X86_64_H
+ 
+ #include "nm-linux.h"
+ 
+ #define I386_USE_GENERIC_WATCHPOINTS
+ #include "i386/nm-i386.h"
+ 
+ /* Support for 8-byte wide hw watchpoints.  */
+ #define TARGET_HAS_DR_LEN_8 1
+ 
+ /* Provide access to the i386 hardware debugging registers.  */
+ 
+ extern void x86_64_linux_dr_set_control (unsigned long control);
+ #define I386_DR_LOW_SET_CONTROL(control) \
+   x86_64_linux_dr_set_control (control)
+ 
+ extern void x86_64_linux_dr_set_addr (int regnum, CORE_ADDR addr);
+ #define I386_DR_LOW_SET_ADDR(regnum, addr) \
+   x86_64_linux_dr_set_addr (regnum, addr)
+ 
+ extern void x86_64_linux_dr_reset_addr (int regnum);
+ #define I386_DR_LOW_RESET_ADDR(regnum) \
+   x86_64_linux_dr_reset_addr (regnum)
+ 
+ extern unsigned long x86_64_linux_dr_get_status (void);
+ #define I386_DR_LOW_GET_STATUS() \
+   x86_64_linux_dr_get_status ()
+ 
+ 
+ #define REGISTER_U_ADDR(addr, blockend, regno) \
+ 	(addr) = x86_64_register_u_addr ((blockend),(regno));
+ CORE_ADDR x86_64_register_u_addr (CORE_ADDR, int);
+ 
+ /* Return the size of the user struct.  */
+ #define KERNEL_U_SIZE kernel_u_size()
+ extern int kernel_u_size (void);
+ 
+ /* Offset of the registers within the user area.  */
+ #define U_REGS_OFFSET 0
+ 
+ /* This is the amount to subtract from u.u_ar0
+    to get the offset in the core file of the register values.  */
+ #define KERNEL_U_ADDR 0x0
+ 
+ /* FIXME use special child_xfer_memory.  */
+ #define CHILD_XFER_MEMORY
+ 
+ #define PTRACE_ARG3_TYPE void*
+ 
+ 
+ /* We define this if link.h is available, because with ELF we use SVR4 style
+    shared libraries. */
+ 
+ #ifdef HAVE_LINK_H
+ #define SVR4_SHARED_LIBS
+ #include "solib.h"		/* Support for shared libraries. */
+ #endif
+ 
+ /* Override copies of {fetch,store}_inferior_registers in `infptrace.c'.  */
+ #define FETCH_INFERIOR_REGISTERS
+ 
+ /* Override child_resume in `infptrace.c'.  */
+ #define CHILD_RESUME
+ 
+ // extern int lin_lwp_prepare_to_proceed (void);
+ #undef PREPARE_TO_PROCEED
+ // #define PREPARE_TO_PROCEED(select_it) lin_lwp_prepare_to_proceed ()
+ 
+ extern void lin_lwp_attach_lwp (ptid_t pid, int verbose);
+ #define ATTACH_LWP(pid, verbose) lin_lwp_attach_lwp ((pid), (verbose))
+ 
+ #include <signal.h>
+ 
+ extern void lin_thread_get_thread_signals (sigset_t * mask);
+ #define GET_THREAD_SIGNALS(mask) lin_thread_get_thread_signals (mask)
+ 
+ #endif /* NM_X86_64.h */
+ 
+ 
Index: config/i386/x86-64linux.mh
===================================================================
RCS file: x86-64linux.mh
diff -N x86-64linux.mh
*** /dev/null	Tue May  5 13:32:27 1998
--- x86-64linux.mh	Tue Sep 18 04:24:42 2001
***************
*** 0 ****
--- 1,11 ----
+ # Host: AMD x86-64 running GNU/Linux
+ 
+ XM_FILE= xm-i386.h
+ XDEPFILES=
+ 
+ NAT_FILE= nm-x86-64.h
+ NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \
+ 	core-aout.o i386-nat.o x86-64-nat.o x86-64-linux-nat.o \
+ 	i387-nat.o proc-service.o thread-db.o lin-lwp.o
+ 
+ LOADLIBES = -ldl -rdynamic
Index: config/i386/x86-64linux.mt
===================================================================
RCS file: x86-64linux.mt
diff -N x86-64linux.mt
*** /dev/null	Tue May  5 13:32:27 1998
--- x86-64linux.mt	Tue Sep 18 04:24:42 2001
***************
*** 0 ****
--- 1,5 ----
+ # Target: AMD x86-64 running GNU/Linux
+ TDEPFILES= x86-64-tdep.o x86-64-linux-tdep.o i387-tdep.o dwarf2cfi.o \
+ 	solib.o solib-svr4.o solib-legacy.o
+ 
+ GDBSERVER_DEPFILES= low-linux.o

-- 
Jiri Smid

---------------------------------------------------------------------
SuSE CR, s.r.o.                                 e-mail: smid@suse.cz
Drahobejlova 27                                tel:+420 2 83095 373
190 00 Praha 9                                 fax:+420 2 83095 374
Ceska republika                                http://www.suse.cz


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]