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


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

[PATCH] Sparc Linux stuff


Hi!

Following patch makes gdb 5.0 compile on sparc-*-linux and adds a
semi-usable support for sparc64-*-linux.

This patch works just fine against gdb from say November, but after somewhen
in December things broke - that's why I haven't submitted the patch yet
(no matter whether this patch is in or not (in the latter case one has to tweak a
few things to make things compile), e.g. next command does not work.
Say

#include <stdio.h>
void foo(void)
{
        printf("a\n");
}
void bar(void)
{
        printf("b\n");
}
void main(void)
{
        foo();
        bar();
        foo();
}

compiled with -g -O0, putting breakpoint on main works just fine but then if
I enter next, it goes on until program exit (ie. does not stop where it
should).
Can somebody please look at this? I'm not familiar enough with the infptrace
and related code, so it would take me a lot of time to find out what's going
on and I have a bunch of gcc issues I have to go after.
If it works, I can try to finish the sparc64 debugging.
).

2000-03-17  Jakub Jelinek  <jakub@redhat.com>

	* config/sparc/tm-linux.h: Work around asm/ptrace.h and sys/ptrace.h
	header clash.
	* config/sparc/nm-linux.h (CHILD_XFER_MEMORY): Define - Linux/SPARC
	does not support PT_READ_U/PT_WRITE_U, on the other side
	PTHREAD_READTEXT/WRITETEXT is much more efficient.
	(USE_PROC_FS): Undefine.
	* config/sparc/linux.mh (NATDEPFILES): Use sparc-linux-nat instead
	of sparc-nat.
	* sparc-nat.c: Delete linux asm/reg.h include.
	* sparc-linux-nat.c: New file.
	* defs.h (TARGET_MAX_PTR_BIT): Define, if not yet defined.
	* blockframe.c (sigtramp_saved_pc): Use TARGET_MAX_PTR_BIT instead
	of TARGET_PTR_BIT since it must be a constant.
	* solib.c (elf_locate_base): Likewise.
	* jv-valprint.c (java_value_print): Likewise.
	* lin-thread.c (save_inferior_pid, restore_inferior_pid): Likewise.
	* linux-thread.c (save_inferior_pid, restore_inferior_pid): Likewise.

	* configure.tgt: Support sparc64-*-linux*.
	* configure.host: Likewise.
	* config/sparc/linux64.mh: New file.
	* config/sparc/linux64.mt: New file.
	* config/sparc/xm-linux64.h: New file.
	* config/sparc/nm-linux64.h: New file.
	* config/sparc/tm-linux64.h: New file.
	* config/sparc/tm-sp64.h (everywhere): Use is_sparc64 expression
	(which can be constant for gdb supporting only one architecture size)
	instead of GDB_TARGET_IS_SPARC64 define. Add GSR register.
	(REGISTER_BYTE64, REGISTER_RAW_SIZE64): Define like REGISTER_BYTE
	or REGISTER_RAW_SIZE, only for gdb supporting both architectures
	point at full 64bit register for general and special registers.
	* config/sparc/tm-sparc.h (is_sparc64): Define to constant 0.
	(REGISTER_BYTE64, REGISTER_RAW_SIZE64): Define to REGISTER_BYTE
	resp. REGISTER_RAW_SIZE as it is the same for 32bit only debugging.
	* sparc-tdep.c (everywhere): Use is_sparc64 expression instead of
	GDB_TARGET_IS_SPARC64 define where needed.
	(sparc_target_architecture_hook): Set gdb_is_sparc64 variable
	for GDB_TARGET_IS_SPARC_BI_ARCH from bfd information.

--- gdb/config/sparc/tm-linux.h.jj	Tue Dec  7 04:56:12 1999
+++ gdb/config/sparc/tm-linux.h	Fri Mar 17 16:09:14 2000
@@ -1,5 +1,5 @@
 /* Macro definitions for GDB for a Sparc running Linux.
-   Copyright 1989, 1992, 1994, 1995, 1998 Free Software Foundation, Inc.
+   Copyright 1989, 1992, 1994, 1995, 1998, 2000 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -26,5 +26,32 @@
 #define SIGCONTEXT_PC_OFFSET 12
 
 #include "tm-linux.h"
+
+/* Work-around for asm/sigcontext.h and asm/elf.h < 2.4 deficiencies */
+#include <features.h>
+
+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
+
+#include <signal.h>
+#include <sys/procfs.h>
+
+#undef	PTRACE_GETREGS  /* possible noise from <asm/ptrace.h> */
+#undef	PTRACE_SETREGS
+#undef	PTRACE_GETFPREGS
+#undef	PTRACE_SETFPREGS
+#undef	PT_DETACH
+
+#include <sys/ptrace.h>
+
+#undef  PT_DETACH
+#define PT_DETACH       	PTRACE_SUNDETACH
+#ifndef PTRACE_READTEXT
+#define PTRACE_READTEXT		18
+#define PTRACE_WRITETEXT	19
+#define PTRACE_READDATA		18
+#define PTRACE_WRITEDATA	17
+#endif
+
+#endif /* glibc 2.0, 2.1 */
 
 #endif /* TM_SPARCLINUX_H */
--- gdb/config/sparc/nm-linux.h.jj	Tue Dec  7 04:56:12 1999
+++ gdb/config/sparc/nm-linux.h	Fri Mar 17 16:09:14 2000
@@ -1,5 +1,5 @@
 /* Macro definitions for running gdb on a Sparc running Linux.
-   Copyright (C) 1989, 1992, 1996, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1989, 1992, 1996, 1998, 2000 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -22,8 +22,5 @@
 #include "solib.h"
 
 #define FETCH_INFERIOR_REGISTERS
-
-/* Return sizeof user struct to callers in less machine dependent routines */
-
-#define KERNEL_U_SIZE kernel_u_size()
-extern int kernel_u_size PARAMS ((void));
+#define CHILD_XFER_MEMORY
+#undef USE_PROC_FS
--- gdb/config/sparc/linux.mh.jj	Tue Dec  7 04:56:12 1999
+++ gdb/config/sparc/linux.mh	Fri Mar 17 16:09:14 2000
@@ -2,7 +2,7 @@
 XDEPFILES= ser-tcp.o
 XM_FILE= xm-linux.h
 NAT_FILE= nm-linux.h
-NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o sparc-nat.o \
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o sparc-linux-nat.o \
 	linux-thread.o
 HOST_IPC=-DBSD_IPC
 GDBSERVER_DEPFILES= low-sparc.o
--- gdb/config/sparc/linux64.mh.jj	Fri Mar 17 09:47:38 2000
+++ gdb/config/sparc/linux64.mh	Fri Mar 17 16:09:14 2000
@@ -0,0 +1,8 @@
+# Host: UltraSPARC, running Linux 64bit programs
+XDEPFILES= ser-tcp.o
+XM_FILE= xm-linux64.h
+NAT_FILE= nm-linux64.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o sparc-linux-nat.o \
+	linux-thread.o
+HOST_IPC=-DBSD_IPC
+GDBSERVER_DEPFILES= low-sparc.o
--- gdb/config/sparc/linux64.mt.jj	Fri Mar 17 09:49:23 2000
+++ gdb/config/sparc/linux64.mt	Fri Mar 17 16:09:14 2000
@@ -0,0 +1,3 @@
+# Target: UltraSPARC, running Linux 64bit programs
+TDEPFILES= sparc-tdep.o solib.o
+TM_FILE= tm-linux64.h
--- gdb/config/sparc/nm-linux64.h.jj	Fri Mar 17 09:51:15 2000
+++ gdb/config/sparc/nm-linux64.h	Fri Mar 17 16:09:14 2000
@@ -0,0 +1,28 @@
+/* Macro definitions for running gdb on a UltraSPARC running Linux.
+   Copyright (C) 1989, 1992, 1996, 1998, 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 <nm-sysv4.h>
+#include "solib.h"
+
+#define FETCH_INFERIOR_REGISTERS
+#define CHILD_XFER_MEMORY
+#undef USE_PROC_FS
+#define PTRACE_ARG3_TYPE long
+#define PTRACE_XFER_TYPE long
--- gdb/config/sparc/tm-linux64.h.jj	Fri Oct 29 12:23:12 1999
+++ gdb/config/sparc/tm-linux64.h	Fri Mar 17 16:09:14 2000
@@ -0,0 +1,37 @@
+/* Macro definitions for GDB for a UltraSparc running Linux.
+   Copyright 1989, 1992, 1994, 1995, 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.  */
+
+#ifndef TM_SPARCLINUX64_H
+#define TM_SPARCLINUX64_H
+
+#define GDB_TARGET_IS_SPARC_BI_ARCH
+
+#include "sparc/tm-sp64.h"
+
+#define SIGCONTEXT_PC_OFFSET 16  /* See asm-sparc64/sigcontext.h */
+
+/* We always want full V9 + Ultra VIS stuff... */
+#undef TM_PRINT_INSN_MACH
+#define TM_PRINT_INSN_MACH bfd_mach_sparc_v9a
+
+#define GDB_PTRACE_REGS64
+
+#include "tm-sysv4.h"
+
+#endif /* TM_SPARCLINUX64_H */
--- gdb/config/sparc/tm-sp64.h.jj	Tue Aug 31 03:08:02 1999
+++ gdb/config/sparc/tm-sp64.h	Fri Mar 17 16:09:14 2000
@@ -1,6 +1,6 @@
 /* Target machine sub-parameters for SPARC64, for GDB, the GNU debugger.
    This is included by other tm-*.h files to define SPARC64 cpu-related info.
-   Copyright 1994, 1995, 1996, 1998 Free Software Foundation, Inc.
+   Copyright 1994, 1995, 1996, 1998, 2000 Free Software Foundation, Inc.
    This is (obviously) based on the SPARC Vn (n<9) port.
    Contributed by Doug Evans (dje@cygnus.com).
    Further modified by Bob Manson (manson@cygnus.com).
@@ -22,6 +22,12 @@
    Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#ifdef GDB_TARGET_IS_SPARC_BI_ARCH
+#define is_sparc64 gdb_is_sparc64
+#else
+#define is_sparc64 1
+#endif
+
 #define GDB_TARGET_IS_SPARC64
 
 struct value;
@@ -102,12 +108,12 @@ struct value;
    function calls. */
 
 #undef  STACK_ALIGN
-#define STACK_ALIGN(ADDR) (((ADDR) + 15 ) & -16)
+#define STACK_ALIGN(ADDR) (is_sparc64 ? (((ADDR) + 15) & -16L) : (((ADDR) + 7) & 0xfffffff8))
 
 /* Number of machine registers.  */
 
 #undef  NUM_REGS
-#define NUM_REGS 125
+#define NUM_REGS 126
 
 /* Initializer for an array of names of registers.
    There should be NUM_REGS strings in this initializer.  */
@@ -141,6 +147,7 @@ struct value;
   "ver", "tick", "pil", "pstate",				\
   "tstate", "tba", "tl", "tt", "tpc", "tnpc", "wstate",		\
   "cwp", "cansave", "canrestore", "cleanwin", "otherwin",	\
+  "gsr",							\
   "asr16", "asr17", "asr18", "asr19", "asr20", "asr21",		\
   "asr22", "asr23", "asr24", "asr25", "asr26", "asr27",		\
   "asr28", "asr29", "asr30", "asr31",				\
@@ -185,6 +192,12 @@ struct value;
 #undef FPS_REGNUM
 #undef CPS_REGNUM
 
+/* #undef dummy regs */
+
+#undef PSTATE_REGNUM
+#undef TPC_REGNUM
+#undef TNPC_REGNUM
+
 /* v9 misc. and priv. regs */
 
 #define C0_REGNUM FP_MAX_REGNUM	/* Start of control registers */
@@ -192,6 +205,7 @@ struct value;
 #define NPC_REGNUM (C0_REGNUM + 1)	/* Next PC */
 #define CCR_REGNUM (C0_REGNUM + 2)	/* Condition Code Register (%xcc,%icc) */
 #define FSR_REGNUM (C0_REGNUM + 3)	/* Floating Point State */
+#define FPS_REGNUM FSR_REGNUM
 #define FPRS_REGNUM (C0_REGNUM + 4)	/* Floating Point Registers State */
 #define	Y_REGNUM (C0_REGNUM + 5)	/* Temp register for multiplication, etc.  */
 #define ASI_REGNUM (C0_REGNUM + 6)	/* Alternate Space Identifier */
@@ -199,38 +213,51 @@ struct value;
 #define TICK_REGNUM (C0_REGNUM + 8)	/* Tick register */
 #define PIL_REGNUM (C0_REGNUM + 9)	/* Processor Interrupt Level */
 #define PSTATE_REGNUM (C0_REGNUM + 10)	/* Processor State */
+#define PS_REGNUM PSTATE_REGNUM
 #define TSTATE_REGNUM (C0_REGNUM + 11)	/* Trap State */
 #define TBA_REGNUM (C0_REGNUM + 12)	/* Trap Base Address */
+#define TBR_REGNUM TBA_REGNUM
 #define TL_REGNUM (C0_REGNUM + 13)	/* Trap Level */
 #define TT_REGNUM (C0_REGNUM + 14)	/* Trap Type */
 #define TPC_REGNUM (C0_REGNUM + 15)	/* Trap pc */
 #define TNPC_REGNUM (C0_REGNUM + 16)	/* Trap npc */
 #define WSTATE_REGNUM (C0_REGNUM + 17)	/* Window State */
 #define CWP_REGNUM (C0_REGNUM + 18)	/* Current Window Pointer */
+#define WIM_REGNUM CWP_REGNUM
 #define CANSAVE_REGNUM (C0_REGNUM + 19)		/* Savable Windows */
 #define CANRESTORE_REGNUM (C0_REGNUM + 20)	/* Restorable Windows */
 #define CLEANWIN_REGNUM (C0_REGNUM + 21)	/* Clean Windows */
 #define OTHERWIN_REGNUM (C0_REGNUM + 22)	/* Other Windows */
-#define ASR_REGNUM(n) (C0_REGNUM+(23-16)+(n))	/* Ancillary State Register
+#define GSR_REGNUM (C0_REGNUM + 23)		/* Graphic State Register */
+#define ASR_REGNUM(n) (C0_REGNUM+(24-16)+(n))	/* Ancillary State Register
 						   (n = 16...31) */
-#define ICC_REGNUM (C0_REGNUM + 39)	/* 32 bit condition codes */
-#define XCC_REGNUM (C0_REGNUM + 40)	/* 64 bit condition codes */
-#define FCC0_REGNUM (C0_REGNUM + 41)	/* fp cc reg 0 */
-#define FCC1_REGNUM (C0_REGNUM + 42)	/* fp cc reg 1 */
-#define FCC2_REGNUM (C0_REGNUM + 43)	/* fp cc reg 2 */
-#define FCC3_REGNUM (C0_REGNUM + 44)	/* fp cc reg 3 */
+#define CPS_REGNUM ASR_REGNUM(31)
+#define ICC_REGNUM (C0_REGNUM + 40)	/* 32 bit condition codes */
+#define XCC_REGNUM (C0_REGNUM + 41)	/* 64 bit condition codes */
+#define FCC0_REGNUM (C0_REGNUM + 42)	/* fp cc reg 0 */
+#define FCC1_REGNUM (C0_REGNUM + 43)	/* fp cc reg 1 */
+#define FCC2_REGNUM (C0_REGNUM + 44)	/* fp cc reg 2 */
+#define FCC3_REGNUM (C0_REGNUM + 45)	/* fp cc reg 3 */
 
 /* Total amount of space needed to store our copies of the machine's
    register state, the array `registers'.
    Some of the registers aren't 64 bits, but it's a lot simpler just to assume
    they all are (since most of them are).  */
 #undef  REGISTER_BYTES
-#define REGISTER_BYTES (32*8+32*8+45*8)
+#define REGISTER_BYTES (32*8+32*8+46*8)
 
 /* Index within `registers' of the first byte of the space for
    register N.  */
 #undef  REGISTER_BYTE
 #define REGISTER_BYTE(N) \
+  ((N) < 32 ? (N)*8 + (is_sparc64 ? 0 : 4)	\
+   : (N) < 64 ? 32*8 + ((N)-32)*4		\
+   : (N) < C0_REGNUM ? 32*8 + 32*4 + ((N)-64)*8	\
+   : 64*8 + ((N)-C0_REGNUM)*8 + (is_sparc64 ? 0 : 4))
+
+/* The same but even for 32bit process work with 64bit register N.  */
+#undef REGISTER_BYTE64
+#define REGISTER_BYTE64(N) \
   ((N) < 32 ? (N)*8				\
    : (N) < 64 ? 32*8 + ((N)-32)*4		\
    : (N) < C0_REGNUM ? 32*8 + 32*4 + ((N)-64)*8	\
@@ -248,14 +275,21 @@ struct value;
 
 #undef  REGISTER_RAW_SIZE
 #define REGISTER_RAW_SIZE(N) \
-  ((N) < 32 ? 8 : (N) < 64 ? 4 : 8)
+  (is_sparc64 ?				\
+   ((N) < 32 ? 8 : (N) < 64 ? 4 : 8)	\
+   : (((N) >= 64 && (N) < C0_REGNUM) ? 8 : 4))
+
+/* The same but even for 32bit process work with 64bit register N.  */
+#undef REGISTER_RAW_SIZE64
+#define REGISTER_RAW_SIZE64(N) \
+   ((N) < 32 ? 8 : (N) < 64 ? 4 : 8)
 
 /* Number of bytes of storage in the program's representation
    for register N.  */
 
 #undef  REGISTER_VIRTUAL_SIZE
 #define REGISTER_VIRTUAL_SIZE(N) \
-  ((N) < 32 ? 8 : (N) < 64 ? 4 : 8)
+  REGISTER_RAW_SIZE(N)
 
 /* Largest value REGISTER_RAW_SIZE can have.  */
 /* tm-sparc.h defines this as 8, but play it safe.  */
@@ -274,19 +308,22 @@ struct value;
 
 #undef  REGISTER_VIRTUAL_TYPE
 #define REGISTER_VIRTUAL_TYPE(N) \
- ((N) < 32 ? builtin_type_long_long \
+ ((N) < 32 ? (is_sparc64 ? builtin_type_long_long : builtin_type_int) \
   : (N) < 64 ? builtin_type_float \
   : (N) < 80 ? builtin_type_double \
-  : builtin_type_long_long)
+  : (is_sparc64 ? builtin_type_long_long : builtin_type_int))
 
-/* We use to support both 32 bit and 64 bit pointers.
-   We can't anymore because TARGET_PTR_BIT must now be a constant.  */
+/* We use this to support both 32 bit and 64 bit pointers.  */
 #undef  TARGET_PTR_BIT
-#define TARGET_PTR_BIT 64
+#define TARGET_PTR_BIT (is_sparc64 ? 64 : 32)
+
+/* The above will be at most 64 bits.  This must be a constant.  */
+#undef  TARGET_MAX_PTR_BIT
+#define TARGET_MAX_PTR_BIT 64
 
 /* Longs are 64 bits. */
 #undef TARGET_LONG_BIT
-#define TARGET_LONG_BIT 64
+#define TARGET_LONG_BIT (is_sparc64 ? 64 : 32)
 
 #undef TARGET_LONG_LONG_BIT
 #define TARGET_LONG_LONG_BIT 64
@@ -308,23 +345,28 @@ struct value;
 
 
 #undef  USE_STRUCT_CONVENTION
-#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 32)
+#define USE_STRUCT_CONVENTION(gcc_p, type) \
+ (is_sparc64 ? TYPE_LENGTH (type) > 32 \
+  : generic_use_struct_convention (gcc_p, type))
 
 #undef REG_STRUCT_HAS_ADDR
-#define REG_STRUCT_HAS_ADDR(gcc_p,type) (TYPE_LENGTH (type) > 32)
+#define REG_STRUCT_HAS_ADDR(gcc_p,type) (is_sparc64 ? TYPE_LENGTH (type) > 32 : gcc_p != 1)
 
 /* Store the address of the place in which to copy the structure the
    subroutine will return.  This is called from call_function. */
 /* FIXME: V9 uses %o0 for this.  */
 
+#if 0
+/* FIXME!!! */
 #undef  STORE_STRUCT_RETURN
 #define STORE_STRUCT_RETURN(ADDR, SP) \
   { target_write_memory ((SP)+(16*8), (char *)&(ADDR), 8); }
+#endif
 
 /* Return number of bytes at start of arglist that are not really args.  */
 
 #undef  FRAME_ARGS_SKIP
-#define FRAME_ARGS_SKIP 136
+#define FRAME_ARGS_SKIP (is_sparc64 ? 136 : 68)
 
 /* Offsets into jmp_buf.
    FIXME: This was borrowed from the v8 stuff and will probably have to change
--- gdb/config/sparc/tm-sparc.h.jj	Tue Feb 22 20:18:53 2000
+++ gdb/config/sparc/tm-sparc.h	Fri Mar 17 16:09:14 2000
@@ -1,6 +1,6 @@
 /* Target machine sub-parameters for SPARC, for GDB, the GNU debugger.
    This is included by other tm-*.h files to define SPARC cpu-related info.
-   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 2000
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@mcc.com)
 
@@ -25,6 +25,11 @@ struct frame_info;
 struct type;
 struct value;
 
+extern int gdb_is_sparc64;
+#ifndef is_sparc64
+#define is_sparc64 0
+#endif
+
 #define TARGET_BYTE_ORDER BIG_ENDIAN
 
 /* Floating point is IEEE compatible.  */
@@ -181,6 +186,13 @@ extern CORE_ADDR sparc_pc_adjust PARAMS 
 #define	FPS_REGNUM 70		/* Floating point status register */
 #define	CPS_REGNUM 71		/* Coprocessor status register */
 
+/* These are just to get sparc-linux-nat.c to compile without too many ifdefs.
+   Code using these will never be executed for 32bit binaries.  */
+#define PSTATE_REGNUM 0
+#define TPC_REGNUM 0
+#define TNPC_REGNUM 0
+
+
 /* Total amount of space needed to store our copies of the machine's
    register state, the array `registers'.  On the sparc, `registers'
    contains the ins and locals, even though they are saved on the
@@ -198,6 +210,7 @@ extern CORE_ADDR sparc_pc_adjust PARAMS 
    register N.  */
 /* ?? */
 #define REGISTER_BYTE(N)  ((N)*4)
+#define REGISTER_BYTE64(N) REGISTER_BYTE(N)
 
 /* We need to override GET_SAVED_REGISTER so that we can deal with the way
    outs change into ins in different frames.  HAVE_REGISTER_WINDOWS can't
@@ -214,6 +227,7 @@ void sparc_get_saved_register PARAMS ((c
 /* On the SPARC, all regs are 4 bytes.  */
 
 #define REGISTER_RAW_SIZE(N) (4)
+#define REGISTER_RAW_SIZE64(N) REGISTER_RAW_SIZE(N)
 
 /* Number of bytes of storage in the program's representation
    for register N.  */
--- gdb/config/sparc/xm-linux64.h.jj	Fri Oct 29 12:23:12 1999
+++ gdb/config/sparc/xm-linux64.h	Fri Mar 17 16:09:14 2000
@@ -0,0 +1,38 @@
+/* Macro definitions for running gdb on a Sparc running Linux.
+   Copyright (C) 1989, 1993, 1994, 1995, 1996, 1998, 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.  */
+
+#ifndef XM_SPARCLINUX64_H
+#define XM_SPARCLINUX64_H
+
+#include "sparc/xm-sparc.h"
+
+#define HAVE_TERMIOS
+/* 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
+
+#define U_REGS_OFFSET 0
+
+#define NEED_POSIX_SETPGID
+
+/* Need R_OK etc, but USG isn't defined.  */
+#include <unistd.h>
+
+#endif /* _XM_SPARCLINUX64_H */
--- gdb/sparc-nat.c.jj	Wed Oct  6 01:08:51 1999
+++ gdb/sparc-nat.c	Fri Mar 17 16:09:14 2000
@@ -26,11 +26,7 @@
 #include <signal.h>
 #include <sys/ptrace.h>
 #include <sys/wait.h>
-#ifdef __linux__
-#include <asm/reg.h>
-#else
 #include <machine/reg.h>
-#endif
 #include <sys/user.h>
 
 /* We don't store all registers immediately when requested, since they
--- gdb/defs.h.jj	Mon Mar 13 18:13:42 2000
+++ gdb/defs.h	Fri Mar 17 16:09:14 2000
@@ -1012,6 +1012,11 @@ extern char *alloca ();
 #define TARGET_BFD_VMA_BIT TARGET_PTR_BIT
 #endif
 
+/* Maximum possible value of the above (must be constant). */
+#if !defined (TARGET_MAX_PTR_BIT)
+#define TARGET_MAX_PTR_BIT TARGET_PTR_BIT
+#endif
+
 /* If we picked up a copy of CHAR_BIT from a configuration file
    (which may get it by including <limits.h>) then use it to set
    the number of bits in a host char.  If not, use the same size
--- gdb/sparc-linux-nat.c.jj	Fri Mar 17 08:37:50 2000
+++ gdb/sparc-linux-nat.c	Fri Mar 17 16:23:01 2000
@@ -0,0 +1,581 @@
+/* Functions specific to running gdb native on a SPARC running Linux.
+   Copyright 1989, 1992, 1993, 1994, 1996, 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"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcore.h"
+
+#include <signal.h>
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include <asm/reg.h>
+#include <sys/user.h>
+#include <sys/syscall.h>
+
+/* We don't store all registers immediately when requested, since they
+   get sent over in large chunks anyway.  Instead, we accumulate most
+   of the changes and send them over once.  "deferred_stores" keeps
+   track of which sets of registers we have locally-changed copies of,
+   so we only need send the groups that have changed.  */
+
+#define	INT_REGS	1
+#define	STACK_REGS	2
+#define	FP_REGS		4
+
+/* libc passes only 4 arguments to the kernel, while for
+   READTEXT/WRITETEXT/READDATA/WRITEDATA we need 5.  */
+
+int
+ptrace5(request, pid, taskaddr, len, addr)
+     int request, pid;
+     unsigned long taskaddr;
+     int len;
+     char *addr;
+{
+  return syscall(SYS_ptrace, request, pid, taskaddr, len, addr);
+}
+
+int
+child_xfer_memory (memaddr, myaddr, len, write, target)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+     struct target_ops *target ATTRIBUTE_UNUSED;
+{
+  errno = 0;
+  if (write)
+    ptrace5 (PTRACE_WRITETEXT, PIDGET(inferior_pid),
+	     (unsigned long)memaddr, len, myaddr);
+  else
+    ptrace5 (PTRACE_READTEXT, PIDGET(inferior_pid),
+	     (unsigned long)memaddr, len, myaddr);
+  if (errno)
+    return 0;
+
+  return len;
+}
+
+static void
+fetch_core_registers PARAMS ((char *, unsigned int, int, CORE_ADDR));
+
+/* Fetch one or more registers from the inferior.  REGNO == -1 to get
+   them all.  We actually fetch more than requested, when convenient,
+   marking them as valid so we won't fetch them again.  */
+
+void
+fetch_inferior_registers (regno)
+     int regno;
+{
+  struct regs inferior_registers;
+  struct fp_status inferior_fp_registers;
+  int i;
+
+  /* We should never be called with deferred stores, because a prerequisite
+     for writing regs is to have fetched them all (PREPARE_TO_STORE), sigh.  */
+  if (deferred_stores)
+    abort ();
+
+  DO_DEFERRED_STORES;
+
+  /* Global and Out regs are fetched directly, as well as the control
+     registers.  If we're getting one of the in or local regs,
+     and the stack pointer has not yet been fetched,
+     we have to do that first, since they're found in memory relative
+     to the stack pointer.  */
+  if (regno < O7_REGNUM		/* including -1 */
+#ifdef GDB_PTRACE_REGS64
+      || regno >= PC_REGNUM
+#else
+      || regno >= Y_REGNUM
+#endif
+      || (!register_valid[SP_REGNUM] && regno < I7_REGNUM))
+    {
+      if (0 != ptrace (PTRACE_GETREGS, inferior_pid,
+		       (PTRACE_ARG3_TYPE) & inferior_registers, 0))
+	perror ("ptrace_getregs");
+
+      *(long *)&registers[REGISTER_BYTE64 (G0_REGNUM)] = 0;
+      memcpy (&registers[REGISTER_BYTE64 (G1_REGNUM)], &inferior_registers.r_g1,
+	      15 * REGISTER_RAW_SIZE64 (G1_REGNUM));
+#ifdef GDB_PTRACE_REGS64
+      *(long *)&registers[REGISTER_BYTE64 (PSTATE_REGNUM)] = (inferior_registers.r_tstate >> 8) & 0x3ff;
+      *(long *)&registers[REGISTER_BYTE64 (CCR_REGNUM)] = (inferior_registers.r_tstate >> 32) & 0xff;
+      *(long *)&registers[REGISTER_BYTE64 (ASI_REGNUM)] = (inferior_registers.r_tstate >> 24) & 0xff;
+      *(long *)&registers[REGISTER_BYTE64 (CWP_REGNUM)] = inferior_registers.r_tstate & 0x1f;
+      *(long *)&registers[REGISTER_BYTE64 (PC_REGNUM)] = inferior_registers.r_tpc;
+      *(long *)&registers[REGISTER_BYTE64 (NPC_REGNUM)] = inferior_registers.r_tnpc;
+      *(long *)&registers[REGISTER_BYTE64 (FPRS_REGNUM)] = inferior_registers.r_fprs;
+#else
+      *(long *) &registers[REGISTER_BYTE64 (PS_REGNUM)] = inferior_registers.r_ps;
+      *(long *) &registers[REGISTER_BYTE64 (PC_REGNUM)] = inferior_registers.r_pc;
+      *(long *) &registers[REGISTER_BYTE64 (NPC_REGNUM)] = inferior_registers.r_npc;
+#endif
+      *(long *) &registers[REGISTER_BYTE64 (Y_REGNUM)] = inferior_registers.r_y;
+
+      for (i = G0_REGNUM; i <= O7_REGNUM; i++)
+	register_valid[i] = 1;
+      register_valid[Y_REGNUM] = 1;
+#ifdef GDB_PTRACE_REGS64
+      register_valid[PSTATE_REGNUM] = 1;
+      register_valid[CCR_REGNUM] = 1;
+      register_valid[ASI_REGNUM] = 1;
+      register_valid[CWP_REGNUM] = 1;
+      register_valid[FPRS_REGNUM] = 1;
+#else
+      register_valid[PS_REGNUM] = 1;
+#endif
+      register_valid[PC_REGNUM] = 1;
+      register_valid[NPC_REGNUM] = 1;
+#ifdef GDB_PTRACE_REGS64
+      /* XXX Lie for now.  */
+      for(i = ASI_REGNUM; i < NUM_REGS; i++)
+	register_valid[i] = 1;
+#else
+      /* If we don't set these valid, read_register_bytes() rereads
+         all the regs every time it is called!  FIXME.  */
+      register_valid[WIM_REGNUM] = 1;	/* Not true yet, FIXME */
+      register_valid[TBR_REGNUM] = 1;	/* Not true yet, FIXME */
+      register_valid[CPS_REGNUM] = 1;	/* Not true yet, FIXME */
+#endif
+    }
+
+  /* Floating point registers */
+  if (regno == -1 ||
+      regno == FPS_REGNUM ||
+      (regno >= FP0_REGNUM && regno <= FP0_REGNUM + 31))
+    {
+      if (0 != ptrace (PTRACE_GETFPREGS, inferior_pid,
+		       (PTRACE_ARG3_TYPE) & inferior_fp_registers,
+		       0))
+	perror ("ptrace_getfpregs");
+      memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+	      sizeof inferior_fp_registers.fpu_fr);
+      memcpy (&registers[REGISTER_BYTE64 (FPS_REGNUM)],
+	      &inferior_fp_registers.Fpu_fsr,
+	      sizeof (FPU_FSR_TYPE));
+#ifdef GDB_PTRACE_REGS64
+      for (i = FP0_REGNUM; i <= FP0_REGNUM + 63; i++)
+	register_valid[i] = 1;
+#else
+      for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
+	register_valid[i] = 1;
+#endif
+      register_valid[FPS_REGNUM] = 1;
+    }
+
+  /* These regs are saved on the stack by the kernel.  Only read them
+     all (16 ptrace calls!) if we really need them.  */
+  if (regno == -1)
+    {
+      CORE_ADDR sp = *(CORE_ADDR *) & registers[REGISTER_BYTE64 (SP_REGNUM)];
+      if (is_sparc64 && (sp & 1))
+	sp += 2047;
+#ifdef GDB_TARGET_IS_SPARC_BI_ARCH
+      if (!is_sparc64)
+	{
+	  unsigned int buf[16];
+
+	  target_read_memory (sp & 0xffffffffU, (char *)buf, 16 * 4);
+	  for (i = 0; i < 16; i++)
+	    *(long *)&registers[REGISTER_BYTE64 (L0_REGNUM + i)] = buf[i];
+	}
+      else
+#endif
+	target_read_memory (sp, &registers[REGISTER_BYTE (L0_REGNUM)],
+			    16 * REGISTER_RAW_SIZE (L0_REGNUM));
+      for (i = L0_REGNUM; i <= I7_REGNUM; i++)
+	register_valid[i] = 1;
+    }
+  else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+    {
+      CORE_ADDR sp = *(CORE_ADDR *) & registers[REGISTER_BYTE64 (SP_REGNUM)];
+      if (is_sparc64 && (sp & 1))
+	sp += 2047;
+      i = REGISTER_BYTE (regno);
+      if (register_valid[regno])
+	printf_unfiltered ("register %d valid and read\n", regno);
+#ifdef GDB_TARGET_IS_SPARC_BI_ARCH
+      if (!is_sparc64)
+	{
+	  target_read_memory (sp + (regno - L0_REGNUM) * 4,
+			      &registers[i], REGISTER_RAW_SIZE64 (regno));
+	  *(int *)&registers[i-4] = 0;
+	}
+      else
+#endif
+	target_read_memory (sp + i - REGISTER_BYTE (L0_REGNUM),
+			    &registers[i], REGISTER_RAW_SIZE (regno));
+      register_valid[regno] = 1;
+    }
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+void
+store_inferior_registers (regno)
+     int regno;
+{
+  struct regs inferior_registers;
+  struct fp_status inferior_fp_registers;
+  int wanna_store = INT_REGS + STACK_REGS + FP_REGS;
+
+  /* First decide which pieces of machine-state we need to modify.  
+     Default for regno == -1 case is all pieces.  */
+  if (regno >= 0)
+    {
+#ifdef GDB_PTRACE_REGS64
+      if (FP0_REGNUM <= regno && regno < FP0_REGNUM + 64)
+#else
+      if (FP0_REGNUM <= regno && regno < FP0_REGNUM + 32)
+#endif
+	{
+	  wanna_store = FP_REGS;
+	}
+      else
+	{
+	  if (regno == SP_REGNUM)
+	    wanna_store = INT_REGS + STACK_REGS;
+	  else if (regno < L0_REGNUM || regno > I7_REGNUM)
+	    wanna_store = INT_REGS;
+	  else if (regno == FPS_REGNUM)
+	    wanna_store = FP_REGS;
+	  else
+	    wanna_store = STACK_REGS;
+	}
+    }
+
+  /* See if we're forcing the stores to happen now, or deferring. */
+  if (regno == -2)
+    {
+      wanna_store = deferred_stores;
+      deferred_stores = 0;
+    }
+  else
+    {
+      if (wanna_store == STACK_REGS)
+	{
+	  /* Fall through and just store one stack reg.  If we deferred
+	     it, we'd have to store them all, or remember more info.  */
+	}
+      else
+	{
+	  deferred_stores |= wanna_store;
+	  return;
+	}
+    }
+
+  if (wanna_store & STACK_REGS)
+    {
+      CORE_ADDR sp = *(CORE_ADDR *) & registers[REGISTER_BYTE64 (SP_REGNUM)];
+
+      if (is_sparc64 && (sp & 1))
+	sp += 2047;
+
+      if (regno < 0 || regno == SP_REGNUM)
+	{
+	  if (!register_valid[L0_REGNUM + 5])
+	    abort ();
+#ifdef GDB_TARGET_IS_SPARC_BI_ARCH
+	  if (!is_sparc64)
+	    {
+	      unsigned int buf[16];
+	      int i;
+	      
+	      for (i = 0; i < 16; i++)
+		buf[i] = *(int *)&registers[REGISTER_BYTE (L0_REGNUM + i)];
+	      target_write_memory (sp & 0xffffffffU, (char *)buf, 16 * 4);
+	    }
+	  else
+#endif
+	    target_write_memory (sp,
+				 &registers[REGISTER_BYTE (L0_REGNUM)],
+				 16 * REGISTER_RAW_SIZE (L0_REGNUM));
+	}
+      else
+	{
+	  if (!register_valid[regno])
+	    abort ();
+#ifdef GDB_TARGET_IS_SPARC_BI_ARCH
+	  if (!is_sparc64)
+	    target_write_memory (sp + (regno - L0_REGNUM) * 4,
+				 &registers[REGISTER_BYTE (regno)], 4);
+	  else
+#endif
+	    target_write_memory (sp + REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM),
+				 &registers[REGISTER_BYTE (regno)],
+				 REGISTER_RAW_SIZE (regno));
+	}
+
+    }
+
+  if (wanna_store & INT_REGS)
+    {
+      if (!register_valid[G1_REGNUM])
+	abort ();
+
+      memcpy (&inferior_registers.r_g1, &registers[REGISTER_BYTE64 (G1_REGNUM)],
+	      15 * REGISTER_RAW_SIZE64 (G1_REGNUM));
+
+#ifdef GDB_PTRACE_REGS64
+      inferior_registers.r_tstate =
+        ((*(long *) &registers[REGISTER_BYTE64 (CWP_REGNUM)]) & 0x1f) |
+        (((*(long *) &registers[REGISTER_BYTE64 (PSTATE_REGNUM)]) & 0x3ff) << 8) |
+        (((*(long *) &registers[REGISTER_BYTE64 (ASI_REGNUM)]) & 0xff) << 24) |
+        (((*(long *) &registers[REGISTER_BYTE64 (CCR_REGNUM)]) & 0xff) << 32);
+      inferior_registers.r_tpc =
+	*(long *) &registers[REGISTER_BYTE64 (PC_REGNUM)];
+      inferior_registers.r_tnpc =
+	*(long *) &registers[REGISTER_BYTE64 (NPC_REGNUM)];
+#else
+      inferior_registers.r_ps =
+	*(long *) &registers[REGISTER_BYTE (PS_REGNUM)];
+      inferior_registers.r_pc =
+	*(long *) &registers[REGISTER_BYTE (PC_REGNUM)];
+      inferior_registers.r_npc =
+	*(long *) &registers[REGISTER_BYTE (NPC_REGNUM)];
+#endif
+      inferior_registers.r_y =
+	*(long *) &registers[REGISTER_BYTE64 (Y_REGNUM)];
+
+      if (0 != ptrace (PTRACE_SETREGS, inferior_pid,
+		       (PTRACE_ARG3_TYPE) & inferior_registers, 0))
+	perror ("ptrace_setregs");
+    }
+
+  if (wanna_store & FP_REGS)
+    {
+      if (!register_valid[FP0_REGNUM + 9])
+	abort ();
+      memcpy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+	      sizeof inferior_fp_registers.fpu_fr);
+      memcpy (&inferior_fp_registers.Fpu_fsr,
+	      &registers[REGISTER_BYTE64 (FPS_REGNUM)], sizeof (FPU_FSR_TYPE));
+      if (0 !=
+	  ptrace (PTRACE_SETFPREGS, inferior_pid,
+		  (PTRACE_ARG3_TYPE) & inferior_fp_registers, 0))
+	perror ("ptrace_setfpregs");
+    }
+}
+
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, ignore)
+     char *core_reg_sect;
+     unsigned core_reg_size;
+     int which;
+     CORE_ADDR ignore ATTRIBUTE_UNUSED; /* reg addr, unused in this version */
+{
+    if (which == 0) {
+
+      /* Integer registers */
+
+#if !defined (GDB_TARGET_IS_SPARC64)
+#define gregs ((struct regs *)core_reg_sect)
+#else
+      struct sparc_core_regs32 {
+	unsigned int r_psr, r_pc, r_npc, r_y;
+	unsigned int r_g1, r_g2, r_g3, r_g4, r_g5, r_g6, r_g7;
+	unsigned int r_o0, r_o1, r_o2, r_o4, r_o5, r_o6, r_o7;
+      };
+#define gregs ((struct sparc_core_regs32 *)core_reg_sect)
+#define gregs64 ((struct regs *)core_reg_sect)
+#endif
+
+      /* G0 *always* holds 0.  */
+      *(long *) &registers[REGISTER_BYTE64 (G0_REGNUM)] = 0;
+
+      /* The globals and output registers.  */
+      if (!is_sparc64)
+	{
+	  if (core_reg_size == 38*sizeof(int))
+	    {
+	      /* Integer registers in Solaris-like layout (e.g. in Linux 2.1.12x+) */
+
+#ifdef GDB_TARGET_IS_SPARC_BI_ARCH
+	      int i;
+
+	      /* The globals and output registers.  */
+	      for (i = 0; i < 31; i++)
+		*(long *) &registers[REGISTER_BYTE64 (G1_REGNUM + i)] = ((int *)core_reg_sect)[i + 1];
+	      *(long *) &registers[REGISTER_BYTE64 (CWP_REGNUM)] = ((int *)core_reg_sect)[32] & 0x1f;
+	      *(long *) &registers[REGISTER_BYTE64 (CCR_REGNUM)] = (((int *)core_reg_sect)[32] >> 20) & 0xf;
+#else
+	      /* The globals and output registers.  */
+	      memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], ((int *)core_reg_sect)+1,
+	                                            31 * REGISTER_RAW_SIZE (G1_REGNUM));
+	      *(long *)&registers[REGISTER_BYTE64 (PS_REGNUM)] = ((int *)core_reg_sect)[32];
+#endif
+	      *(long *)&registers[REGISTER_BYTE64 (PC_REGNUM)] = ((int *)core_reg_sect)[33];
+	      *(long *)&registers[REGISTER_BYTE (NPC_REGNUM)] = ((int *)core_reg_sect)[34];
+	      *(long *)&registers[REGISTER_BYTE (Y_REGNUM)] = ((int *)core_reg_sect)[35];
+	      return;
+	    }
+	                                                                              
+#ifdef GDB_TARGET_IS_SPARC_BI_ARCH
+	  int i;
+
+	  for (i = 0; i < 15; i++)
+	    *(long *) &registers[REGISTER_BYTE64 (G1_REGNUM + i)] =
+	      *((&gregs->r_g1)+i);
+	  *(long *) &registers[REGISTER_BYTE64 (CWP_REGNUM)] = gregs->r_psr & 0x1f;
+	  *(long *) &registers[REGISTER_BYTE64 (CCR_REGNUM)] = (gregs->r_psr >> 20) & 0xf;
+#else	      
+	  memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &gregs->r_g1,
+	      15 * REGISTER_RAW_SIZE (G1_REGNUM));
+	  *(long *) &registers[REGISTER_BYTE (PS_REGNUM)] = gregs->r_psr;
+#endif
+	  *(long *) &registers[REGISTER_BYTE64 (PC_REGNUM)] = gregs->r_pc;
+	  *(long *) &registers[REGISTER_BYTE64 (NPC_REGNUM)] = gregs->r_npc;
+	  *(long *) &registers[REGISTER_BYTE64 (Y_REGNUM)] = gregs->r_y;
+	}
+#ifdef GDB_TARGET_IS_SPARC64
+      else
+	{
+	  memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &gregs64->r_g1,
+	      15 * REGISTER_RAW_SIZE (G1_REGNUM));
+	  *(long *)&registers[REGISTER_BYTE64 (PSTATE_REGNUM)] = (gregs64->r_tstate >> 8) & 0x3ff;
+	  *(long *)&registers[REGISTER_BYTE64 (CCR_REGNUM)] = (gregs64->r_tstate >> 32) & 0xff;
+	  *(long *)&registers[REGISTER_BYTE64 (ASI_REGNUM)] = (gregs64->r_tstate >> 24) & 0xff;
+	  *(long *)&registers[REGISTER_BYTE64 (CWP_REGNUM)] = gregs64->r_tstate & 0x1f;
+	  *(long *)&registers[REGISTER_BYTE64 (PC_REGNUM)] = gregs64->r_tpc;
+	  *(long *)&registers[REGISTER_BYTE64 (NPC_REGNUM)] = gregs64->r_tnpc;
+	  *(long *)&registers[REGISTER_BYTE64 (FPRS_REGNUM)] = gregs64->r_fprs;
+	  *(long *) &registers[REGISTER_BYTE64 (Y_REGNUM)] = gregs64->r_y;
+	}
+#endif
+
+      /* My best guess at where to get the locals and input
+         registers is exactly where they usually are, right above
+         the stack pointer.  If the core dump was caused by a bus error
+         from blowing away the stack pointer (as is possible) then this
+         won't work, but it's worth the try. */
+      {
+	long sp;
+	int ret;
+
+	sp = *(long *) &registers[REGISTER_BYTE64 (SP_REGNUM)];
+	if (is_sparc64 && (sp & 1))
+	  sp += 2047;
+#ifdef GDB_TARGET_IS_SPARC_BI_ARCH
+	if (!is_sparc64)
+	  {
+	    unsigned int buf[16];
+	    int i;
+
+	    ret = target_read_memory (sp & 0xffffffffU, (char *)buf, 16 * 4);
+	    for (i = 0; i < 16; i++)
+	      *(long *)&registers[REGISTER_BYTE64 (L0_REGNUM + i)] = buf[i];
+	  }
+	else
+#endif
+	  ret = target_read_memory (sp, &registers[REGISTER_BYTE (L0_REGNUM)],
+				    16 * REGISTER_RAW_SIZE (L0_REGNUM));
+	if (ret != 0)
+	  {
+	    /* fprintf_unfiltered so user can still use gdb */
+	    fprintf_unfiltered (gdb_stderr,
+		"Couldn't read input and local registers from core file\n");
+	  }
+      }
+    }
+  else if (which == 2)
+    {
+
+      /* Floating point registers */
+
+#if !defined (GDB_TARGET_IS_SPARC64)
+#define fpuregs  ((struct fpu *) core_reg_sect)
+      if (core_reg_size >= sizeof (struct fpu))
+	{
+	  memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], fpuregs->fpu_regs,
+		  sizeof (fpuregs->fpu_regs));
+	  memcpy (&registers[REGISTER_BYTE (FPS_REGNUM)], &fpuregs->fpu_fsr,
+		  sizeof (FPU_FSR_TYPE));
+	  return;
+	}
+#else
+      if (is_sparc64)
+	{
+	  struct sparc_core_fpu64
+	    {
+	      unsigned long fpu64_regs[32], fpu64_fsr, fpu64_gsr, fpu64_fprs;
+	    };
+#define fpuregs64 ((struct sparc_core_fpu64 *) core_reg_sect)
+	  if (core_reg_size >= sizeof (struct sparc_core_fpu64))
+	    {
+	      memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], fpuregs64->fpu64_regs,
+		      sizeof (fpuregs64->fpu64_regs));
+	      memcpy (&registers[REGISTER_BYTE (FPS_REGNUM)], &fpuregs64->fpu64_fsr,
+		      sizeof (fpuregs64->fpu64_fsr));
+	      memcpy (&registers[REGISTER_BYTE (GSR_REGNUM)], &fpuregs64->fpu64_gsr,
+		      sizeof (fpuregs64->fpu64_gsr));
+	      return;
+	    }
+	}
+      else
+	{
+	  struct sparc_core_fpu32
+	    {
+	      unsigned int fpu32_regs[32];
+	      unsigned int __unused;
+	      unsigned int fpu32_fsr;
+	      unsigned char fpu32_qcnt;
+	      unsigned char fpu32_q_entrysize;
+	      unsigned char fpu32_en;
+	      unsigned int fpu32_q[64];
+	    };
+#define fpuregs32 ((struct sparc_core_fpu32 *) core_reg_sect)
+	  if (core_reg_size >= sizeof (struct sparc_core_fpu32))
+	    {
+	      memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], fpuregs32->fpu32_regs,
+		      sizeof (fpuregs32->fpu32_regs));
+	      *(long *)&registers[REGISTER_BYTE64 (FPS_REGNUM)] = 0;
+	      memcpy (&registers[REGISTER_BYTE (FPS_REGNUM)], &fpuregs32->fpu32_fsr,
+		      sizeof (fpuregs32->fpu32_fsr));
+	      return;
+	    }
+	}
+#endif
+      fprintf_unfiltered (gdb_stderr, "Couldn't read float regs from core file\n");
+    }
+}
+
+
+/* Register that we are able to handle sparc core file formats.
+   FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns sparc_core_fns =
+{
+  bfd_target_unknown_flavour,		/* core_flavour */
+  default_check_format,			/* check_format */
+  default_core_sniffer,			/* core_sniffer */
+  fetch_core_registers,			/* core_read_registers */
+  NULL					/* next */
+};
+
+void
+_initialize_core_sparc ()
+{
+  add_core_fns (&sparc_core_fns);
+}
--- gdb/blockframe.c.jj	Wed Dec 22 22:45:03 1999
+++ gdb/blockframe.c	Fri Mar 17 16:09:14 2000
@@ -1000,7 +1000,7 @@ sigtramp_saved_pc (frame)
      struct frame_info *frame;
 {
   CORE_ADDR sigcontext_addr;
-  char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+  char buf[TARGET_MAX_PTR_BIT / TARGET_CHAR_BIT];
   int ptrbytes = TARGET_PTR_BIT / TARGET_CHAR_BIT;
   int sigcontext_offs = (2 * TARGET_INT_BIT) / TARGET_CHAR_BIT;
 
--- gdb/configure.host.jj	Wed Dec 22 22:45:03 1999
+++ gdb/configure.host	Fri Mar 17 16:09:14 2000
@@ -20,7 +20,7 @@ m88*)			gdb_host_cpu=m88k ;;
 # OBSOLETE np1)			gdb_host_cpu=gould ;;
 # OBSOLETE pyramid)		gdb_host_cpu=pyr ;;
 powerpc*)		gdb_host_cpu=powerpc ;;
-sparc64)		gdb_host_cpu=sparc ;;
+sparc*)			gdb_host_cpu=sparc ;;
 *)			gdb_host_cpu=$host_cpu ;;
 
 esac
@@ -155,6 +155,7 @@ sparc-*-solaris2*)	gdb_host=sun4sol2 ;;
 sparc-*-sunos4*)	gdb_host=sun4os4 ;;
 sparc-*-sunos5*)	gdb_host=sun4sol2 ;;
 sparc-*-*)		gdb_host=sun4os4 ;;
+sparc64-*-linux*)	gdb_host=linux64 ;;
 sparc64-*-*)		gdb_host=sun4sol2 ;;
 
 strongarm-*-*)		gdb_host=arm ;;
--- gdb/solib.c.jj	Mon Mar  6 19:04:56 2000
+++ gdb/solib.c	Fri Mar 17 16:09:14 2000
@@ -717,7 +717,7 @@ elf_locate_base ()
 #ifdef DT_MIPS_RLD_MAP
       else if (dyn_tag == DT_MIPS_RLD_MAP)
 	{
-	  char pbuf[TARGET_PTR_BIT / HOST_CHAR_BIT];
+	  char pbuf[TARGET_MAX_PTR_BIT / HOST_CHAR_BIT];
 
 	  /* DT_MIPS_RLD_MAP contains a pointer to the address
 	     of the dynamic link structure.  */
--- gdb/sparc-tdep.c.jj	Wed Oct  6 01:08:51 1999
+++ gdb/sparc-tdep.c	Fri Mar 17 16:09:14 2000
@@ -1,5 +1,5 @@
 /* Target-dependent code for the SPARC for GDB, the GNU debugger.
-   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -42,12 +42,6 @@
 #define SPARC_HAS_FPU 1
 #endif
 
-#ifdef GDB_TARGET_IS_SPARC64
-#define FP_REGISTER_BYTES (64 * 4)
-#else
-#define FP_REGISTER_BYTES (32 * 4)
-#endif
-
 /* If not defined, assume 32 bit sparc.  */
 #ifndef FP_MAX_REGNUM
 #define FP_MAX_REGNUM (FP0_REGNUM + 32)
@@ -73,6 +67,15 @@ int deferred_stores = 0;	/* Cumulates st
 
 int bi_endian = 0;
 
+/* Are we debugging 64bit code or 32bit?  */
+
+#ifdef GDB_TARGET_IS_SPARC64
+int gdb_is_sparc64 = 1;
+#else
+int gdb_is_sparc64 = 0;
+#endif
+
+#define FP_REGISTER_BYTES (is_sparc64 ? 64 * 4 : 32 * 4)
 
 /* Fetch a single instruction.  Even on bi-endian machines
    such as sparc86x, instructions are always big-endian.  */
@@ -122,10 +125,7 @@ fetch_instruction (pc)
 
 typedef enum
 {
-  Error, not_branch, bicc, bicca, ba, baa, ticc, ta,
-#ifdef GDB_TARGET_IS_SPARC64
-  done_retry
-#endif
+  Error, not_branch, bicc, bicca, ba, baa, ticc, ta, done_retry
 }
 branch_type;
 
@@ -187,13 +187,11 @@ sparc_software_single_step (ignore, inse
 	  brktrg = 1;
 	  target_insert_breakpoint (target, break_mem[2]);
 	}
-#ifdef GDB_TARGET_IS_SPARC64
       else if (br == done_retry)
 	{
 	  brktrg = 1;
 	  target_insert_breakpoint (target, break_mem[2]);
 	}
-#endif
     }
   else
     {
@@ -251,10 +249,8 @@ sparc_init_extra_frame_info (fromleaf, f
 	  /* Should we adjust for stack bias here? */
 	  get_saved_register (buf, 0, 0, fi, FP_REGNUM, 0);
 	  fi->frame = extract_address (buf, REGISTER_RAW_SIZE (FP_REGNUM));
-#ifdef GDB_TARGET_IS_SPARC64
-	  if (fi->frame & 1)
+	  if (is_sparc64 && fi->frame & 1)
 	    fi->frame += 2047;
-#endif
 
 	}
     }
@@ -292,10 +288,8 @@ sparc_init_extra_frame_info (fromleaf, f
 	      /* Overwrite the frame's address with the value in %i7.  */
 	      get_saved_register (buf, 0, 0, fi, I7_REGNUM, 0);
 	      fi->frame = extract_address (buf, REGISTER_RAW_SIZE (I7_REGNUM));
-#ifdef GDB_TARGET_IS_SPARC64
-	      if (fi->frame & 1)
+	      if (is_sparc64 && fi->frame & 1)
 		fi->frame += 2047;
-#endif
 	      /* Record where the fp got saved.  */
 	      fi->fp_addr = fi->frame + fi->sp_offset + X_SIMM13 (insn);
 
@@ -384,7 +378,7 @@ sparc_frame_saved_pc (frame)
 #endif
 
       CORE_ADDR sigcontext_addr;
-      char scbuf[TARGET_PTR_BIT / HOST_CHAR_BIT];
+      char scbuf[TARGET_MAX_PTR_BIT / HOST_CHAR_BIT];
       int saved_pc_offset = SIGCONTEXT_PC_OFFSET;
       char *name = NULL;
 
@@ -616,9 +610,7 @@ isbranch (instruction, addr, target)
 	  || X_OP2 (instruction) == 1
 	  || X_OP2 (instruction) == 3
 	  || X_OP2 (instruction) == 5
-#ifndef GDB_TARGET_IS_SPARC64
-	  || X_OP2 (instruction) == 7
-#endif
+	  || (!is_sparc64 && X_OP2 (instruction) == 7)
       ))
     {
       if (X_COND (instruction) == 8)
@@ -629,9 +621,7 @@ isbranch (instruction, addr, target)
 	{
 	case 2:
 	case 6:
-#ifndef GDB_TARGET_IS_SPARC64
 	case 7:
-#endif
 	  offset = 4 * X_DISP22 (instruction);
 	  break;
 	case 1:
@@ -644,8 +634,7 @@ isbranch (instruction, addr, target)
 	}
       *target = addr + offset;
     }
-#ifdef GDB_TARGET_IS_SPARC64
-  else if (X_OP (instruction) == 2
+  else if (is_sparc64 && X_OP (instruction) == 2
 	   && X_OP3 (instruction) == 62)
     {
       if (X_FCN (instruction) == 0)
@@ -661,7 +650,6 @@ isbranch (instruction, addr, target)
 	  val = done_retry;
 	}
     }
-#endif
 
   return val;
 }
@@ -753,11 +741,10 @@ sparc_get_saved_register (raw_buffer, op
 	  else if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM + 32)
 	    addr = frame1->frame + (regnum - FP0_REGNUM) * 4
 	      - (FP_REGISTER_BYTES);
-#ifdef GDB_TARGET_IS_SPARC64
-	  else if (regnum >= FP0_REGNUM + 32 && regnum < FP_MAX_REGNUM)
+	  else if (is_sparc64
+		   && regnum >= FP0_REGNUM + 32 && regnum < FP_MAX_REGNUM)
 	    addr = frame1->frame + 32 * 4 + (regnum - FP0_REGNUM - 32) * 8
 	      - (FP_REGISTER_BYTES);
-#endif
 #endif /* FP0_REGNUM */
 	  else if (regnum >= Y_REGNUM && regnum < NUM_REGS)
 	    addr = frame1->frame + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE
@@ -842,11 +829,7 @@ sparc_get_saved_register (raw_buffer, op
 
 /* Definitely see tm-sparc.h for more doc of the frame format here.  */
 
-#ifdef GDB_TARGET_IS_SPARC64
-#define DUMMY_REG_SAVE_OFFSET (128 + 16)
-#else
-#define DUMMY_REG_SAVE_OFFSET 0x60
-#endif
+#define DUMMY_REG_SAVE_OFFSET (is_sparc64 ? 128 + 16 : 0x60)
 
 /* See tm-sparc.h for how this is calculated.  */
 #ifdef FP0_REGNUM
@@ -866,18 +849,21 @@ sparc_push_dummy_frame ()
 
   old_sp = sp = read_sp ();
 
-#ifdef GDB_TARGET_IS_SPARC64
-  /* PC, NPC, CCR, FSR, FPRS, Y, ASI */
-  read_register_bytes (REGISTER_BYTE (PC_REGNUM), &register_temp[0],
-		       REGISTER_RAW_SIZE (PC_REGNUM) * 7);
-  read_register_bytes (REGISTER_BYTE (PSTATE_REGNUM), &register_temp[8],
-		       REGISTER_RAW_SIZE (PSTATE_REGNUM));
-  /* FIXME: not sure what needs to be saved here.  */
-#else
-  /* Y, PS, WIM, TBR, PC, NPC, FPS, CPS regs */
-  read_register_bytes (REGISTER_BYTE (Y_REGNUM), &register_temp[0],
-		       REGISTER_RAW_SIZE (Y_REGNUM) * 8);
-#endif
+  if (is_sparc64)
+    {
+      /* PC, NPC, CCR, FSR, FPRS, Y, ASI */
+      read_register_bytes (REGISTER_BYTE (PC_REGNUM), &register_temp[0],
+			   REGISTER_RAW_SIZE (PC_REGNUM) * 7);
+      read_register_bytes (REGISTER_BYTE (PSTATE_REGNUM), &register_temp[8],
+			   REGISTER_RAW_SIZE (PSTATE_REGNUM));
+      /* FIXME: not sure what needs to be saved here.  */
+    }
+  else
+    {
+      /* Y, PS, WIM, TBR, PC, NPC, FPS, CPS regs */
+      read_register_bytes (REGISTER_BYTE (Y_REGNUM), &register_temp[0],
+			   REGISTER_RAW_SIZE (Y_REGNUM) * 8);
+    }
 
   read_register_bytes (REGISTER_BYTE (O0_REGNUM),
 		       &register_temp[8 * SPARC_INTREG_SIZE],
@@ -996,28 +982,30 @@ sparc_frame_find_saved_regs (fi, saved_r
 	saved_regs_addr->regs[regnum] =
 	  frame_addr + (regnum - FP0_REGNUM) * 4
 	  - DUMMY_STACK_REG_BUF_SIZE + 24 * SPARC_INTREG_SIZE;
-#ifdef GDB_TARGET_IS_SPARC64
-      for (regnum = FP0_REGNUM + 32; regnum < FP_MAX_REGNUM; regnum++)
-	saved_regs_addr->regs[regnum] =
-	  frame_addr + 32 * 4 + (regnum - FP0_REGNUM - 32) * 4
-	  - DUMMY_STACK_REG_BUF_SIZE + 24 * SPARC_INTREG_SIZE;
-#endif
+      if (is_sparc64)
+	for (regnum = FP0_REGNUM + 32; regnum < FP_MAX_REGNUM; regnum++)
+	  saved_regs_addr->regs[regnum] =
+	    frame_addr + 32 * 4 + (regnum - FP0_REGNUM - 32) * 4
+	    - DUMMY_STACK_REG_BUF_SIZE + 24 * SPARC_INTREG_SIZE;
 #endif /* FP0_REGNUM */
-#ifdef GDB_TARGET_IS_SPARC64
-      for (regnum = PC_REGNUM; regnum < PC_REGNUM + 7; regnum++)
+      if (is_sparc64)
 	{
-	  saved_regs_addr->regs[regnum] =
-	    frame_addr + (regnum - PC_REGNUM) * SPARC_INTREG_SIZE
-	    - DUMMY_STACK_REG_BUF_SIZE;
+	  for (regnum = PC_REGNUM; regnum < PC_REGNUM + 7; regnum++)
+	    {
+	      saved_regs_addr->regs[regnum] =
+		frame_addr + (regnum - PC_REGNUM) * SPARC_INTREG_SIZE
+		- DUMMY_STACK_REG_BUF_SIZE;
+	    }
+	  saved_regs_addr->regs[PSTATE_REGNUM] =
+	    frame_addr + 8 * SPARC_INTREG_SIZE - DUMMY_STACK_REG_BUF_SIZE;
+	}
+      else
+	{
+	  for (regnum = Y_REGNUM; regnum < NUM_REGS; regnum++)
+	    saved_regs_addr->regs[regnum] =
+	      frame_addr + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE
+	      - DUMMY_STACK_REG_BUF_SIZE;
 	}
-      saved_regs_addr->regs[PSTATE_REGNUM] =
-	frame_addr + 8 * SPARC_INTREG_SIZE - DUMMY_STACK_REG_BUF_SIZE;
-#else
-      for (regnum = Y_REGNUM; regnum < NUM_REGS; regnum++)
-	saved_regs_addr->regs[regnum] =
-	  frame_addr + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE
-	  - DUMMY_STACK_REG_BUF_SIZE;
-#endif
       frame_addr = fi->bottom ?
 	fi->bottom : read_sp ();
     }
@@ -1101,18 +1089,16 @@ sparc_pop_frame ()
       write_register_bytes (REGISTER_BYTE (FP0_REGNUM),
 			    raw_buffer, FP_REGISTER_BYTES);
     }
-#ifndef GDB_TARGET_IS_SPARC64
-  if (fsr.regs[FPS_REGNUM])
+  if (!is_sparc64 && fsr.regs[FPS_REGNUM])
     {
       read_memory (fsr.regs[FPS_REGNUM], raw_buffer, 4);
       write_register_bytes (REGISTER_BYTE (FPS_REGNUM), raw_buffer, 4);
     }
-  if (fsr.regs[CPS_REGNUM])
+  if (!is_sparc64 && fsr.regs[CPS_REGNUM])
     {
       read_memory (fsr.regs[CPS_REGNUM], raw_buffer, 4);
       write_register_bytes (REGISTER_BYTE (CPS_REGNUM), raw_buffer, 4);
     }
-#endif
 #endif /* FP0_REGNUM */
   if (fsr.regs[G1_REGNUM])
     {
@@ -1160,10 +1146,8 @@ sparc_pop_frame ()
          locals from the registers array, so we need to muck with the
          registers array.  */
       sp = fsr.regs[SP_REGNUM];
-#ifdef GDB_TARGET_IS_SPARC64
-      if (sp & 1)
+      if (is_sparc64 && (sp & 1))
 	sp += 2047;
-#endif
       read_memory (sp, reg_temp, SPARC_INTREG_SIZE * 16);
 
       /* Restore the out registers.
@@ -1174,10 +1158,8 @@ sparc_pop_frame ()
       write_register_bytes (REGISTER_BYTE (L0_REGNUM), reg_temp,
 			    SPARC_INTREG_SIZE * 16);
     }
-#ifndef GDB_TARGET_IS_SPARC64
-  if (fsr.regs[PS_REGNUM])
+  if (!is_sparc64 && fsr.regs[PS_REGNUM])
     write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4));
-#endif
   if (fsr.regs[Y_REGNUM])
     write_register (Y_REGNUM, read_memory_integer (fsr.regs[Y_REGNUM], REGISTER_RAW_SIZE (Y_REGNUM)));
   if (fsr.regs[PC_REGNUM])
@@ -1897,17 +1879,15 @@ sparc_fix_call_dummy (dummy, pc, fun, va
     store_unsigned_integer (dummy + CALL_DUMMY_CALL_OFFSET + 8, 4,
 			    TYPE_LENGTH (value_type) & 0x1fff);
 
-#ifndef GDB_TARGET_IS_SPARC64
   /* If this is not a simulator target, change the first four instructions
      of the call dummy to NOPs.  Those instructions include a 'save'
      instruction and are designed to work around problems with register
      window flushing in the simulator. */
-  if (strcmp (target_shortname, "sim") != 0)
+  if (!is_sparc64 && strcmp (target_shortname, "sim") != 0)
     {
       for (i = 0; i < 4; i++)
 	store_unsigned_integer (dummy + (i * 4), 4, 0x01000000);
     }
-#endif
 
   /* If this is a bi-endian target, GDB has written the call dummy
      in little-endian order.  We must byte-swap it back to big-endian. */
@@ -1934,6 +1914,18 @@ sparc_target_architecture_hook (ap)
 {
   int i, j;
 
+#ifdef GDB_TARGET_IS_SPARC_BI_ARCH
+  switch (ap->mach)
+    {
+    case bfd_mach_sparc_v9:
+    case bfd_mach_sparc_v9a:
+      gdb_is_sparc64 = 1;
+      break;
+    default:
+      gdb_is_sparc64 = 0;
+      break;
+    }
+#endif
   if (ap->mach == bfd_mach_sparc_sparclite_le)
     {
       if (TARGET_BYTE_ORDER_SELECTABLE_P)
@@ -1952,14 +1944,6 @@ sparc_target_architecture_hook (ap)
 }
 
 
-void
-_initialize_sparc_tdep ()
-{
-  tm_print_insn = gdb_print_insn_sparc;
-  tm_print_insn_info.mach = TM_PRINT_INSN_MACH;		/* Selects sparc/sparclite */
-  target_architecture_hook = sparc_target_architecture_hook;
-}
-
 
 #ifdef GDB_TARGET_IS_SPARC64
 
@@ -1970,7 +1954,7 @@ sparc64_read_sp ()
 {
   CORE_ADDR sp = read_register (SP_REGNUM);
 
-  if (sp & 1)
+  if (is_sparc64 && (sp & 1))
     sp += 2047;
   return sp;
 }
@@ -1980,7 +1964,7 @@ sparc64_read_fp ()
 {
   CORE_ADDR fp = read_register (FP_REGNUM);
 
-  if (fp & 1)
+  if (is_sparc64 && (fp & 1))
     fp += 2047;
   return fp;
 }
@@ -1990,7 +1974,7 @@ sparc64_write_sp (val)
      CORE_ADDR val;
 {
   CORE_ADDR oldsp = read_register (SP_REGNUM);
-  if (oldsp & 1)
+  if (is_sparc64 && (oldsp & 1))
     write_register (SP_REGNUM, val - 2047);
   else
     write_register (SP_REGNUM, val);
@@ -2001,7 +1985,7 @@ sparc64_write_fp (val)
      CORE_ADDR val;
 {
   CORE_ADDR oldfp = read_register (FP_REGNUM);
-  if (oldfp & 1)
+  if (is_sparc64 && (oldfp & 1))
     write_register (FP_REGNUM, val - 2047);
   else
     write_register (FP_REGNUM, val);
@@ -2022,6 +2006,10 @@ sp64_push_arguments (nargs, args, sp, st
   int regnum = 0;
   CORE_ADDR tempsp;
 
+  if (!is_sparc64)
+    return sparc_push_arguments (nargs, args, sp, struct_return,
+				 struct_retaddr);
+
   sp = (sp & ~(((unsigned long) TYPE_LENGTH (builtin_type_long)) - 1UL));
 
   /* Figure out how much space we'll need. */
@@ -2094,6 +2082,12 @@ sparc64_extract_return_value (type, regb
   int typelen = TYPE_LENGTH (type);
   int regsize = REGISTER_RAW_SIZE (O0_REGNUM);
 
+  if (!is_sparc64)
+    {
+      sparc_extract_return_value (type, regbuf, valbuf);
+      return;
+    }  
+
   if (TYPE_CODE (type) == TYPE_CODE_FLT && SPARC_HAS_FPU)
     {
       memcpy (valbuf, &regbuf[REGISTER_BYTE (FP0_REGNUM)], typelen);
@@ -2146,3 +2140,11 @@ sparc64_extract_return_value (type, regb
 
 
 #endif
+
+void
+_initialize_sparc_tdep ()
+{
+  tm_print_insn = gdb_print_insn_sparc;
+  tm_print_insn_info.mach = TM_PRINT_INSN_MACH;		/* Selects sparc/sparclite */
+  target_architecture_hook = sparc_target_architecture_hook;
+}
--- gdb/jv-valprint.c.jj	Wed Feb  2 01:21:08 2000
+++ gdb/jv-valprint.c	Fri Mar 17 16:09:14 2000
@@ -99,7 +99,7 @@ java_value_print (val, stream, format, p
 
 	  while (i < length && things_printed < print_max)
 	    {
-	      char buf[TARGET_PTR_BIT / HOST_CHAR_BIT];
+	      char buf[TARGET_MAX_PTR_BIT / HOST_CHAR_BIT];
 
 	      fputs_filtered (", ", stream);
 	      wrap_here (n_spaces (2));
--- gdb/configure.tgt.jj	Thu Feb 24 04:31:45 2000
+++ gdb/configure.tgt	Fri Mar 17 16:09:14 2000
@@ -269,7 +269,8 @@ sparc86x-*-*)		gdb_target=sparclite ;;
 # should return.  Work is still needed to get gdb to print the 64 bit
 # regs (some of which are usable in v8plus) so sp64sol.mt hasn't been
 # deleted though presumably it should be eventually.
-#sparc64-*-solaris2*)	gdb_target=sp64sol2 ;;
+#sparcv9-*-solaris2*)	gdb_target=sp64sol2 ;;
+sparc64-*-linux*)	gdb_target=linux64 ;;
 sparc64-*-*)		gdb_target=sp64 ;;
 
 # OBSOLETE tahoe-*-*)		gdb_target=tahoe ;;
--- gdb/lin-thread.c.jj	Wed Feb  9 09:52:46 2000
+++ gdb/lin-thread.c	Fri Mar 17 16:09:14 2000
@@ -658,7 +658,7 @@ init_thread_db_library ()
 static struct cleanup *
 save_inferior_pid (void)
 {
-#if TARGET_PTR_BIT > TARGET_INT_BIT
+#if TARGET_MAX_PTR_BIT > TARGET_INT_BIT
   return make_cleanup (restore_inferior_pid, (void *) ((long) inferior_pid));
 #else
   return make_cleanup (restore_inferior_pid, (void *) inferior_pid);
@@ -668,7 +668,7 @@ save_inferior_pid (void)
 static void
 restore_inferior_pid (void *saved_pid)
 {
-#if TARGET_PTR_BIT > TARGET_INT_BIT
+#if TARGET_MAX_PTR_BIT > TARGET_INT_BIT
   inferior_pid = (int) ((long) saved_pid);
 #else
   inferior_pid = (int) saved_pid;
--- gdb/linux-thread.c.jj	Thu Feb 10 05:53:26 2000
+++ gdb/linux-thread.c	Fri Mar 17 16:09:14 2000
@@ -381,7 +381,7 @@ static void
 restore_inferior_pid (arg)
     void *arg;
 {
-#if TARGET_PTR_BIT > TARGET_INT_BIT
+#if TARGET_MAX_PTR_BIT > TARGET_INT_BIT
   inferior_pid = (int) ((long) arg);
 #else
   inferior_pid = (int) arg;
@@ -392,7 +392,7 @@ restore_inferior_pid (arg)
 static struct cleanup *
 save_inferior_pid ()
 {
-#if TARGET_PTR_BIT > TARGET_INT_BIT
+#if TARGET_MAX_PTR_BIT > TARGET_INT_BIT
   return make_cleanup (restore_inferior_pid, (void *) ((long) inferior_pid));
 #else
   return make_cleanup (restore_inferior_pid, (void *) inferior_pid);

	Jakub

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