Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFA]: x86_64 target files
@ 2001-08-02  7:20 Jiri Smid
  2001-08-02  8:39 ` Eli Zaretskii
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: Jiri Smid @ 2001-08-02  7:20 UTC (permalink / raw)
  To: gdb-patches

Hello,

This is the related new files for x86-64 target.

Index: ChangeLog
from  Jiri Smid <smid@suse.cz>

	* configure.host: Recognize x86_64-*-linux*.
	* configure.tgt: Likewise.
	* config/i386/x86_64.mh: New file.
	* config/i386/x86_64.mt: New file.
	* config/i386/nm-x86_64.h: New file.
	* config/i386/tm-x86_64.h: New file.
	* config/i386/xm-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.

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/08/02 07:38:37
*************** 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_64 ;;
  
  esac
Index: configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.34
diff -c -3 -p -r1.34 configure.tgt
*** configure.tgt	2001/07/19 05:10:38	1.34
--- configure.tgt	2001/08/02 07:38:37
*************** 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
*** 312,317 ****
--- 313,321 ----
  			;;
  
  # OBSOLETE w65-*-*)		gdb_target=w65 ;;
+ 
+ x86_64-*-linux*)	gdb_target=x86_64
+  		configdirs="${configdirs} gdbserver" ;;
  
  z8k-*-coff*)		gdb_target=z8k ;;
  
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	Thu Aug  2 00:38:40 2001
***************
*** 0 ****
--- 1,739 ----
+ /* Native-dependent code for Linux/x86-64.
+    Copyright 1999, 2000, 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.  */
+ 
+ #include "defs.h"
+ #include "inferior.h"
+ #include "gdbcore.h"
+ #include "regcache.h"
+ 
+ #include <asm/unistd.h>
+ #include <sys/ptrace.h>
+ #include <sys/user.h>
+ #include <sys/procfs.h>
+ 
+ #ifdef HAVE_SYS_REG_H
+ #include <sys/reg.h>
+ #endif
+ 
+ /* Prototypes for supply_gregset etc.  */
+ #include "gregset.h"
+ 
+ /* Prototypes for i387_supply_fsave etc.  */
+ #include "i387-nat.h"
+ \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.  */
+ 
+ /* Mapping between the general-purpose registers in `struct user'
+    format and GDB's register array layout.  */
+ 
+ static int regmap[] =
+ {
+   RAX, RDX, RCX, RBX,
+   RSI, RDI, RBP, RSP,
+   R8, R9, R10, R11,
+   R12, R13, R14, R15,
+   RIP, EFLAGS
+ };
+ 
+ /* 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)
+ 
+ /* Does the current host support the GETREGS request?  */
+ int have_ptrace_getregs =
+ #ifdef HAVE_PTRACE_GETREGS
+   1
+ #else
+   0
+ #endif
+ ;
+ 
+ \f
+ 
+ /* Fetching registers directly from the U area, one at a time.  */
+ 
+ /* FIXME: kettenis/2000-03-05: This duplicates code from `inptrace.c'.
+    The problem is that we define FETCH_INFERIOR_REGISTERS since we
+    want to use our own versions of {fetch,store}_inferior_registers
+    that use the GETREGS request.  This means that the code in
+    `infptrace.c' is #ifdef'd out.  But we need to fall back on that
+    code when GDB is running on top of a kernel that doesn't support
+    the GETREGS request.  I want to avoid changing `infptrace.c' right
+    now.  */
+ 
+ #ifndef PT_READ_U
+ #define PT_READ_U PTRACE_PEEKUSR
+ #endif
+ #ifndef PT_WRITE_U
+ #define PT_WRITE_U PTRACE_POKEUSR
+ #endif
+ 
+ /* Default the type of the ptrace transfer to int.  */
+ #ifndef PTRACE_XFER_TYPE
+ #define PTRACE_XFER_TYPE unsigned long
+ #endif
+ 
+ /* Registers we shouldn't try to fetch.  */
+ #define OLD_CANNOT_FETCH_REGISTER(regno) ((regno) >= NUM_GREGS)
+ 
+ /* Fetch one register.  */
+ 
+ static void
+ fetch_register (int regno)
+ {
+   /* This isn't really an address.  But ptrace thinks of it as one.  */
+   CORE_ADDR regaddr;
+   char mess[128];		/* For messages */
+   register int i;
+   unsigned int offset;		/* Offset of registers within the u area.  */
+   char buf[MAX_REGISTER_RAW_SIZE];
+   int tid;
+ 
+   if (OLD_CANNOT_FETCH_REGISTER (regno))
+     {
+       memset (buf, '\0', REGISTER_RAW_SIZE (regno));	/* Supply zeroes */
+       supply_register (regno, buf);
+       return;
+     }
+ 
+   /* Overload thread id onto process id */
+   if ((tid = TIDGET (inferior_ptid)) == 0)
+     tid = PIDGET (inferior_ptid);		/* no thread id, just use process id */
+ 
+   offset = U_REGS_OFFSET;
+ 
+   regaddr = register_addr (regno, offset);
+   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+     {
+       errno = 0;
+       ptrace (PT_READ_U, tid, (PTRACE_ARG3_TYPE) regaddr, ((PTRACE_XFER_TYPE *) buf) + i );
+       regaddr += sizeof (PTRACE_XFER_TYPE);
+       if (errno != 0)
+ 	{
+ 	  sprintf (mess, "reading register %s (#%d)",
+ 		   REGISTER_NAME (regno), regno);
+ 	  perror_with_name (mess);
+ 	}
+     }
+   supply_register (regno, buf);
+ }
+ 
+ /* Fetch register values from the inferior.
+    If REGNO is negative, do this for all registers.
+    Otherwise, REGNO specifies which register (so we can save time). */
+ 
+ void
+ old_fetch_inferior_registers (int regno)
+ {
+  if (regno >= 0)
+     {
+       fetch_register (regno);
+     }
+   else
+     {
+       for (regno = 0; regno < NUM_REGS; regno++)
+ 	{
+ 	  fetch_register (regno);
+ 	}
+     }
+ }
+ 
+ /* Registers we shouldn't try to store.  */
+ #define OLD_CANNOT_STORE_REGISTER(regno) ((regno) >= NUM_GREGS)
+ 
+ /* Store one register. */
+ 
+ static void
+ store_register (int regno)
+ {
+   /* This isn't really an address.  But ptrace thinks of it as one.  */
+   CORE_ADDR regaddr;
+   char mess[128];		/* For messages */
+   register int i;
+   unsigned int offset;		/* Offset of registers within the u area.  */
+   int tid;
+ 
+   if (OLD_CANNOT_STORE_REGISTER (regno))
+     {
+       return;
+     }
+ 
+   /* Overload thread id onto process id */
+   if ((tid = TIDGET (inferior_ptid)) == 0)
+     tid = PIDGET (inferior_ptid);		/* no thread id, just use process id */
+ 
+   offset = U_REGS_OFFSET;
+ 
+   regaddr = register_addr (regno, offset);
+   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+     {
+       errno = 0;
+       ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
+ 	      *(PTRACE_XFER_TYPE *) & registers[REGISTER_BYTE (regno) + i]);
+       regaddr += sizeof (PTRACE_XFER_TYPE);
+       if (errno != 0)
+ 	{
+ 	  sprintf (mess, "writing register %s (#%d)",
+ 		   REGISTER_NAME (regno), regno);
+ 	  perror_with_name (mess);
+ 	}
+     }
+ }
+ 
+ /* Store our register values back into the inferior.
+    If REGNO is negative, do this for all registers.
+    Otherwise, REGNO specifies which register (so we can save time).  */
+ 
+ void
+ old_store_inferior_registers (int regno)
+ {
+   if (regno >= 0)
+     {
+       store_register (regno);
+     }
+   else
+     {
+       for (regno = 0; regno < NUM_REGS; regno++)
+ 	{
+ 	  store_register (regno);
+ 	}
+     }
+ }
+ \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 < NUM_GREGS; i++)
+     supply_register (i, (char *) (regp + 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 < NUM_GREGS; i++)
+     if ((regno == -1 || regno == i))
+       *(regp + regmap[i]) = *(elf_greg_t *) &registers[REGISTER_BYTE (i)];
+ }
+ 
+ #ifdef HAVE_PTRACE_GETREGS
+ 
+ /* 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)
+     {
+       if (errno == EIO)
+ 	{
+ 	  /* The kernel we're running on doesn't support the GETREGS
+ 	     request.  Reset `have_ptrace_getregs'.  */
+ 	  have_ptrace_getregs = 0;
+ 	  return;
+ 	}
+ 
+       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");
+ }
+ 
+ #else
+ 
+ static void fetch_regs (int tid) {}
+ static void store_regs (int tid, int regno) {}
+ 
+ #endif
+ \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);
+ }
+ 
+ #ifdef HAVE_PTRACE_GETREGS
+ 
+ /* 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");
+ }
+ 
+ #else
+ 
+ static void fetch_fpregs (int tid) {}
+ static void store_fpregs (int tid, int regno) {}
+ 
+ #endif
+ \f
+ 
+ /* Transferring arbitrary registers between GDB and inferior.  */
+ 
+ /* Check if register REGNO in the child process is accessible.
+    If we are accessing registers directly via the U area, only the
+    general-purpose registers are available.
+    All registers should be accessible if we have GETREGS support.  */
+ 
+ int
+ cannot_fetch_register (int regno)
+ {
+   if (! have_ptrace_getregs)
+     return OLD_CANNOT_FETCH_REGISTER (regno);
+   return 0;
+ }
+ int
+ cannot_store_register (int regno)
+ {
+   if (! have_ptrace_getregs)
+     return OLD_CANNOT_STORE_REGISTER (regno);
+   return 0;
+ }
+ 
+ /* 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;
+ 
+   /* Use the old method of peeking around in `struct user' if the
+      GETREGS request isn't available.  */
+   if (! have_ptrace_getregs)
+     {
+       old_fetch_inferior_registers (regno);
+       return;
+     }
+ 
+   /* 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);
+ 
+       /* The call above might reset `have_ptrace_getregs'.  */
+       if (! have_ptrace_getregs)
+ 	{
+ 	  old_fetch_inferior_registers (-1);
+ 	  return;
+ 	}
+ 
+       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;
+ 
+   /* Use the old method of poking around in `struct user' if the
+      SETREGS request isn't available.  */
+   if (! have_ptrace_getregs)
+     {
+       old_store_inferior_registers (regno);
+       return;
+     }
+ 
+   /* 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 */
+ };
+ 
+ void
+ _initialize_i386_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	Thu Aug  2 00:38:40 2001
***************
*** 0 ****
--- 1,298 ----
+ /* Target-dependent code for Linux running on x86-64, for GDB.
+    Copyright 2000, 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.  */
+ 
+ #include "defs.h"
+ #include "gdbcore.h"
+ #include "frame.h"
+ #include "value.h"
+ #include "regcache.h"
+ 
+ /* For x86_64_linux_skip_solib_resolver.  */
+ #include "symtab.h"
+ #include "symfile.h"
+ #include "objfiles.h"
+ 
+ #include "solib-svr4.h"		/* For struct link_map_offsets.  */
+ 
+ \f
+ /* Recognizing signal handler frames.  */
+ 
+ #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];
+ /* We only recognize a signal trampoline if PC is at the start of
+      one of the two instructions.  We optimize for finding the PC at
+      the start, as will be the case when the trampoline is not the
+      first frame on the stack.  We assume that in the case where the
+      PC is not at the start of the instruction sequence, there will be
+      a few trailing readable bytes on the stack.  */
+ 
+   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;
+ }
+ 
+ /* Return whether PC is in a Linux sigtramp routine.  */
+ 
+ int
+ x86_64_linux_in_sigtramp (CORE_ADDR pc, char *name)
+ {
+  if (name)
+     return STREQ ("__restore_rt", name);
+ 
+  return x86_64_linux_sigtramp_start (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.  */
+ 
+ /* FIXME */
+ 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);
+ }
+ 
+ /* Offset to saved SP in sigcontext, from <asm/sigcontext.h>.  */
+ #define LINUX_SIGCONTEXT_SP_OFFSET (208)
+ 
+ /* Assuming FRAME is for a Linux sigtramp routine, return the saved
+    stack pointer.  */
+ 
+ CORE_ADDR
+ x86_64_linux_sigtramp_saved_sp (struct frame_info *frame)
+ {
+   CORE_ADDR addr;
+ 
+   addr = x86_64_linux_sigcontext_addr (frame);
+   return read_memory_integer (addr + LINUX_SIGCONTEXT_SP_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);
+ }
+ 
+ \f
+ 
+ /* Calling functions in shared libraries.  */
+ /* Find the minimal symbol named NAME, and return both the minsym
+    struct and its objfile.  This probably ought to be in minsym.c, but
+    everything there is trying to deal with things like C++ and
+    SOFUN_ADDRESS_MAYBE_TURQUOISE, ...  Since this is so simple, it may
+    be considered too special-purpose for general consumption.  */
+ 
+ static struct minimal_symbol *
+ find_minsym_and_objfile (char *name, struct objfile **objfile_p)
+ {
+   struct objfile *objfile;
+ 
+   ALL_OBJFILES (objfile)
+     {
+       struct minimal_symbol *msym;
+ 
+       ALL_OBJFILE_MSYMBOLS (objfile, msym)
+ 	{
+ 	  if (SYMBOL_NAME (msym)
+ 	      && STREQ (SYMBOL_NAME (msym), name))
+ 	    {
+ 	      *objfile_p = objfile;
+ 	      return msym;
+ 	    }
+ 	}
+     }
+ 
+   return 0;
+ }
+ 
+ static CORE_ADDR
+ skip_hurd_resolver (CORE_ADDR pc)
+ {
+ /* The HURD dynamic linker is part of the GNU C library, so many
+      GNU/Linux distributions use it.  (All ELF versions, as far as I
+      know.)  An unresolved PLT entry points to "_dl_runtime_resolve",
+      which calls "fixup" to patch the PLT, and then passes control to
+      the function.
+ 
+      We look for the symbol `_dl_runtime_resolve', and find `fixup' in
+      the same objfile.  If we are at the entry point of `fixup', then
+      we set a breakpoint at the return address (at the top of the
+      stack), and continue.
+ 
+      It's kind of gross to do all these checks every time we're
+      called, since they don't change once the executable has gotten
+      started.  But this is only a temporary hack --- upcoming versions
+      of Linux will provide a portable, efficient interface for
+      debugging programs that use shared libraries.  */
+ 
+   struct objfile *objfile;
+   struct minimal_symbol *resolver
+     = find_minsym_and_objfile ("_dl_runtime_resolve", &objfile);
+ 
+   if (resolver)
+     {
+       struct minimal_symbol *fixup
+ 	= lookup_minimal_symbol ("fixup", 0, objfile);
+ 
+       if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc)
+ 	return (SAVED_PC_AFTER_CALL (get_current_frame ()));
+     }
+ 
+   return 0;
+ }
+ 
+ /* See the comments for SKIP_SOLIB_RESOLVER at the top of infrun.c.
+    This function:
+    1) decides whether a PLT has sent us into the linker to resolve
+       a function reference, and
+    2) if so, tells us where to set a temporary breakpoint that will
+       trigger when the dynamic linker is done.  */
+ 
+ CORE_ADDR
+ x86_64_linux_skip_solib_resolver (CORE_ADDR pc)
+ {
+   CORE_ADDR result;
+ 
+   /* Plug in functions for other kinds of resolvers here.  */
+   result = skip_hurd_resolver (pc);
+   if (result)
+     return result;
+ 
+   return 0;
+ }
+ 
+ /* Fetch (and possibly build) an appropriate link_map_offsets
+    structure for native Linux/x86 targets using the struct offsets
+    defined in link.h (but without actual reference to that file).
+ 
+    This makes it possible to access Linux/x86 shared libraries from a
+    GDB that was not built on an Linux/x86 host (for cross debugging).  */
+ 
+ struct link_map_offsets *
+ x86_64_linux_svr4_fetch_link_map_offsets (void)
+ {
+   static struct link_map_offsets lmo;
+   static struct link_map_offsets *lmp = NULL;
+ 
+   if (lmp == NULL)
+     {
+       lmp = &lmo;
+ 
+       lmo.r_debug_size = 12;	/* The actual size is 32 bytes, but
+ 				   this is all we need.  */
+       lmo.r_map_offset = 8;
+       lmo.r_map_size   = 8;
+ 
+       lmo.link_map_size = 40;
+ 
+       lmo.l_addr_offset = 0;
+       lmo.l_addr_size   = 8;
+ 
+       lmo.l_name_offset = 8;
+       lmo.l_name_size   = 8;
+ 
+       lmo.l_next_offset = 24;
+       lmo.l_next_size   = 8;
+ 
+       lmo.l_prev_offset = 32;
+       lmo.l_prev_size   = 8;
+     }
+ 
+   return lmp;
+ }
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	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,276 ----
+ /* AMD x86_64 native support.
+    Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999,
+    2000 Free Software Foundation, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ #include "defs.h"
+ 
+ #ifdef HAVE_PTRACE_H
+ #include <ptrace.h>
+ #else
+ #ifdef HAVE_SYS_PTRACE_H
+ #include <sys/ptrace.h>
+ #endif
+ #endif
+ 
+ #include "frame.h"
+ #include "inferior.h"
+ #include "language.h"
+ #include "gdbcore.h"
+ 
+ #ifdef USG
+ #include <sys/types.h>
+ #endif
+ 
+ #include <sys/param.h>
+ #include <sys/dir.h>
+ #include <signal.h>
+ #include <sys/user.h>
+ #include <sys/ioctl.h>
+ #include <fcntl.h>
+ #include <asm/debugreg.h>
+ 
+ #include <sys/file.h>
+ #include "gdb_stat.h"
+ 
+ #ifdef HAVE_SYS_REG_H
+ #include <sys/reg.h>
+ #endif
+ 
+ #include "floatformat.h"
+ 
+ #include "target.h"
+ \f
+ 
+ /* This table must line up with REGISTER_NAMES in tm-x86_64.h
+    symbols like 'RAX' come from <sys/reg.h>.  */
+ static int regmap[] = {
+   RAX, RDX, RCX, RBX,
+   RSI, RDI, RBP, RSP,
+   R8, R9, R10, R11,
+   R12, R13, R14, R15,
+   RIP, EFLAGS
+ };
+ 
+ /* 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 * regmap[regnum]);
+ }
+ \f
+ 
+ 
+ int
+ kernel_u_size (void)
+ {
+   return (sizeof (struct user));
+ }
+ \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];
+ 
+ static int
+ x86_64_insert_aligned_watchpoint (ptid_t, CORE_ADDR, CORE_ADDR, int, int);
+ 
+ static int
+ x86_64_insert_nonaligned_watchpoint (ptid_t, CORE_ADDR, CORE_ADDR, int, int);
+ 
+ /* Insert a watchpoint.  */
+ 
+ int
+ x86_64_insert_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw)
+ {
+   return x86_64_insert_aligned_watchpoint (ptid, addr, addr, len, rw);
+ }
+ 
+ static int
+ x86_64_insert_aligned_watchpoint (ptid_t ptid, CORE_ADDR waddr, CORE_ADDR addr,
+ 				  int len, int rw)
+ {
+   int i;
+   int read_write_bits, len_bits;
+   int free_debug_register;
+   int register_number;
+ 
+   /* Look for a free debug register.  */
+   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+     {
+       if (address_lookup[i - DR_FIRSTADDR] == 0)
+ 	break;
+     }
+ 
+   /* No more debug registers!  */
+   if (i > DR_LASTADDR)
+     return -1;
+ 
+   read_write_bits = (rw & 1) ? DR_RW_READ : DR_RW_WRITE;
+ 
+   if (len == 1)
+     len_bits = DR_LEN_1;
+   else if (len == 2)
+     {
+       if (addr % 2)
+ 	return x86_64_insert_nonaligned_watchpoint (ptid, waddr, addr, len,
+ 						    rw);
+       len_bits = DR_LEN_2;
+     }
+   else if (len == 4)
+     {
+       if (addr % 4)
+ 	return x86_64_insert_nonaligned_watchpoint (ptid, waddr, addr, len,
+ 						    rw);
+       len_bits = DR_LEN_4;
+     }
+   else if (len == 8)
+     {
+       if (addr % 8)
+ 	return x86_64_insert_nonaligned_watchpoint (ptid, waddr, addr, len,
+ 						    rw);
+       len_bits = DR_LEN_8;
+     }
+   else
+     return x86_64_insert_nonaligned_watchpoint (ptid, waddr, addr, len, rw);
+ 
+   free_debug_register = i;
+   register_number = free_debug_register - DR_FIRSTADDR;
+   debug_control_mirror |=
+     ((read_write_bits | len_bits)
+      << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
+   debug_control_mirror |=
+     (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
+   debug_control_mirror |= DR_LOCAL_SLOWDOWN;
+   debug_control_mirror &= ~DR_CONTROL_RESERVED;
+ 
+   ptrace (6, PIDGET (ptid), offsetof (struct user, u_debugreg[DR_CONTROL]),
+ 	  debug_control_mirror);
+   ptrace (6, PIDGET (ptid), offsetof (struct user, u_debugreg[free_debug_register]),
+ 	  addr);
+ 
+   /* Record where we came from.  */
+   address_lookup[register_number] = addr;
+   return 0;
+ }
+ 
+ static int
+ x86_64_insert_nonaligned_watchpoint (ptid_t ptid, CORE_ADDR waddr, CORE_ADDR addr,
+ 				     int len, int rw)
+ {
+   int align;
+   int size;
+   int rv;
+ 
+   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 */
+   };
+ 
+   rv = 0;
+   while (len > 0)
+     {
+       align = addr % 8;
+       /* Eight is the maximum length for x86-64.  */
+       size = size_try_array[len > 8 ? 7 : len - 1][align];
+ 
+       rv = x86_64_insert_aligned_watchpoint (ptid, waddr, addr, size, rw);
+       if (rv)
+ 	{
+ 	  x86_64_remove_watchpoint (ptid, waddr, size);
+ 	  return rv;
+ 	}
+       addr += size;
+       len -= size;
+     }
+   return rv;
+ }
+ 
+ /* Remove a watchpoint.  */
+ 
+ int
+ x86_64_remove_watchpoint (ptid_t ptid, CORE_ADDR addr, int len)
+ {
+   int i;
+   int register_number;
+ 
+   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+     {
+       register_number = i - DR_FIRSTADDR;
+       if (address_lookup[register_number] == addr)
+ 	{
+ 	  debug_control_mirror &=
+ 	    ~(1 <<
+ 	      (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
+ 	  address_lookup[register_number] = 0;
+ 	}
+     }
+   ptrace (6, PIDGET (ptid), offsetof (struct user, u_debugreg[DR_CONTROL]),
+ 	  debug_control_mirror);
+   ptrace (6, PIDGET (ptid), offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+ 
+   return 0;
+ }
+ 
+ /* Check if stopped by a watchpoint.  */
+ 
+ CORE_ADDR
+ x86_64_stopped_by_watchpoint (ptid_t ptid)
+ {
+   int i;
+   int status;
+ 
+   status = ptrace (3, PIDGET (ptid), offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+   ptrace (6, PIDGET (ptid), offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+ 
+   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+     {
+       if (status & (1 << (i - DR_FIRSTADDR)))
+ 	return address_lookup[i - DR_FIRSTADDR];
+     }
+   return 0;
+ }
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	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,763 ----
+ /* AMD x86-64 target-dependent stuff.
+    Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+    1998, 1999, 2000, 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.  */
+ 
+ #include "defs.h"
+ #include "gdb_string.h"
+ #include "frame.h"
+ #include "inferior.h"
+ #include "gdbcore.h"
+ #include "target.h"
+ #include "floatformat.h"
+ #include "symtab.h"
+ #include "gdbcmd.h"
+ #include "command.h"
+ #include "arch-utils.h"
+ #include "regcache.h"
+ 
+ /* x86_64_register_byte[i] is the offset into the register file of the
+    start of register number i.  We initialize this from
+    x86_64_register_raw_size.  */
+ int x86_64_register_byte[NUM_REGS];
+ 
+ /* x86_64_register_raw_size[i] is the number of bytes of storage in
+    GDB's register array occupied by register i.  */
+ 
+ int x86_64_register_raw_size[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
+ };
+ 
+ /* x86_64_register_virtual_size[i] is the size in bytes of the virtual
+    type of register i.  */
+ int x86_64_register_virtual_size[NUM_REGS];
+ \f
+ 
+ /* This is the variable that is set with "set disassembly-flavor", and
+    its legitimate values.  */
+ static const char att_flavor[] = "att";
+ static const char intel_flavor[] = "intel";
+ static const char *valid_flavors[] = {
+   att_flavor,
+   intel_flavor,
+   NULL
+ };
+ static const char *disassembly_flavor = att_flavor;
+ 
+ /* This is used to keep the bfd arch_info in sync with the disassembly
+    flavor.  */
+ static void set_disassembly_flavor_sfunc (char *, int,
+ 					  struct cmd_list_element *);
+ static void set_disassembly_flavor (void);
+ \f
+ 
+ /* Stdio style buffering was used to minimize calls to ptrace, but
+    this buffering did not take into account that the code section
+    being accessed may not be an even number of buffers long (even if
+    the buffer is only sizeof(int) long).  In cases where the code
+    section size happened to be a non-integral number of buffers long,
+    attempting to read the last buffer would fail.  Simply using
+    target_read_memory and ignoring errors, rather than read_memory, is
+    not the correct solution, since legitimate access errors would then
+    be totally ignored.  To properly handle this situation and continue
+    to use buffering would require that this code be able to determine
+    the minimum code section size granularity (not the alignment of the
+    section itself, since the actual failing case that pointed out this
+    problem had a section alignment of 4 but was not a multiple of 4
+    bytes long), on a target by target basis, and then adjust it's
+    buffer size accordingly.  This is messy, but potentially feasible.
+    It probably needs the bfd library's help and support.  For now, the
+    buffer size is set to 1.  (FIXME -fnf) */
+ 
+ #define CODESTREAM_BUFSIZ 1	/* Was sizeof(int), see note above */
+ static CORE_ADDR codestream_next_addr;
+ static CORE_ADDR codestream_addr;
+ static unsigned char codestream_buf[CODESTREAM_BUFSIZ];
+ static int codestream_off;
+ static int codestream_cnt;
+ 
+ #define codestream_tell() (codestream_addr + codestream_off)
+ #define codestream_peek() \
+   (codestream_cnt == 0 ? \
+    codestream_fill(1) : codestream_buf[codestream_off])
+ #define codestream_get() \
+   (codestream_cnt-- == 0 ? \
+    codestream_fill(0) : codestream_buf[codestream_off++])
+ 
+ static unsigned char
+ codestream_fill (int peek_flag)
+ {
+   codestream_addr = codestream_next_addr;
+   codestream_next_addr += CODESTREAM_BUFSIZ;
+   codestream_off = 0;
+   codestream_cnt = CODESTREAM_BUFSIZ;
+   read_memory (codestream_addr, (char *) codestream_buf, CODESTREAM_BUFSIZ);
+ 
+   if (peek_flag)
+     return (codestream_peek ());
+   else
+     return (codestream_get ());
+ }
+ 
+ static void
+ codestream_seek (CORE_ADDR place)
+ {
+   codestream_next_addr = place / CODESTREAM_BUFSIZ;
+   codestream_next_addr *= CODESTREAM_BUFSIZ;
+   codestream_cnt = 0;
+   codestream_fill (1);
+   while (codestream_tell () != place)
+     codestream_get ();
+ }
+ 
+ static void
+ codestream_read (unsigned char *buf, int count)
+ {
+   unsigned char *p;
+   int i;
+ 
+   p = buf;
+   for (i = 0; i < count; i++)
+     *p++ = codestream_get ();
+ }
+ \f
+ void
+ x86_64_push_dummy_frame (void)
+ {
+   CORE_ADDR sp = read_register (SP_REGNUM);
+   int regnum;
+   char regbuf[MAX_REGISTER_RAW_SIZE];
+ 
+   for (regnum = 0; regnum < NUM_REGS; regnum++)
+     {
+       read_register_gen (regnum, regbuf);
+       sp = push_bytes (sp, regbuf, REGISTER_RAW_SIZE (regnum));
+     }
+   write_register (SP_REGNUM, sp);
+ }
+ 
+ /* Insert the function address into the call sequence
+    stored at DUMMY.  */
+ void
+ uw_create_dummy_fde (CORE_ADDR initial_location, CORE_ADDR address_range);
+ 
+ void
+ x86_64_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
+ 		       value_ptr * args, struct type *type, int gcc_p)
+ {
+   int i;
+   long to = (long) (fun);
+ 
+   *(dummy + 3) = (to & 0xff);
+   *(dummy + 4) = ((to >> 8) & 0xff);
+   *(dummy + 5) = ((to >> 16) & 0xff);
+   *(dummy + 6) = ((to >> 24) & 0xff);
+   *(dummy + 7) = ((to >> 32) & 0xff);
+   *(dummy + 8) = ((to >> 40) & 0xff);
+   *(dummy + 9) = ((to >> 48) & 0xff);
+   *(dummy + 10) = ((to >> 52) & 0xff);
+ 
+   uw_create_dummy_fde (pc, CALL_DUMMY_LENGTH);
+ }
+ 
+ #ifdef GET_LONGJMP_TARGET
+ 
+ /* Figure out where the longjmp will land.  Slurp the args out of the
+    stack.  We expect the first arg to be a pointer to the jmp_buf
+    structure from which we extract the pc (JB_PC) that we will land
+    at.  The pc is copied into PC.  This routine returns true on
+    success.  */
+ 
+ int
+ get_longjmp_target (CORE_ADDR * pc)
+ {
+   char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+   CORE_ADDR sp, jb_addr;
+ 
+   sp = read_register (SP_REGNUM);
+ 
+   if (target_read_memory (sp + 8,	/* Offset of first arg on stack.  */
+ 			  buf, TARGET_PTR_BIT / TARGET_CHAR_BIT))
+     return 0;
+ 
+   jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+ 
+   if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
+ 			  TARGET_PTR_BIT / TARGET_CHAR_BIT))
+     return 0;
+ 
+   *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+ 
+   return 1;
+ }
+ 
+ #endif /* GET_LONGJMP_TARGET */
+ 
+ /* 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 (class1, class2)
+      enum x86_64_reg_class class1, 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;
+ 	}
+     }
+   internal_error (__FILE__, __LINE__, "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__, "Unexpected memory class");
+       }
+   return 1;
+ }
+ 
+ #define RET_INT_REGS 2
+ #define RET_SSE_REGS 2
+ int ret_int_r[RET_INT_REGS] = {
+   RAX_REGNUM, RDX_REGNUM
+ };
+ int ret_sse_r[RET_SSE_REGS] = {
+   XMM0_REGNUM, XMM1_REGNUM
+ };
+ 
+ /* 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 (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;
+ 
+   printf ("Argument classify n=%d\n", n);
+ 
+   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:
+ 	      printf ("X86_64_NO_CLASS\n");
+ 	      break;
+ 	    case X86_64_INTEGER_CLASS:
+ 	      printf ("X86_64_INTEGER_CLASS %d %d\n",
+ 		      ret_int_r[(intreg + 1) / 2],
+ 		      regbuf + REGISTER_BYTE (ret_int_r[(intreg + 1) / 2]));
+ 	      memcpy (valbuf + offset,
+ 		      regbuf + REGISTER_BYTE (ret_int_r[(intreg + 1) / 2]),
+ 		      8);
+ 	      offset += 8;
+ 	      intreg += 2;
+ 	      break;
+ 	    case X86_64_INTEGERSI_CLASS:
+ 	      printf ("X86_64_INTEGERSI_CLASS\n");
+ 	      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:
+ 	      printf ("X86_64_SSE_CLASS\n");
+ 	      memcpy (valbuf + offset,
+ 		      regbuf + REGISTER_BYTE (ret_sse_r[(ssereg + 1) / 2]),
+ 		      8);
+ 	      offset += 8;
+ 	      ssereg += 2;
+ 	      break;
+ 	    case X86_64_SSEUP_CLASS:
+ 	      printf ("X86_64_SSEUP_CLASS\n");
+ 	      memcpy (valbuf + offset + 8,
+ 		      regbuf + REGISTER_BYTE (ret_sse_r[ssereg / 2]), 8);
+ 	      offset += 8;
+ 	      ssereg++;
+ 	      break;
+ 	    case X86_64_X87_CLASS:
+ 	      printf ("X86_64_X87_CLASS\n");
+ 	      memcpy (valbuf + offset, regbuf + REGISTER_BYTE (FP0_REGNUM),
+ 		      8);
+ 	      offset += 8;
+ 	      break;
+ 	    case X86_64_X87UP_CLASS:
+ 	      printf ("X86_64_X87UP_CLASS\n");
+ 	      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");
+ 	    }
+ 	}
+     }
+ }
+ 
+ /* 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))
+     {
+       if (NUM_FREGS == 0)
+ 	{
+ 	  warning ("Cannot set floating-point return value.");
+ 	  return;
+ 	}
+ 
+       /* 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);
+     }
+ }
+ 
+ /* 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
+ 
+ /* 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_flavor == att_flavor)
+     return print_insn_i386_att (memaddr, info);
+   else if (disassembly_flavor == intel_flavor)
+     return print_insn_i386_intel (memaddr, info);
+   /* Never reached -- disassembly_flavour is always either att_flavor
+      or intel_flavor.  */
+   internal_error (__FILE__, __LINE__, "failed internal consistency check");
+ }
+ 
+ /* If the disassembly mode is intel, we have to also switch the bfd
+    mach_type.  This function is run in the set disassembly_flavor
+    command, and does that.  */
+ 
+ static void
+ set_disassembly_flavor_sfunc (char *args, int from_tty,
+ 			      struct cmd_list_element *c)
+ {
+   set_disassembly_flavor ();
+ }
+ 
+ static void
+ set_disassembly_flavor (void)
+ {
+   if (disassembly_flavor == att_flavor)
+     set_architecture_from_arch_mach (bfd_arch_i386, bfd_mach_x86_64);
+   else if (disassembly_flavor == intel_flavor)
+     set_architecture_from_arch_mach (bfd_arch_i386,
+ 				     bfd_mach_x86_64_intel_syntax);
+ }
+ \f
+ 
+ void
+ _initialize_x86_64_tdep (void)
+ {
+ /* Initialize the table saying where each register starts in the
+      register file.  */
+   {
+     int i, offset;
+ 
+     offset = 0;
+     for (i = 0; i < NUM_REGS; i++)
+       {
+ 	x86_64_register_byte[i] = offset;
+ 	offset += x86_64_register_raw_size[i];
+       }
+   }
+ 
+   /* Initialize the table of virtual register sizes.  */
+   {
+     int i;
+ 
+     for (i = 0; i < NUM_REGS; i++)
+       x86_64_register_virtual_size[i] =
+ 	TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (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 flavor.  */
+   {
+     struct cmd_list_element *new_cmd;
+ 
+     new_cmd = add_set_enum_cmd ("disassembly-flavor", no_class,
+ 				valid_flavors, &disassembly_flavor, "\
+ Set the disassembly flavor, the valid values are \"att\" and \"intel\", \
+ and the default value is \"att\".", &setlist);
+     new_cmd->function.sfunc = set_disassembly_flavor_sfunc;
+     add_show_from_set (new_cmd, &showlist);
+   }
+ 
+   /* Finally, initialize the disassembly flavor to the default given
+      in the disassembly_flavor variable.  */
+   set_disassembly_flavor ();
+ }
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	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,109 ----
+ /* Native support for Linux/x86-64.
+    Copyright 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+    1999, 2000, 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 NM_X86_64_H
+ #define NM_X86_64_H
+ 
+ #include "nm-linux.h"
+ 
+ 
+ #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
+ /* GNU/Linux supports the x86_64 hardware debugging registers.  */
+ 
+ #define TARGET_HAS_HARDWARE_WATCHPOINTS
+ 
+ #define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) 1
+ 
+ /* After a watchpoint trap, the PC points to the instruction after
+    the one that caused the trap.  Therefore we don't need to step over it.
+    But we do need to reset the status register to avoid another trap.  */
+ #define HAVE_CONTINUABLE_WATCHPOINT
+ 
+ #define STOPPED_BY_WATCHPOINT(W)  \
+   x86_64_stopped_by_watchpoint (inferior_ptid)
+ CORE_ADDR x86_64_stopped_by_watchpoint (ptid_t);
+ 
+ /* Use these macros for watchpoint insertion/removal.  */
+ 
+ #define target_insert_watchpoint(addr, len, type)  \
+   x86_64_insert_watchpoint (inferior_ptid, addr, len, type)
+ int x86_64_insert_watchpoint (ptid_t pid, CORE_ADDR addr, int len, int rw);
+ 
+ #define target_remove_watchpoint(addr, len, type)  \
+   x86_64_remove_watchpoint (inferior_ptid, addr, len)
+ int x86_64_remove_watchpoint (ptid_t pid, CORE_ADDR addr, int len);
+ \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
+ 
+ /* Nevertheless, define CANNOT_{FETCH,STORE}_REGISTER, because we might fall
+    back on the code `infptrace.c' (well a copy of that code in
+    `i386-linux-nat.c' for now) and we can access only the
+    general-purpose registers in that way.  */
+ extern int cannot_fetch_register (int regno);
+ extern int cannot_store_register (int regno);
+ #define CANNOT_FETCH_REGISTER(regno) cannot_store_register (regno)
+ #define CANNOT_STORE_REGISTER(regno) cannot_fetch_register (regno)
+ 
+ /* 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/tm-x86_64.h
===================================================================
RCS file: tm-x86_64.h
diff -N tm-x86_64.h
*** /dev/null	Tue May  5 13:32:27 1998
--- tm-x86_64.h	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,462 ----
+ /* Definitions to target GDB to GNU/Linux on x86-64.
+    Copyright 1992, 1993, 1995, 1996, 1998, 1999, 2000, 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 TM_X86_64_H
+ #define TM_X86_64_H
+ 
+ #define X86_64_GNULINUX_TARGET
+ #define ARCH_64BIT
+ #define TARGET_LONG_BIT 64
+ #define TARGET_LONG_LONG_BIT 64
+ #define TARGET_PTR_BIT 64
+ #define DWARF2_USE_CFI
+ 
+ #include "tm-linux.h"
+ #include "regcache.h"
+ 
+ /* Forward declarations for prototypes.  */
+ struct frame_info;
+ struct frame_saved_regs;
+ struct value;
+ struct type;
+ 
+ #define TARGET_BYTE_ORDER LITTLE_ENDIAN
+ 
+ /* The format used for `long double' is the i387 extended floating-point
+    format.  */
+ #define TARGET_LONG_DOUBLE_FORMAT &floatformat_i387_ext
+ 
+ /* Although the x86-64 extended floating-point has only 80 significant
+    bits, a `long double' actually takes up 128, to enforce
+    alignment.  */
+ 
+ #define TARGET_LONG_DOUBLE_BIT 128
+ 
+ /* Used for example in valprint.c:print_floating() to enable checking
+    for NaN's.  */
+ 
+ #define IEEE_FLOAT (1)
+ 
+ /* Number of traps that happen between exec'ing the shell to run an
+    inferior, and when we finally get to the inferior code.  This is 2
+    on most implementations.  */
+ 
+ #define START_INFERIOR_TRAPS_EXPECTED 2
+ 
+ /* Offset from address of function to start of its code.
+    Zero on most machines.  */
+ 
+ #define FUNCTION_START_OFFSET 0
+ 
+ /* On x86_64 there are no reasonable prologs.  */
+ 
+ #define SKIP_PROLOGUE(frompc)   (frompc)
+ 
+ /* Immediately after a function call, return the saved pc.  */
+ 
+ #define SAVED_PC_AFTER_CALL(frame) x86_64_linux_saved_pc_after_call (frame)
+ extern CORE_ADDR x86_64_linux_saved_pc_after_call (struct frame_info *);
+ 
+ /* Stack grows downward.  */
+ 
+ #define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+ 
+ /* Sequence of bytes for breakpoint instruction.  */
+ 
+ #define BREAKPOINT {0xcc}
+ 
+ /* Amount PC must be decremented by after a breakpoint.  This is often the
+    number of bytes in BREAKPOINT but not always.  */
+ 
+ #define DECR_PC_AFTER_BREAK 1
+ 
+ /* Say how long (ordinary) registers are.  This is a piece of bogosity
+    used in push_word and a few other places; REGISTER_RAW_SIZE is the
+    real way to know how big a register is.  */
+ \f
+ #define REGISTER_SIZE 8
+ 
+ /* Number of general registers.  */
+ #define NUM_GREGS (18)
+ 
+ /* Number of floating-point unit registers.  */
+ #define NUM_FREGS (16)
+ 
+ /* Number of SSE registers.
+    There are 16 xmm registers and 1 Control and Status Register (mxcsr).  */
+ #define NUM_SSE_REGS (17)
+ 
+ /* Number of all registers.  */
+ #define NUM_REGS (NUM_GREGS + NUM_FREGS + NUM_SSE_REGS)
+ 
+ /* Initializer for an array of names of registers.  There should be at least
+    NUM_REGS strings in this initializer.  Any excess ones are simply ignored.  */
+ 
+ #define 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"				\
+ 		       }
+ 
+ /* Register numbers of various important registers.  */
+ #define FP_REGNUM 6		/* (rbp) */
+ #define SP_REGNUM 7		/* (rsp) Contains address of top of stack.  */
+ #define PC_REGNUM 16		/* (rip) Contains program counter.  */
+ #define PS_REGNUM 17		/* (ps)  Contains processor status.  */
+ 
+ #define RAX_REGNUM    0		/* First return register.  */
+ #define RDX_REGNUM    1		/* Second return register.  */
+ #define RDI_REGNUM    5
+ 
+ /* Floating point registers. FP0 .. FP7 are consecutive register numbers.  */
+ #define FP0_REGNUM   18		/* First FPU floating-point register.  */
+ #define FP7_REGNUM   25		/* Last  FPU floating-point register.  */
+ 
+ /* 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.  */
+ 
+ #define FIRST_FPU_CTRL_REGNUM 26
+ #define FCTRL_REGNUM 26		/* FPU control word.  */
+ #define FPC_REGNUM   26		/* old name for FCTRL_REGNUM.  */
+ #define FSTAT_REGNUM 27		/* FPU status word.  */
+ #define FTAG_REGNUM  28		/* FPU register tag word.  */
+ #define FCS_REGNUM   29		/* FPU instruction's code segment selector
+ 				   16 bits, called "FPU Instruction Pointer
+ 				   Selector" in the x86 manuals.  */
+ #define FCOFF_REGNUM 30		/* FPU instruction's offset within segment
+ 				   ("Fpu Code OFFset").  */
+ #define FDS_REGNUM   31		/* FPU operand's data segment.  */
+ #define FDOFF_REGNUM 32		/* FPU operand's offset within segment.  */
+ #define FOP_REGNUM   33		/* FPU opcode, bottom eleven bits.  */
+ #define LAST_FPU_CTRL_REGNUM 33
+ 
+ /* SSE registers. XMM0 .. XMM15  are consecutive register numbers.   */
+ #define XMM0_REGNUM  34		/* First SSE data register.  */
+ #define XMM1_REGNUM  35
+ #define XMM15_REGNUM 49		/* Last  SSE2 data register.  */
+ #define MXCSR_REGNUM 50		/* Streaming SIMD Extension control/status.  */
+ 
+ #define IS_FP_REGNUM(n) (FP0_REGNUM <= (n) && (n) <= FP7_REGNUM)
+ #define IS_FPU_CTRL_REGNUM(n) (FIRST_FPU_CTRL_REGNUM <= (n) && (n) <= LAST_FPU_CTRL_REGNUM)
+ #define IS_SSE_REGNUM(n) (XMM0_REGNUM <= (n) && (n) <= XMM15_REGNUM)
+ 
+ #define FPU_REG_RAW_SIZE (10)
+ 
+ /* Sizes of individual register sets.  These cover the entire register
+    file, so summing up the sizes of those portions actually present
+    yields REGISTER_BYTES.  */
+ #define SIZEOF_GREGS (NUM_GREGS * REGISTER_SIZE)
+ #define SIZEOF_FPU_REGS (8 * FPU_REG_RAW_SIZE)
+ #define SIZEOF_FPU_CTRL_REGS \
+   ((LAST_FPU_CTRL_REGNUM - FIRST_FPU_CTRL_REGNUM + 1) * 4)
+ #define SIZEOF_SSE_REGS (8 * 16 + 4)
+ 
+ /* Total amount of space needed to store our copies of the machine's register
+    state, the array `registers'.  */
+ #define REGISTER_BYTES \
+   (SIZEOF_GREGS + SIZEOF_FPU_REGS + SIZEOF_FPU_CTRL_REGS + SIZEOF_SSE_REGS)
+ 
+ /* Index within `registers' of the first byte of the space for register N.  */
+ #define REGISTER_BYTE(n) (x86_64_register_byte[(n)])
+ extern int x86_64_register_byte[];
+ 
+ /* Number of bytes of storage in the actual machine representation for
+    register N.  */
+ #define REGISTER_RAW_SIZE(n) (x86_64_register_raw_size[(n)])
+ extern int x86_64_register_raw_size[];
+ 
+ /* Number of bytes of storage in the program's representation
+    for register N.  */
+ #define REGISTER_VIRTUAL_SIZE(n) (x86_64_register_virtual_size[(n)])
+ extern int x86_64_register_virtual_size[];
+ 
+ /* Largest value REGISTER_RAW_SIZE can have.  */
+ #define MAX_REGISTER_RAW_SIZE 16
+ 
+ /* Return the GDB type object for the "standard" data type of data in
+    register N.  Perhaps si and di should go here, but potentially they
+    could be used for things other than address.  */
+ 
+ #undef  REGISTER_VIRTUAL_TYPE
+ #define REGISTER_VIRTUAL_TYPE(N)				\
+   (((N) == PC_REGNUM || (N) == SP_REGNUM)	\
+    ? lookup_pointer_type (builtin_type_void)			\
+    : IS_FP_REGNUM(N) ? builtin_type_long_double			\
+    : IS_SSE_REGNUM(N) ? builtin_type_v4sf			\
+    : IS_FPU_CTRL_REGNUM(N) || N==MXCSR_REGNUM || N==PS_REGNUM   \
+    ? builtin_type_int : builtin_type_long)
+ 
+ /* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+ #define MAX_REGISTER_VIRTUAL_SIZE 16
+ 
+ /* REGISTER_CONVERTIBLE(N) is true iff 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.  */
+ #define REGISTER_CONVERTIBLE(n) (IS_FP_REGNUM (n))
+ 
+ /* Convert data from raw format for register REGNUM in buffer FROM to
+    virtual format with type TYPE in buffer TO.  */
+ #define REGISTER_CONVERT_TO_VIRTUAL(regnum, type, from, to) \
+   x86_64_register_convert_to_virtual ((regnum), (type), (from), (to))
+ extern void x86_64_register_convert_to_virtual (int regnum, struct type *type,
+ 						char *from, char *to);
+ 
+ /* Convert data from virtual format with type TYPE in buffer FROM to
+    raw format for register REGNUM in buffer TO.  */
+ #define REGISTER_CONVERT_TO_RAW(type, regnum, from, to) \
+   x86_64_register_convert_to_raw ((type), (regnum), (from), (to))
+ extern void x86_64_register_convert_to_raw (struct type *type, int regnum,
+ 					    char *from, char *to);
+ 
+ /* Print out the i387 floating point state.  */
+ #define FLOAT_INFO { i387_float_info (); }
+ extern void i387_float_info (void);
+ \f
+ /* Don't use default structure extract routine */
+ #undef EXTRACT_STRUCT_VALUE_ADDRESS
+ 
+ /* 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.  */
+ #define USE_STRUCT_CONVENTION(gcc_p, type) x86_64_use_struct_convention (type)
+ extern int x86_64_use_struct_convention (struct type *value_type);
+ 
+ /* Store the address of the place in which to copy the structure the
+    subroutine will return.  This is called from call_function. */
+ #define STORE_STRUCT_RETURN(ADDR, SP) write_register (RDI_REGNUM, ADDR);
+ 
+ /* 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.  */
+ 
+ #define EXTRACT_RETURN_VALUE(type, regbuf, valbuf) \
+   x86_64_extract_return_value ((type), (regbuf), (valbuf))
+ extern void x86_64_extract_return_value (struct type *type, char *regbuf,
+ 					 char *valbuf);
+ 
+ /* Write into the appropriate registers a function return value stored
+    in VALBUF of type TYPE, given in virtual format.  */
+ #define STORE_RETURN_VALUE(type, valbuf) \
+   x86_64_store_return_value ((type), (valbuf))
+ extern void x86_64_store_return_value (struct type *type, char *valbuf);
+ 
+ /* FRAME_CHAIN takes a frame's nominal address and produces the frame's
+    chain-pointer.  */
+ #define FRAME_CHAIN(FRAME) uw_frame_chain(FRAME)
+ extern CORE_ADDR uw_frame_chain (struct frame_info *thisframe);
+ 
+ /* A macro that tells us whether the function invocation represented
+    by FI does not have a frame on the stack associated with it.  If it
+    does not, FRAMELESS is set to 1, else 0.  */
+ #define FRAMELESS_FUNCTION_INVOCATION(FI) (0)
+ 
+ /* Saved Pc.  Get it from sigcontext if within sigtramp.  */
+ #define FRAME_SAVED_PC(FRAME)					\
+   ((FRAME)->signal_handler_caller				\
+    ? sigtramp_saved_pc (FRAME)					\
+    : (FRAMELESS_SIGNAL (FRAME)					\
+       ? read_memory_integer (x86_64_linux_sigtramp_saved_sp ((FRAME)->next), 8) \
+       : uw_get_ra (FRAME)))
+ extern CORE_ADDR uw_get_ra (struct frame_info *fi);
+ extern CORE_ADDR sigtramp_saved_pc (struct frame_info *);
+ 
+ #define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+ 
+ #define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+ 
+ /* Return number of args passed to a frame. -1, means no way to tell.  */
+ #define FRAME_NUM_ARGS(fi) (-1)
+ 
+ /* Return number of bytes at start of arglist that are not really args.  */
+ 
+ #define FRAME_ARGS_SKIP 8
+ 
+ /* Handled by unwind informations.  */
+ #define FRAME_INIT_SAVED_REGS(fi)
+ 
+ /* Frame pc initialization is handled by unwind informations.  */
+ #define INIT_FRAME_PC(fromleaf, prev) \
+ 	uw_init_frame_pc (fromleaf, prev)
+ extern void uw_init_frame_pc (int, struct frame_info *fi);
+ 
+ /* Unwind informations context is in frame info. */
+ #define EXTRA_FRAME_INFO \
+ 	struct unwind_context *context;
+ 
+ /* Initialization of unwind informations.  */
+ #define INIT_EXTRA_FRAME_INFO(fromleaf, fi) uw_init_extra_frame_info(fromleaf, fi)
+ extern void uw_init_extra_frame_info (int fromleaf, struct frame_info *fi);
+ 
+ /* Getting saved registers is handled by unwind informations.  */
+ #define GET_SAVED_REGISTER(raw_buffer, optimized, addrp, frame, regnum, lval) \
+    uw_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+ extern void uw_get_saved_register (char *raw_buffer,
+ 				   int *optimized,
+ 				   CORE_ADDR * addrp,
+ 				   struct frame_info *frame,
+ 				   int regnum, enum lval_type *lval);
+ #undef FRAME_INIT_SAVED_REGS
+ #define FRAME_INIT_SAVED_REGS(fi)
+ 
+ #define TARGET_READ_FP() uw_read_fp()
+ extern CORE_ADDR uw_read_fp ();
+ 
+ #define TARGET_WRITE_FP(val) uw_write_fp(val)
+ extern void uw_write_fp (CORE_ADDR val);
+ 
+ /* Cons up virtual frame pointer for trace */
+ #define TARGET_VIRTUAL_FRAME_POINTER(PC, REGP, OFFP) \
+ 	uw_virtual_frame_pointer ((PC), (REGP), (OFFP))
+ extern void uw_virtual_frame_pointer (CORE_ADDR, long *, long *);
+ \f
+ /* Things needed for making the inferior call functions.  */
+ 
+ /* "An argument's size is increased, if necessary, to make it a
+    multiple of [32 bit] words.  This may require tail padding,
+    depending on the size of the argument" - from the x86 ABI.  */
+ #define PARM_BOUNDARY 32
+ 
+ /* Push an empty stack frame, to record the current PC, etc.  */
+ 
+ #define PUSH_DUMMY_FRAME { x86_64_push_dummy_frame (); }
+ extern void x86_64_push_dummy_frame (void);
+ 
+ /* Discard from the stack the innermost frame, restoring all registers.  */
+ #define POP_FRAME  { uw_pop_frame (); }
+ extern void uw_pop_frame (void);
+ 
+ /* this is
+  *   mov    $0x................,%r14
+  *   callq  *(%r14)
+  *   int3
+  */
+ #define CALL_DUMMY { 0x000000000000be49, 0x00000000cc16ff49 }
+ 
+ #define CALL_DUMMY_LENGTH 16
+ 
+ #define CALL_DUMMY_START_OFFSET 0	/* Start execution at beginning of dummy.  */
+ 
+ #define CALL_DUMMY_BREAKPOINT_OFFSET 12
+ 
+ /* Insert the specified number of args and function address
+    into a call sequence of the above form stored at DUMMYNAME.  */
+ #define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+   x86_64_fix_call_dummy (dummyname, pc, fun, nargs, args, type, gcc_p)
+ extern void x86_64_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun,
+ 				   int nargs, struct value **args,
+ 				   struct type *type, int gcc_p);
+ \f
+ /* Use target_specific function to define link map offsets.  */
+ extern struct link_map_offsets
+   *x86_64_linux_svr4_fetch_link_map_offsets (void);
+ #define SVR4_FETCH_LINK_MAP_OFFSETS() x86_64_linux_svr4_fetch_link_map_offsets ()
+ 
+ /* The following works around a problem with /usr/include/sys/procfs.h  */
+ #define sys_quotactl 1
+ 
+ /* When the x86-64 Linux kernel calls a signal handler, the return
+    address points to a bit of code on the stack.  These definitions
+    are used to identify this bit of code as a signal trampoline in
+    order to support backtracing through calls to signal handlers.  */
+ 
+ #define IN_SIGTRAMP(pc, name) x86_64_linux_in_sigtramp (pc, name)
+ extern int x86_64_linux_in_sigtramp (CORE_ADDR, char *);
+ 
+ /* We need our own version of sigtramp_saved_pc to get the saved PC in
+    a sigtramp routine.  */
+ 
+ #define sigtramp_saved_pc x86_64_linux_sigtramp_saved_pc
+ extern CORE_ADDR x86_64_linux_sigtramp_saved_pc (struct frame_info *);
+ 
+ /* Signal trampolines don't have a meaningful frame.  As in tm-i386.h,
+    the frame pointer value we use is actually the frame pointer of the
+    calling frame--that is, the frame which was in progress when the
+    signal trampoline was entered.  gdb mostly treats this frame
+    pointer value as a magic cookie.  We detect the case of a signal
+    trampoline by looking at the SIGNAL_HANDLER_CALLER field, which is
+    set based on IN_SIGTRAMP.
+ 
+    When a signal trampoline is invoked from a frameless function, we
+    essentially have two frameless functions in a row.  In this case,
+    we use the same magic cookie for three frames in a row.  We detect
+    this case by seeing whether the next frame has
+    SIGNAL_HANDLER_CALLER set, and, if it does, checking whether the
+    current frame is actually frameless.  In this case, we need to get
+    the PC by looking at the SP register value stored in the signal
+    context.
+ 
+    This should work in most cases except in horrible situations where
+    a signal occurs just as we enter a function but before the frame
+    has been set up.  */
+ 
+ #define FRAMELESS_SIGNAL(FRAME)					\
+   ((FRAME)->next != NULL					\
+    && (FRAME)->next->signal_handler_caller			\
+    && frameless_look_for_prologue (FRAME))
+ 
+ extern CORE_ADDR x86_64_linux_sigtramp_saved_sp (struct frame_info *);
+ 
+ 
+ /* When we call a function in a shared library, and the PLT sends us
+    into the dynamic linker to find the function's real address, we
+    need to skip over the dynamic linker call.  This function decides
+    when to skip, and where to skip to.  See the comments for
+    SKIP_SOLIB_RESOLVER at the top of infrun.c.  */
+ #define SKIP_SOLIB_RESOLVER x86_64_linux_skip_solib_resolver
+ extern CORE_ADDR x86_64_linux_skip_solib_resolver (CORE_ADDR pc);
+ 
+ /* N_FUN symbols in shared libaries have 0 for their values and need
+    to be relocated. */
+ #define SOFUN_ADDRESS_MAYBE_MISSING
+ \f
+ 
+ /* Support for longjmp.  */
+ 
+ /* Details about jmp_buf.  It's supposed to be an array of integers.  */
+ 
+ #define JB_ELEMENT_SIZE 4	/* Size of elements in jmp_buf.  */
+ #define JB_PC		5	/* Array index of saved PC.  */
+ 
+ /* Figure out where the longjmp will land.  Slurp the args out of the
+    stack.  We expect the first arg to be a pointer to the jmp_buf
+    structure from which we extract the pc (JB_PC) that we will land
+    at.  The pc is copied into ADDR.  This routine returns true on
+    success.  */
+ 
+ #define GET_LONGJMP_TARGET(addr) get_longjmp_target (addr)
+ extern int get_longjmp_target (CORE_ADDR * addr);
+ 
+ #endif /* ifndef TM_X86_64_H */
Index: config/i386/x86_64.mh
===================================================================
RCS file: x86_64.mh
diff -N x86_64.mh
*** /dev/null	Tue May  5 13:32:27 1998
--- x86_64.mh	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,11 ----
+ # Host: AMD x86-64 running GNU/Linux
+ 
+ XM_FILE= xm-x86_64.h
+ XDEPFILES=
+ 
+ NAT_FILE= nm-x86_64.h
+ NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \
+ 	core-aout.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_64.mt
===================================================================
RCS file: x86_64.mt
diff -N x86_64.mt
*** /dev/null	Tue May  5 13:32:27 1998
--- x86_64.mt	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,6 ----
+ # Target: AMD x86-64 running GNU/Linux
+ TDEPFILES= x86_64-tdep.o x86_64-linux-tdep.o i387-tdep.o \
+ 	solib.o solib-svr4.o solib-legacy.o
+ TM_FILE= tm-x86_64.h
+ 
+ GDBSERVER_DEPFILES= low-linux.o
Index: config/i386/xm-x86_64.h
===================================================================
RCS file: xm-x86_64.h
diff -N xm-x86_64.h
*** /dev/null	Tue May  5 13:32:27 1998
--- xm-x86_64.h	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,32 ----
+ /* Native support for GNU/Linux, for GDB, the GNU debugger.
+    Copyright 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 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 XM_X86_64_H
+ #define XM_X86_64_H
+ 
+ #define HOST_BYTE_ORDER LITTLE_ENDIAN
+ 
+ #define HOST_LONG_DOUBLE_FORMAT &floatformat_i387_ext
+ 
+ /* Need R_OK etc, but USG isn't defined.  */
+ #include <unistd.h>
+ 
+ #endif /* #ifndef XM_X86_64_H */

-- 
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] 17+ messages in thread

* Re: [RFA]: x86_64 target files
  2001-08-02  7:20 [RFA]: x86_64 target files Jiri Smid
@ 2001-08-02  8:39 ` Eli Zaretskii
  2001-08-02  9:37   ` Andreas Jaeger
  2001-08-02  9:43 ` Kevin Buettner
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2001-08-02  8:39 UTC (permalink / raw)
  To: Jiri Smid; +Cc: gdb-patches

On 2 Aug 2001, Jiri Smid wrote:

> This is the related new files for x86-64 target.

What is x86-64, exactly?  Some of the files seem to hint that it's an AMD 
CPU, but others just say x86-64.

If this is a new target, I think it should be added to NEWS in the 
appropriate section.

> 	* x86_64-linux-tdep.c: New file.
> 	* x86_64-linux-nat.c: New file.

These 2 file names clash after truncation to 8+3, so they should be added 
to config/djgpp/fnchange.lst, which see.

> + int
> + x86_64_insert_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw)
> + {
> +   return x86_64_insert_aligned_watchpoint (ptid, addr, addr, len, rw);
> + }
> + 
> + static int
> + x86_64_insert_aligned_watchpoint (ptid_t ptid, CORE_ADDR waddr, CORE_ADDR addr,
> + 				  int len, int rw)

This and the rest of watchpoint support is based on the old code from 
i386v-nat.c.  Isn't it much better to use the approach in i386-nat.c 
instead?  Most of the ia32 targets now use code from i386-nat.c, and thus 
support watchpoint sharing, and have a few subtle bugs in the previous 
code solved.  I think it makes sense to base this new target on the new 
code rather than on the old one.


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

* Re: [RFA]: x86_64 target files
  2001-08-02  8:39 ` Eli Zaretskii
@ 2001-08-02  9:37   ` Andreas Jaeger
  0 siblings, 0 replies; 17+ messages in thread
From: Andreas Jaeger @ 2001-08-02  9:37 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Jiri Smid, gdb-patches

Eli Zaretskii <eliz@is.elta.co.il> writes:

> On 2 Aug 2001, Jiri Smid wrote:
> 
>> This is the related new files for x86-64 target.

Thanks!

> What is x86-64, exactly?  Some of the files seem to hint that it's an AMD 
> CPU, but others just say x86-64.

x86-64 is AMD's 64 bit architecture which is an 64-bit enhancement to
the ia32 (ix86) architecture.  The step from 32-bit to 64-bit has been
done in a similar way as done by MIPS and SPARC for their CPUs.

In a nutshell:
x86-64 has 16 (instead of 8 for ia32) normal registers that hold
64-bit, 16 XMM (instead of 8 for ia32) registers used by SSE/SSE2 and
the x87 FPU.

For more details check http://www.x86-64.org - or ask me,
Andreas
-- 
 Andreas Jaeger
  SuSE Labs aj@suse.de
   private aj@arthur.inka.de
    http://www.suse.de/~aj


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

* Re: [RFA]: x86_64 target files
  2001-08-02  7:20 [RFA]: x86_64 target files Jiri Smid
  2001-08-02  8:39 ` Eli Zaretskii
@ 2001-08-02  9:43 ` Kevin Buettner
  2001-08-09 22:53   ` Andrew Cagney
  2001-08-09 23:12 ` config/i386/xm-x86_64.h; Was " Andrew Cagney
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Kevin Buettner @ 2001-08-02  9:43 UTC (permalink / raw)
  To: Jiri Smid, gdb-patches

Jiri,

I haven't looked closely at your patch, but one of the things that I
did notice is that your target is not multi-arched.  I am fairly certain
that this will need to be done before your changes will be accepted.

For more information, see

    http://sources.redhat.com/gdb/papers/multi-arch/

Also, I am curious about the reasons for having two *-nat.c files.
I think that x86_64-linux-nat.c is fine, but I noticed that the
presumably more generic x86_64-nat.c still has ptrace() calls in
it.  It seems to me that it may be difficult for other operating
systems (such as those which don't use ptrace()) to make use of
this file.

Kevin


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

* Re: [RFA]: x86_64 target files
  2001-08-02  9:43 ` Kevin Buettner
@ 2001-08-09 22:53   ` Andrew Cagney
  0 siblings, 0 replies; 17+ messages in thread
From: Andrew Cagney @ 2001-08-09 22:53 UTC (permalink / raw)
  To: Jiri Smid; +Cc: Kevin Buettner, gdb-patches

> Jiri,
> 
> I haven't looked closely at your patch, but one of the things that I
> did notice is that your target is not multi-arched.  I am fairly certain
> that this will need to be done before your changes will be accepted.
> 
> For more information, see
> 
>     http://sources.redhat.com/gdb/papers/multi-arch/


Yes, that is correct.  All new targets need to use the multi-arch framework.

In general the target should be broken down into two parts:

	o	the generic target code
		which is typically purely multi-arch
		(i.e. no macros at all)

	o	the nat stuff (which I tend to have
		little intereest in :-)

Andrew


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

* config/i386/xm-x86_64.h; Was [RFA]: x86_64 target files
  2001-08-02  7:20 [RFA]: x86_64 target files Jiri Smid
  2001-08-02  8:39 ` Eli Zaretskii
  2001-08-02  9:43 ` Kevin Buettner
@ 2001-08-09 23:12 ` Andrew Cagney
  2001-08-09 23:25 ` configure.host; Was: " Andrew Cagney
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Andrew Cagney @ 2001-08-09 23:12 UTC (permalink / raw)
  To: Jiri Smid; +Cc: gdb-patches

Just FYI, I'm trying to eliminate the need for xm files such as.

 > * config/i386/xm-x86_64.h: New file.

however for the moment we've still got them, so notes below:

 > + /* Need R_OK etc, but USG isn't defined.  */
 > + #include <unistd.h>

I think this bit is wrong.  It should be handled by autoconf or some 
other mechanism.  If it is really really needed then the xm-* file will 
need to be renamed to something that mentions ``linux''.  There is no 
guarentee that any other OS will have the same problem.

Could you even exploit MarkK's recent cleanups and just point XM_FILE at 
config/i386/xm-i386.h?

	Andrew


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

* configure.host; Was: [RFA]: x86_64 target files
  2001-08-02  7:20 [RFA]: x86_64 target files Jiri Smid
                   ` (2 preceding siblings ...)
  2001-08-09 23:12 ` config/i386/xm-x86_64.h; Was " Andrew Cagney
@ 2001-08-09 23:25 ` Andrew Cagney
  2001-08-09 23:41 ` configure.tgt; " Andrew Cagney
  2001-08-09 23:57 ` Misc; " Andrew Cagney
  5 siblings, 0 replies; 17+ messages in thread
From: Andrew Cagney @ 2001-08-09 23:25 UTC (permalink / raw)
  To: Jiri Smid; +Cc: gdb-patches

>  * configure.host: Recognize x86_64-*-linux*.


Could I suggest also mentioning the x86_64 -> i386 map in the change log 
entry.

>  * config/i386/nm-x86_64.h: New file.


configure.host and and */*/*.mh go hand in hand.  Since LINUX isn't the 
only OS out there, I think a more specific name for this file is needed.

Keep an eye on XM_FILE, you may eventually be able to delete it.

	Andrew

> *** configure.host	2001/07/10 20:41:54	1.23
> --- configure.host	2001/08/02 07:38:37
> *************** 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_64 ;;
>   
>   esac
> 

> Index: config/i386/x86_64.mh
> ===================================================================
> RCS file: x86_64.mh
> diff -N x86_64.mh
> *** /dev/null	Tue May  5 13:32:27 1998
> --- x86_64.mh	Thu Aug  2 00:38:41 2001
> ***************
> *** 0 ****
> --- 1,11 ----
> + # Host: AMD x86-64 running GNU/Linux
> + 
> + XM_FILE= xm-x86_64.h
> + XDEPFILES=
> + 
> + NAT_FILE= nm-x86_64.h
> + NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \
> + 	core-aout.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
> 



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

* configure.tgt; Was: [RFA]: x86_64 target files
  2001-08-02  7:20 [RFA]: x86_64 target files Jiri Smid
                   ` (3 preceding siblings ...)
  2001-08-09 23:25 ` configure.host; Was: " Andrew Cagney
@ 2001-08-09 23:41 ` Andrew Cagney
  2001-08-09 23:57 ` Misc; " Andrew Cagney
  5 siblings, 0 replies; 17+ messages in thread
From: Andrew Cagney @ 2001-08-09 23:41 UTC (permalink / raw)
  To: Jiri Smid; +Cc: gdb-patches

> 	* configure.tgt: Likewise.


Again, could I suggest mentioning the x86_64->i386 cpu map.

As with the host, the target files need to be broken along OS vs generic 
architecture lines.


>   # OBSOLETE w65-*-*)		gdb_target=w65 ;;
> + 
> + x86_64-*-linux*)	gdb_target=x86_64
> +  		configdirs="${configdirs} gdbserver" ;;


Could this please be changed to:

	x86_64-*-linux*)	gdb_target=<something-linuxish>
		configdirs=... ;;
	x86_64-*-*)	gdb_target=x86_64 ;;

i.e. again, separate out the linux specific stuff from the more generic 
x86_64 stuff.

Further down in that same file is the code to mark this target as 
multi-arch.  I think that should apply to x86_64-*-*.  This would mean 
that tm-x86_64 is redundant.


> 	* config/i386/x86_64.mt: New file.


Per the above, I think there should be two files:

	x86_64.mt
		which would not contain GDBSERVER_*
	<something linuxish>.mt
		which contains GDBSERVER_*


> 	* config/i386/tm-x86_64.h: New file.


Per the above, this file can probably be eliminated.

	Andrew



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

* Misc; Was: [RFA]: x86_64 target files
  2001-08-02  7:20 [RFA]: x86_64 target files Jiri Smid
                   ` (4 preceding siblings ...)
  2001-08-09 23:41 ` configure.tgt; " Andrew Cagney
@ 2001-08-09 23:57 ` Andrew Cagney
  2001-08-30  1:35   ` Jiri Smid
  5 siblings, 1 reply; 17+ messages in thread
From: Andrew Cagney @ 2001-08-09 23:57 UTC (permalink / raw)
  To: Jiri Smid; +Cc: gdb-patches

Jiri, some quick comments on things that caught my eye.  Once the 
*-tdep.c file is multi-arched (as much as possible) I'll go review the 
*-nat file properly.

	enjoy,
		Andrew

> + /* This table must line up with REGISTER_NAMES in tm-x86_64.h
> +    symbols like 'RAX' come from <sys/reg.h>.  */
> + static int regmap[] = {
> +   RAX, RDX, RCX, RBX,
> +   RSI, RDI, RBP, RSP,
> +   R8, R9, R10, R11,
> +   R12, R13, R14, R15,
> +   RIP, EFLAGS
> + };


You are encouraged to create a file like:

	x86_64-tdep.h

so that this sort of thing can be shared amonst the various x86_64 
specific files.  Both *-nat and *-nat-linux contained that exact table. 
  Just be careful to namespace proof things a little (x86_64 prefixes 
and the like).

--

> + /* This is the variable that is set with "set disassembly-flavor", and
> +    its legitimate values.  */
> + static const char att_flavor[] = "att";
> + static const char intel_flavor[] = "intel";
> + static const char *valid_flavors[] = {
> +   att_flavor,
> +   intel_flavor,
> +   NULL
> + };
> + static const char *disassembly_flavor = att_flavor;
> 


Have a look at the ARM which queries opcodes for a list of disassembly 
variants instead of duplicating those variants here.

--

> + static unsigned char
> + codestream_fill (int peek_flag)


FYI, I don't think that the code stream stuff belongs in a *-tdep.c. 
Hmm, I suspect you accidently picked it up when clonning i386-tdep.c. 
Could I recommend going through your new *-tdep.c file and cleaning out 
anything that isn't being used.

	Andrew


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

* Re: Misc; Was: [RFA]: x86_64 target files
  2001-08-09 23:57 ` Misc; " Andrew Cagney
@ 2001-08-30  1:35   ` Jiri Smid
  2001-08-30  7:39     ` Andrew Cagney
  0 siblings, 1 reply; 17+ messages in thread
From: Jiri Smid @ 2001-08-30  1:35 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: gdb-patches

  Hello,

  Sorry for late response - I was on vacation.

Andrew Cagney <ac131313@cygnus.com> writes:

> Jiri, some quick comments on things that caught my eye.  Once the *-tdep.c file
> is multi-arched (as much as possible) I'll go review the *-nat file properly.
> 
> 	enjoy,
> 		Andrew
> 
> > + /* This table must line up with REGISTER_NAMES in tm-x86_64.h
> > +    symbols like 'RAX' come from <sys/reg.h>.  */
> > + static int regmap[] = {
> > +   RAX, RDX, RCX, RBX,
> > +   RSI, RDI, RBP, RSP,
> > +   R8, R9, R10, R11,
> > +   R12, R13, R14, R15,
> > +   RIP, EFLAGS
> > + };
> 
> 
> You are encouraged to create a file like:
> 
> 	x86_64-tdep.h
> 
> so that this sort of thing can be shared amonst the various x86_64 specific
> files.  Both *-nat and *-nat-linux contained that exact table. Just be careful
> to namespace proof things a little (x86_64 prefixes and the like).

  OK.
> 
> --
> 
> > + /* This is the variable that is set with "set disassembly-flavor", and
> > +    its legitimate values.  */
> > + static const char att_flavor[] = "att";
> > + static const char intel_flavor[] = "intel";
> > + static const char *valid_flavors[] = {
> > +   att_flavor,
> > +   intel_flavor,
> > +   NULL
> > + };
> > + static const char *disassembly_flavor = att_flavor;
> >
> 
> 
> Have a look at the ARM which queries opcodes for a list of disassembly variants
> instead of duplicating those variants here.
>
  I have looked at ARM and there is list of dissassembly flavors
(register set names) obtained from binutils. But in i386/x86_64 case there
is no way how to get list of flavors. I am not sure what do you mean...
Changes in binutils?

> 
> > + static unsigned char
> > + codestream_fill (int peek_flag)
> 
> 
> FYI, I don't think that the code stream stuff belongs in a *-tdep.c. Hmm,
> I suspect you accidently picked it up when clonning i386-tdep.c. Could
> I recommend going through your new *-tdep.c file and cleaning out anything that
> isn't being used.
> 
  OK, I removed it.


-- 
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] 17+ messages in thread

* Re: Misc; Was: [RFA]: x86_64 target files
  2001-08-30  1:35   ` Jiri Smid
@ 2001-08-30  7:39     ` Andrew Cagney
  2001-08-30 11:03       ` Andreas Jaeger
  0 siblings, 1 reply; 17+ messages in thread
From: Andrew Cagney @ 2001-08-30  7:39 UTC (permalink / raw)
  To: Jiri Smid; +Cc: gdb-patches

>> Have a look at the ARM which queries opcodes for a list of disassembly variants
>> instead of duplicating those variants here.
>>
> 
> I have looked at ARM and there is list of dissassembly flavors
> (register set names) obtained from binutils. But in i386/x86_64 case there
> is no way how to get list of flavors. I am not sure what do you mean...
> Changes in binutils?

Hmm, the interface isn't as clean as I remembered :-).  Yes, it would 
mean getting a change into binutils.

The theory is that GDB knows nothing about the assembler except how to 
call it.  It defers to opcodes for things like assembler flavour names - 
this guarentees that objdump and GDB have a consistent interface.  For 
you, it is looking like the best thing is to file a PR and follow it up 
later.

One side thought, I'm surprised that there isn't a simple ``set 
disassembler ...'' command.

	Andrew



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

* Re: Misc; Was: [RFA]: x86_64 target files
  2001-08-30  7:39     ` Andrew Cagney
@ 2001-08-30 11:03       ` Andreas Jaeger
  2001-08-30 16:53         ` Andrew Cagney
  0 siblings, 1 reply; 17+ messages in thread
From: Andreas Jaeger @ 2001-08-30 11:03 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: Jiri Smid, gdb-patches

Andrew Cagney <ac131313@cygnus.com> writes:

>>> Have a look at the ARM which queries opcodes for a list of disassembly variants
>>> instead of duplicating those variants here.
>>>
>> I have looked at ARM and there is list of dissassembly flavors
>> (register set names) obtained from binutils. But in i386/x86_64 case there
>> is no way how to get list of flavors. I am not sure what do you mean...
>> Changes in binutils?
>
> Hmm, the interface isn't as clean as I remembered :-).  Yes, it would
> mean getting a change into binutils.
>
> The theory is that GDB knows nothing about the assembler except how to
> call it.  It defers to opcodes for things like assembler flavour names
> -
> this guarentees that objdump and GDB have a consistent interface.  For
> you, it is looking like the best thing is to file a PR and follow it
> up later.

I can try to take care of this in binutils.  You suggest something
like get_arm_regnames in opcodes/arm-dis.c I guess?

I'll look tomorrow into this,

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


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

* Re: Misc; Was: [RFA]: x86_64 target files
  2001-08-30 11:03       ` Andreas Jaeger
@ 2001-08-30 16:53         ` Andrew Cagney
  2001-08-31  0:13           ` Andreas Jaeger
  0 siblings, 1 reply; 17+ messages in thread
From: Andrew Cagney @ 2001-08-30 16:53 UTC (permalink / raw)
  To: Andreas Jaeger; +Cc: Jiri Smid, gdb-patches

> 
> I can try to take care of this in binutils.  You suggest something
> like get_arm_regnames in opcodes/arm-dis.c I guess?

Yes, but having looked at the interface, it isn't the most elegant.  If 
it is there and gdb uses it then nice.  If not, then something to fix later.

> I'll look tomorrow into this,

Thanks.
	Andrew



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

* Re: Misc; Was: [RFA]: x86_64 target files
  2001-08-30 16:53         ` Andrew Cagney
@ 2001-08-31  0:13           ` Andreas Jaeger
  2001-08-31  2:00             ` i386 flavors [Was: Re: Misc; Was: [RFA]: x86_64 target files] Andreas Jaeger
  2001-08-31 10:39             ` Misc; Was: [RFA]: x86_64 target files Andrew Cagney
  0 siblings, 2 replies; 17+ messages in thread
From: Andreas Jaeger @ 2001-08-31  0:13 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: Jiri Smid, gdb-patches

Andrew Cagney <ac131313@cygnus.com> writes:

>>
>> I can try to take care of this in binutils.  You suggest something
>> like get_arm_regnames in opcodes/arm-dis.c I guess?
>
> Yes, but having looked at the interface, it isn't the most elegant.

Do you have a better idea for an interface?

Andreas
> If it is there and gdb uses it then nice.  If not, then something to
> fix later.


>> I'll look tomorrow into this,
>
> Thanks.
> 	Andrew
>
>
>

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


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

* i386 flavors [Was: Re: Misc; Was: [RFA]: x86_64 target files]
  2001-08-31  0:13           ` Andreas Jaeger
@ 2001-08-31  2:00             ` Andreas Jaeger
  2001-08-31 10:39             ` Misc; Was: [RFA]: x86_64 target files Andrew Cagney
  1 sibling, 0 replies; 17+ messages in thread
From: Andreas Jaeger @ 2001-08-31  2:00 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: Jiri Smid, gdb-patches

Here's a proposal for an implementation  - it's similar to the arm way
of doing it.

I would additionally export print_insn_i386 and then gdb would use
that call.  i386-tdep.c and x86-64-tdep.c would need to use the new
interface, I can send patches if we like to go this way.

Mark, as i386 maintainer, what do you think?

Andreas

typedef struct
{
  const char *name;
  const char *description;
}
i386_flavor;

static i386_flavor i386_flavors [] =
{
  { "att", "Select ATT syntax."},
  { "intel", "Select Intel syntax."}
};

enum {ATT_FLAVOR, INTEL_FLAVOR};

static int current_i386_flavor;

int
get_i386_num_flavors (void)
{
  return sizeof (i386_flavors) / sizeof (i386_flavor);
}

int
set_i386_flavor (int flavor);
{
  int old = current_i386_flavor;
  current_i386_flavor = flavor;
  
  switch (flavor)
    {
    case ATT_FLAVOR:
      intel_syntax = 0;
      open_char = '(';
      close_char =  ')';
      separator_char = ',';
      scale_char = ',';
      break;

    case INTEL_FLAVOR:
      intel_syntax = 1;
      open_char = '[';
      close_char = ']';
      separator_char = '+';
      scale_char = '*';
      break;

    default:
      abort ();
    }

  return old;
}

void
get_i386_flavor (int flavor, const char **name, const char **description)
{
  *name = i386_flavors [flavor].name;
  *description = i386_flavors [flavor].description;
}

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


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

* Re: Misc; Was: [RFA]: x86_64 target files
  2001-08-31  0:13           ` Andreas Jaeger
  2001-08-31  2:00             ` i386 flavors [Was: Re: Misc; Was: [RFA]: x86_64 target files] Andreas Jaeger
@ 2001-08-31 10:39             ` Andrew Cagney
  2001-08-31 13:12               ` Andreas Jaeger
  1 sibling, 1 reply; 17+ messages in thread
From: Andrew Cagney @ 2001-08-31 10:39 UTC (permalink / raw)
  To: Andreas Jaeger; +Cc: Jiri Smid, gdb-patches

> Andrew Cagney <ac131313@cygnus.com> writes:
> 
> 
>>>
>>> I can try to take care of this in binutils.  You suggest something
>>> like get_arm_regnames in opcodes/arm-dis.c I guess?
> 
>>
>> Yes, but having looked at the interface, it isn't the most elegant.
> 
> 
> Do you have a better idea for an interface?

No.

(Just to be clear.  The ``fix'', what ever it is, requires an interface 
change to OPCODES.  I don't think it is reasonable for me to make the 
x86-64 tdep file approval dependant on such an external interface 
change.  Hence me suggestion to Jiri that a PR recording the problem be 
filed and hence the code remain as is.)

I've only got a gut feeling.   The x86-64 makes for a second target (and 
if we add in the x86m at least a third) that wants a mechanism for 
controlling the opcodes assembler.  GDB can certainly keep adding hooks 
to OPCODES, however, I think it might be time to consider a more generic 
interface - that way GDB developers only need to do this once.

Looking at include/dis-asm.h, `struct disassemble_info' already contains 
dissassembler_options.  A simplistic(1) aproach might be to add the command:

	(gdb) set disassembler <blah>

where <blah> was mindlessly assigned to dissassembler_options.  There 
are plenty of variations on this and probably other better ideas.

Enjoy,
	Andrew

(1) And my simplistic suggestion is certainly not as simple as it looks 
:-/ : getting GDB to detect / report a invalid option at the time it is 
set instead of used;  getting GDB to handle this in a multi-arch 
environment (an open problem - avoided so far by people using ``set 
<arch> <option> ...'');  getting GDB to report a list of valid options 
in response to:

	(gdb) set disassembler
or even	(gdb) set disassembler <tab>

hmm ... :-)


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

* Re: Misc; Was: [RFA]: x86_64 target files
  2001-08-31 10:39             ` Misc; Was: [RFA]: x86_64 target files Andrew Cagney
@ 2001-08-31 13:12               ` Andreas Jaeger
  0 siblings, 0 replies; 17+ messages in thread
From: Andreas Jaeger @ 2001-08-31 13:12 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: Jiri Smid, gdb-patches

Andrew Cagney <ac131313@cygnus.com> writes:

>> Andrew Cagney <ac131313@cygnus.com> writes:
>>
>>>>
>>>> I can try to take care of this in binutils.  You suggest something
>>>> like get_arm_regnames in opcodes/arm-dis.c I guess?
>>
>>>
>>> Yes, but having looked at the interface, it isn't the most elegant.
>> Do you have a better idea for an interface?
>
> No.
>
> (Just to be clear.  The ``fix'', what ever it is, requires an
> interface change to OPCODES.  I don't think it is reasonable for me to
> make the x86-64 tdep file approval dependant on such an external
> interface change.  Hence me suggestion to Jiri that a PR recording the
> problem be filed and hence the code remain as is.)

That's reasonable.

IMO - and as x86-64 binutils co-maintainer - if it's not too complex,
we should do it directly and not wait.  Therefore I'd like to discuss
it now and get it done directly right.  If we notice that the solution
is too involved, we can stick with Jiri's version.

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


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

end of thread, other threads:[~2001-08-31 13:12 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-08-02  7:20 [RFA]: x86_64 target files Jiri Smid
2001-08-02  8:39 ` Eli Zaretskii
2001-08-02  9:37   ` Andreas Jaeger
2001-08-02  9:43 ` Kevin Buettner
2001-08-09 22:53   ` Andrew Cagney
2001-08-09 23:12 ` config/i386/xm-x86_64.h; Was " Andrew Cagney
2001-08-09 23:25 ` configure.host; Was: " Andrew Cagney
2001-08-09 23:41 ` configure.tgt; " Andrew Cagney
2001-08-09 23:57 ` Misc; " Andrew Cagney
2001-08-30  1:35   ` Jiri Smid
2001-08-30  7:39     ` Andrew Cagney
2001-08-30 11:03       ` Andreas Jaeger
2001-08-30 16:53         ` Andrew Cagney
2001-08-31  0:13           ` Andreas Jaeger
2001-08-31  2:00             ` i386 flavors [Was: Re: Misc; Was: [RFA]: x86_64 target files] Andreas Jaeger
2001-08-31 10:39             ` Misc; Was: [RFA]: x86_64 target files Andrew Cagney
2001-08-31 13:12               ` Andreas Jaeger

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