Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFA]: x86_64 target
@ 2001-09-18  4:54 Jiri Smid
  2001-09-18  7:11 ` Eli Zaretskii
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Jiri Smid @ 2001-09-18  4:54 UTC (permalink / raw)
  To: gdb-patches

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);
+ }
+ \f
+ 
+ /* 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
+ \f
+ 
+ /* 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");
+ }
+ \f
+ 
+ /* 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");
+ }
+ \f
+ 
+ /* 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);
+ }
+ \f
+ 
+ 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");
+ }
+ \f
+ 
+ /* 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 */
+ };
+ \f
+ 
+ #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]);
+ }
+ \f
+ 
+ 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);
+ }
+ \f
+ 
+ /* 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);
+ }
+ \f
+ 
+ /* 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);
+     }
+ }
+ \f
+ 
+ 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];
+ }
+ \f
+ 
+ 
+ /* 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");
+ }
+ \f
+ 
+ /* 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);
+ \f
+ 
+ /* 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 ()
+ \f
+ 
+ #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*
+ \f
+ 
+ /* 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


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFA]: x86_64 target
  2001-09-18  4:54 [RFA]: x86_64 target Jiri Smid
@ 2001-09-18  7:11 ` Eli Zaretskii
  2001-09-19  7:42 ` Mark Kettenis
  2001-09-19 10:17 ` Andreas Jaeger
  2 siblings, 0 replies; 5+ messages in thread
From: Eli Zaretskii @ 2001-09-18  7:11 UTC (permalink / raw)
  To: smid; +Cc: gdb-patches

> From: Jiri Smid <smid@suse.cz>
> Date: 18 Sep 2001 13:54:47 +0200
> 
>   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)

I think i386-nat.c is Mark Kettenis's responsibility, so he should
approve the patches to that file.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFA]: x86_64 target
  2001-09-18  4:54 [RFA]: x86_64 target Jiri Smid
  2001-09-18  7:11 ` Eli Zaretskii
@ 2001-09-19  7:42 ` Mark Kettenis
  2001-09-19 11:51   ` Andrew Cagney
  2001-09-19 10:17 ` Andreas Jaeger
  2 siblings, 1 reply; 5+ messages in thread
From: Mark Kettenis @ 2001-09-19  7:42 UTC (permalink / raw)
  To: Jiri Smid; +Cc: gdb-patches, ac131313

Hi Jiri,

You're not listed under Write After Approval in the MAINTAINERS file
yet.  Andrew, is Jiri's paperwork in order?  If it is then:

The i386-nat.c changes are approved.

There are some comments in x86-64-linux-nat.c that you took from
i386-linux-nat.c, but that don't really apply in your case:

 - The comment that starts with:

   /* The register sets used in Linux ELF core-dumps...

   Replacing it with

   /* The register sets used in Linux ELF core-dumps are identical to the
      register sets used by `ptrace'.  */

   should be enough.

 - The comment that talks about PTRACE_SETFPXREGS doesn't make sense
   for x86_64.  Just leave it out.

Is the stuff in x86-64-nat.c really necessary?

Please remove the extra whitespace at the end of nm-x86-64.h.

Please do not apply the patches to NEWS and configure.host and
configure.tgt until all the other stuff is checked in.

With those changes, the rest if this stuff also approved.  I'll
probably start working on multi-arching some of the i386 targets once
you've checked this in.  In that process I'll probably want to touch
i386-tdep.h and x86_64-tdep.c, so we should work out how to ccoperate
without hindering eachother too much on those bits.

Cheers,

Mark


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFA]: x86_64 target
  2001-09-18  4:54 [RFA]: x86_64 target Jiri Smid
  2001-09-18  7:11 ` Eli Zaretskii
  2001-09-19  7:42 ` Mark Kettenis
@ 2001-09-19 10:17 ` Andreas Jaeger
  2 siblings, 0 replies; 5+ messages in thread
From: Andreas Jaeger @ 2001-09-19 10:17 UTC (permalink / raw)
  To: Jiri Smid; +Cc: gdb-patches

Jiri,

can you name those files x86-64linux etc instead of x86_64?  x86-64 is
the official name of the architecture.

Thanks,
Andreas

	* 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.

-- 
 Andreas Jaeger
  SuSE Labs aj@suse.de
   private aj@arthur.inka.de
    http://www.suse.de/~aj


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFA]: x86_64 target
  2001-09-19  7:42 ` Mark Kettenis
@ 2001-09-19 11:51   ` Andrew Cagney
  0 siblings, 0 replies; 5+ messages in thread
From: Andrew Cagney @ 2001-09-19 11:51 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: Jiri Smid, gdb-patches, ac131313

> You're not listed under Write After Approval in the MAINTAINERS file
> yet.  Andrew, is Jiri's paperwork in order?  If it is then:


Yes it is all in order.  I think Jiri's just been too busy sorting out 
x86-64 to action the ``add to maintainers file'' task.

enjoy,
Andrew



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2001-09-19 11:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-09-18  4:54 [RFA]: x86_64 target Jiri Smid
2001-09-18  7:11 ` Eli Zaretskii
2001-09-19  7:42 ` Mark Kettenis
2001-09-19 11:51   ` Andrew Cagney
2001-09-19 10:17 ` Andreas Jaeger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox