This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[PATCH/SPARC] Add GNU/Linux UltraSPARC
- From: Mark Kettenis <kettenis at chello dot nl>
- To: gdb-patches at sources dot redhat dot com
- Date: Sun, 2 Nov 2003 21:27:20 +0100 (CET)
- Subject: [PATCH/SPARC] Add GNU/Linux UltraSPARC
Committed to the SPARC-branch.
Mark
Index: ChangeLog
from Mark Kettenis <kettenis@gnu.org>
* sparc64-tdep.h (r_tstate_offset): New define.
(sparc64_supply_gregset, sparc64_collect_gregset,
sparc64_supply_fpregset, sparc64_collect_fpregset): New
prototypes.
(sparc64_sol2_gregset): New extern declaration.
(sparc64_sol2_init_abi): New prototype.
* sparc64-tdep.c: Include "symtab.h" and "objfiles.h". Don't
include "sparc-tdep.h".
(X_RD, X_I): New macros.
(sparc64_analyze_prologue): Sync with implementation in
sparc-tdep.c.
(TSTATE_CWP, TSTATE_ICC, TSTATE_XCC): New macros.
(PSR_S, PSR_ICC, PSR_VERS, PSR_IMPL, PSR_V8PLUS, PSR_XCC): New
macros.
(sparc64_supply_gregset, sparc64_collect_gregset,
sparc64_supply_fpregset, sparc64_collect_fpregset): New functions.
* sparc64-nat.c: New file.
* sparc64-sol2-nat.c: New file.
* sparc64-sol2-tdep.c: New file.
* sparc64-linux-nat.c: New file.
* sparc64-linux-tdep.c: New file.
* Makefile.in (sparc_tdep_h): New variable.
(ALLDEPFILES): Add sparc64-sol2-tdep.c, sparc64-linux-tdep.c,
sparc64-nat.c sparc64-sol2-nat.c and sparc64-linux-nat.c
(sparc-nat.o, sparc-linux-tdep.o, sparc64-tdep.o): Update
dependencies.
(sparc64-nat.o, sparc64-linux-nat.o, sparc64-linux-tdep.o,
sparc64-sol2-nat.o, sparc64-sol2-tdep.o): New dependencies.
* configure.tgt: Add sparc64-*-linux*.
* configure.host: Add sparc64-*-linux*.
* config/sparc/linux64.mt: New file.
* config/sparc/linux64.mh: New file.
Index: configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.116.4.2
diff -u -p -r1.116.4.2 configure.tgt
--- configure.tgt 25 Oct 2003 18:42:28 -0000 1.116.4.2
+++ configure.tgt 2 Nov 2003 20:22:32 -0000
@@ -205,6 +205,7 @@ sh*) gdb_target=embed ;;
sparc-*-solaris2*) gdb_target=sol2 ;;
sparc-*-linux*) gdb_target=linux ;;
sparc-*-*) gdb_target=sparc ;;
+sparc64-*-linux*) gdb_target=linux64 ;;
xstormy16-*-*) gdb_target=xstormy16 ;;
Index: configure.host
===================================================================
RCS file: /cvs/src/src/gdb/configure.host,v
retrieving revision 1.57.4.2
diff -u -p -r1.57.4.2 configure.host
--- configure.host 25 Oct 2003 18:42:28 -0000 1.57.4.2
+++ configure.host 2 Nov 2003 20:22:33 -0000
@@ -133,6 +133,7 @@ sh*-*-netbsdelf*) gdb_host=nbsd ;;
sparc-*-solaris2*) gdb_host=sol2 ;;
sparc-*-linux*) gdb_host=linux ;;
sparc64-*-freebsd*) gdb_host=fbsd ;;
+sparc64-*-linux*) gdb_host=linux64 ;;
vax-*-bsd*) gdb_host=vaxbsd ;;
vax-*-ultrix2*) gdb_host=vaxult2 ;;
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.445.2.4
diff -u -p -r1.445.2.4 Makefile.in
--- Makefile.in 25 Oct 2003 18:42:28 -0000 1.445.2.4
+++ Makefile.in 2 Nov 2003 20:22:35 -0000
@@ -748,6 +748,7 @@ somsolib_h = somsolib.h
source_h = source.h
sparc_tdep_h = sparc-tdep.h
sparc64_tdep_h = sparc64-tdep.h $(sparc_tdep_h)
+sparc_nat_h = sparc-nat.h
srec_h = srec.h
stabsread_h = stabsread.h
stack_h = stack.h
@@ -1295,7 +1296,9 @@ ALLDEPFILES = \
solib.c solib-irix.c solib-svr4.c solib-sunos.c \
sparc-tdep.c sparc-linux-tdep.c sparc-sol2-tdep.c \
sparc-nat.c sparc-sol2-nat.c sparcbsd-nat.c \
- sparc64-tdep.c sparc64fbsd-tdep.c \
+ sparc64-tdep.c sparc64-sol2-tdep.c sparc64-linux-tdep.c \
+ sparc64fbsd-tdep.c \
+ sparc64-nat.c sparc64-sol2-nat.c sparc64-linux-nat.c \
sparc64fbsd-nat.c \
sun3-nat.c \
symm-tdep.c symm-nat.c \
@@ -2302,15 +2305,15 @@ source.o: source.c $(defs_h) $(symtab_h)
$(gdb_string_h) $(gdb_stat_h) $(gdbcore_h) $(gdb_regex_h) \
$(symfile_h) $(objfiles_h) $(annotate_h) $(gdbtypes_h) $(linespec_h) \
$(filenames_h) $(completer_h) $(ui_out_h)
-sparc-nat.o: sparc-nat.c $(defs_h) $(inferior_h) $(regcache_h) $(gdb_wait_h) \
- $(sparc_tdep_h)
+sparc-nat.o: sparc-nat.c $(defs_h) $(inferior_h) $(regcache_h) \
+ $(gdb_string_h) $(gdb_wait_h) $(sparc_tdep_h) $(sparc_nat_h)
sparc-tdep.o: sparc-tdep.c $(defs_h) $(arch_utils_h) $(dis_asm_h) $(frame_h) \
$(frame_base_h) $(frame_unwind_h) $(gdbcore_h) $(gdbtypes_h) \
$(inferior_h) $(symtab_h) $(objfiles_h) $(osabi_h) $(regcache_h) \
$(target_h) $(value_h) $(gdb_assert_h) $(gdb_string_h) \
$(sparc_tdep_h)
sparc-linux-tdep.o: sparc-linux-tdep.c $(defs_h) $(gdbarch_h) $(osabi_h) \
- $(sparc_tdep_h)
+ $(solib_svr4_h) $(sparc_tdep_h)
sparc-sol2-nat.o: sparc-sol2-nat.c $(defs_h) $(gregset_h) $(regcache_h) \
$(sparc_tdep_h)
sparc-sol2-tdep.o: sparc-sol2-tdep.c $(defs_h) $(frame_h) $(frame_base_h) \
@@ -2319,11 +2322,21 @@ sparc-sol2-tdep.o: sparc-sol2-tdep.c $(d
$(gdb_string_h) $(sparc_tdep_h)
sparcbsd-nat.o: sparcbsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \
$(sparc64_tdep_h) $(sparcbsd_nat_h)
+sparc64-nat.o: sparc-nat.c $(defs_h) $(gdbarch_h) \
+ $(sparc64_tdep_h) $(sparc_nat_h)
sparc64-tdep.o: sparc64-tdep.c $(defs_h) $(arch_utils_h) $(floatformat_h) \
$(frame_h) $(frame_base_h) $(frame_unwind_h) $(gdbcore_h) \
- $(gdbtypes_h) $(inferior_h) $(osabi_h) $(regcache_h) $(target_h) \
- $(value_h) $(gdb_assert_h) $(gdb_string_h) $(sparc_tdep_h) \
+ $(gdbtypes_h) $(inferior_h) $(symtab_h) $(objfiles_h) $(osabi_h) \
+ $(regcache_h) $(target_h) $(value_h) $(gdb_assert_h) $(gdb_string_h) \
+ $(sparc64_tdep_h)
+sparc64-linux-nat.o: sparc64-linux-nat.c $(defs_h) \
+ $(sparc64_tdep_h) $(sparc_nat_h)
+sparc64-linux-tdep.o: sparc64-linux-tdep.c $(defs_h) $(gdbarch_h) \
+ $(osabi_h) $(solib_svr4_h) $(sparc64_tdep_h)
+sparc64-sol2-nat.o: sparc64-sol2-nat.o $(defs_h) $(gregset_h) $(regcache_h) \
$(sparc64_tdep_h)
+sparc64-sol2-tdep.c: sparc64-sol2-tdep.o $(defs_h) $(gdbarch_h) $(symtab_h) \
+ $(objfiles_h) $(osabi_h) $(sparc64_tdep_h)
sparc64fbsd-tdep.o: sparc64fbsd-tdep.c $(defs_h) $(gdbcore_h) $(osabi_h) \
$(regcache_h) $(target_h) $(gdb_string_h) $(sparc64_tdep_h)
sparc64fbsd-nat.o: sparc64fbsd-nat.c $(defs_h) $(sparc64_tdep_h) \
Index: sparc64-linux-nat.c
===================================================================
RCS file: sparc64-linux-nat.c
diff -N sparc64-linux-nat.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sparc64-linux-nat.c 2 Nov 2003 20:22:35 -0000
@@ -0,0 +1,48 @@
+/* Native-dependent code for GNU/Linux UltraSPARC.
+
+ Copyright 2003 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 "sparc64-tdep.h"
+#include "sparc-nat.h"
+
+static const struct sparc_gregset sparc64_linux_ptrace_gregset =
+{
+ 16 * 8, /* "tstate" */
+ 17 * 8, /* %pc */
+ 18 * 8, /* %npc */
+ 19 * 8, /* %y */
+ -1, /* %wim */
+ -1, /* %tbr */
+ 0 * 8, /* %g1 */
+ -1, /* %l0 */
+ 4 /* sizeof (%y) */
+};
+
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+void _initialize_sparc64_linux_nat (void);
+
+void
+_initialize_sparc64_linux_nat (void)
+{
+ sparc_gregset = &sparc64_linux_ptrace_gregset;
+}
Index: sparc64-linux-tdep.c
===================================================================
RCS file: sparc64-linux-tdep.c
diff -N sparc64-linux-tdep.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sparc64-linux-tdep.c 2 Nov 2003 20:22:35 -0000
@@ -0,0 +1,82 @@
+/* Target-dependent code for GNU/Linux UltraSPARC.
+
+ Copyright 2003 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 "gdbarch.h"
+#include "osabi.h"
+#include "solib-svr4.h"
+
+#include "sparc64-tdep.h"
+
+static struct link_map_offsets *
+sparc64_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;
+
+ /* Everything we need is in the first 16 bytes. */
+ lmo.r_debug_size = 16;
+ lmo.r_map_offset = 8;
+ lmo.r_map_size = 8;
+
+ /* Everything we need is in the first 40 bytes. */
+ 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;
+}
+
+static void
+sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ /* GNU/Linux is very similar to Solaris ... */
+ sparc64_sol2_init_abi (info, gdbarch);
+
+ /* ... but doesn't have kernel-assisted single-stepping support. */
+ set_gdbarch_software_single_step (gdbarch, sparc_software_single_step);
+
+ set_solib_svr4_fetch_link_map_offsets
+ (gdbarch, sparc64_linux_svr4_fetch_link_map_offsets);
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern void _initialize_sparc64_linux_tdep (void);
+
+void
+_initialize_sparc64_linux_tdep (void)
+{
+ gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
+ GDB_OSABI_LINUX, sparc64_linux_init_abi);
+}
Index: sparc64-nat.c
===================================================================
RCS file: sparc64-nat.c
diff -N sparc64-nat.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sparc64-nat.c 2 Nov 2003 20:22:35 -0000
@@ -0,0 +1,86 @@
+/* Native-dependent code for GNU/Linux UltraSPARC.
+
+ Copyright 2003 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 "gdbarch.h"
+
+#include "sparc64-tdep.h"
+#include "sparc-nat.h"
+
+/* Determine whether `gregset_t' contains register REGNUM. */
+
+static int
+sparc64_gregset_supplies_p (int regnum)
+{
+ if (gdbarch_ptr_bit (current_gdbarch) == 32)
+ return sparc32_gregset_supplies_p (regnum);
+
+ /* Integer registers. */
+ if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM)
+ || (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
+ || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM)
+ || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM))
+ return 1;
+
+ /* Control registers. */
+ if (regnum == SPARC64_PC_REGNUM
+ || regnum == SPARC64_NPC_REGNUM
+ || regnum == SPARC64_STATE_REGNUM
+ || regnum == SPARC64_Y_REGNUM)
+ return 1;
+
+ return 0;
+}
+
+/* Determine whether `fpregset_t' contains register REGNUM. */
+
+static int
+sparc64_fpregset_supplies_p (int regnum)
+{
+ if (gdbarch_ptr_bit (current_gdbarch) == 32)
+ return sparc32_fpregset_supplies_p (regnum);
+
+ /* Floating-point registers. */
+ if ((regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
+ || (regnum >= SPARC64_F32_REGNUM && regnum <= SPARC64_F62_REGNUM))
+ return 1;
+
+ /* Control registers. */
+ if (regnum == SPARC64_FSR_REGNUM)
+ return 1;
+
+ return 0;
+}
+
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+void _initialize_sparc64_nat (void);
+
+void
+_initialize_sparc64_nat (void)
+{
+ sparc_supply_gregset = sparc64_supply_gregset;
+ sparc_collect_gregset = sparc64_collect_gregset;
+ sparc_supply_fpregset = sparc64_supply_fpregset;
+ sparc_collect_fpregset = sparc64_collect_fpregset;
+ sparc_gregset_supplies_p = sparc64_gregset_supplies_p;
+ sparc_fpregset_supplies_p = sparc64_fpregset_supplies_p;
+}
Index: sparc64-sol2-nat.c
===================================================================
RCS file: sparc64-sol2-nat.c
diff -N sparc64-sol2-nat.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sparc64-sol2-nat.c 2 Nov 2003 20:22:35 -0000
@@ -0,0 +1,57 @@
+/* Native-dependent code for Solaris UltraSPARC.
+
+ Copyright 2003 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 "regcache.h"
+
+#include <sys/procfs.h>
+#include "gregset.h"
+
+#include "sparc64-tdep.h"
+
+/* These functions provide the (temporary) glue between the Solaris
+ SPARC target dependent code and the machine independent SVR4 /proc
+ support. */
+
+void
+supply_gregset (prgregset_t *gregs)
+{
+ sparc64_supply_gregset (&sparc64_sol2_gregset, current_regcache, -1, gregs);
+}
+
+void
+supply_fpregset (prfpregset_t *fpregs)
+{
+ sparc64_supply_fpregset (current_regcache, -1, fpregs);
+}
+
+void
+fill_gregset (prgregset_t *gregs, int regnum)
+{
+ sparc64_collect_gregset (&sparc64_sol2_gregset,
+ current_regcache, regnum, gregs);
+}
+
+void
+fill_fpregset (prfpregset_t *fpregs, int regnum)
+{
+ sparc64_collect_fpregset (current_regcache, regnum, fpregs);
+}
Index: sparc64-sol2-tdep.c
===================================================================
RCS file: sparc64-sol2-tdep.c
diff -N sparc64-sol2-tdep.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sparc64-sol2-tdep.c 2 Nov 2003 20:22:35 -0000
@@ -0,0 +1,73 @@
+/* Target-dependent code for Solaris UltraSPARC.
+
+ Copyright 2003 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 "gdbarch.h"
+#include "symtab.h"
+#include "objfiles.h"
+#include "osabi.h"
+
+#include "sparc64-tdep.h"
+
+/* From <sys/regset.h>. */
+const struct sparc_gregset sparc64_sol2_gregset =
+{
+ 32 * 8, /* "tstate" */
+ 33 * 8, /* %pc */
+ 34 * 8, /* %npc */
+ 35 * 8, /* %y */
+ -1, /* %wim */
+ -1, /* %tbr */
+ 1 * 8, /* %g1 */
+ 16 * 8, /* %l0 */
+ 8 /* sizeof (%y) */
+};
+
+
+void
+sparc64_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ sparc64_init_abi (info, gdbarch);
+
+ /* Solaris has SVR4-style shared libraries... */
+ set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
+ set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+
+ /* ...which means that we need some special handling when doing
+ prologue analysis. */
+ tdep->plt_entry_size = 16;
+
+ /* Solaris has kernel-assisted single-stepping support. */
+ set_gdbarch_software_single_step (gdbarch, NULL);
+}
+
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+void _initialize_sparc64_sol2_tdep (void);
+
+void
+_initialize_sparc64_sol2_tdep (void)
+{
+ gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
+ GDB_OSABI_SOLARIS, sparc64_sol2_init_abi);
+}
Index: sparc64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc64-tdep.c,v
retrieving revision 1.3.4.1
diff -u -p -r1.3.4.1 sparc64-tdep.c
--- sparc64-tdep.c 18 Oct 2003 18:25:46 -0000 1.3.4.1
+++ sparc64-tdep.c 2 Nov 2003 20:22:35 -0000
@@ -28,6 +28,8 @@
#include "gdbcore.h"
#include "gdbtypes.h"
#include "inferior.h"
+#include "symtab.h"
+#include "objfiles.h"
#include "osabi.h"
#include "regcache.h"
#include "target.h"
@@ -36,7 +38,6 @@
#include "gdb_assert.h"
#include "gdb_string.h"
-#include "sparc-tdep.h"
#include "sparc64-tdep.h"
/* This file implements the The SPARC 64-bit ABI as defined by the
@@ -56,11 +57,13 @@
/* Macros to extract fields from SPARC instructions. */
#define X_OP(i) (((i) >> 30) & 0x3)
+#define X_RD(i) (((i) >> 25) & 0x1f)
#define X_A(i) (((i) >> 29) & 1)
#define X_COND(i) (((i) >> 25) & 0xf)
#define X_OP2(i) (((i) >> 22) & 0x7)
#define X_IMM22(i) ((i) & 0x3fffff)
#define X_OP3(i) (((i) >> 19) & 0x3f)
+#define X_I(i) (((i) >> 13) & 1)
/* Sign extension macros. */
#define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000)
#define X_DISP19(i) ((((i) & 0x7ffff) ^ 0x40000) - 0x40000)
@@ -526,17 +529,52 @@ static CORE_ADDR
sparc64_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
struct sparc64_frame_cache *cache)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
unsigned long insn;
+ int offset = 0;
+ int dest = -1;
if (current_pc <= pc)
return current_pc;
- /* Check whether the function starts with a SAVE instruction. */
+ /* We have to handle to "Procedure Linkage Table" (PLT) special. On
+ SPARC the linker usually defines a symbol (typically
+ _PROCEDURE_LINKAGE_TABLE_) at the start of the .plt section.
+ This symbol makes us end up here with PC pointing at the start of
+ the PLT and CURRENT_PC probably pointing at a PLT entry. If we
+ would do our normal prologue analysis, we would probably conclude
+ that we've got a frame when in reality we don't, since the
+ dynamic linker patches up the first PLT with some code that
+ starts with a SAVE instruction. Patch up PC such that it points
+ at the start of our PLT entry. */
+ if (tdep->plt_entry_size > 0 && in_plt_section (current_pc, NULL))
+ pc = current_pc - ((current_pc - pc) % tdep->plt_entry_size);
+
insn = sparc_fetch_instruction (pc);
+
+ /* Recognize a SETHI insn and record its destination. */
+ if (X_OP (insn) == 0 && X_OP2 (insn) == 0x04)
+ {
+ dest = X_RD (insn);
+ offset += 4;
+
+ insn = sparc_fetch_instruction (pc + 4);
+ }
+
+ /* Allow for an arithmetic operation on DEST or %g1. */
+ if (X_OP (insn) == 2 && X_I (insn)
+ && (X_RD (insn) == 1 || X_RD (insn) == dest))
+ {
+ offset += 4;
+
+ insn = sparc_fetch_instruction (pc + 8);
+ }
+
+ /* Check for the SAVE instruction that sets up the frame. */
if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3c)
{
cache->frameless_p = 0;
- return pc + 4;
+ return pc + offset + 4;
}
return pc;
@@ -1203,4 +1241,299 @@ sparc64_init_abi (struct gdbarch_info in
frame_unwind_append_sniffer (gdbarch, sparc64_frame_sniffer);
frame_base_set_default (gdbarch, &sparc64_frame_base);
+}
+
+
+/* Helper functions for dealing with register sets. */
+
+#define TSTATE_CWP 0x000000000000001f
+#define TSTATE_ICC 0x0000000f00000000
+#define TSTATE_XCC 0x000000f000000000
+
+#define PSR_S 0x00000080
+#define PSR_ICC 0x00f00000
+#define PSR_VERS 0x0f000000
+#define PSR_IMPL 0xf0000000
+#define PSR_V8PLUS 0xff000000
+#define PSR_XCC 0x000f0000
+
+void
+sparc64_supply_gregset (const struct sparc_gregset *gregset,
+ struct regcache *regcache,
+ int regnum, const void *gregs)
+{
+ int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
+ const char *regs = gregs;
+ int i;
+
+ if (sparc32)
+ {
+ if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
+ {
+ int offset = gregset->r_tstate_offset;
+ ULONGEST tstate, psr;
+ char buf[4];
+
+ tstate = extract_unsigned_integer (regs + offset, 8);
+ psr = ((tstate & TSTATE_CWP) | PSR_S | ((tstate & TSTATE_ICC) >> 12)
+ | ((tstate & TSTATE_XCC) >> 20) | PSR_V8PLUS);
+ store_unsigned_integer (buf, 4, psr);
+ regcache_raw_supply (regcache, SPARC32_PSR_REGNUM, buf);
+ }
+
+ if (regnum == SPARC32_PC_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC32_PC_REGNUM,
+ regs + gregset->r_pc_offset + 4);
+
+ if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC32_NPC_REGNUM,
+ regs + gregset->r_npc_offset + 4);
+
+ if (regnum == SPARC32_Y_REGNUM || regnum == -1)
+ {
+ int offset = gregset->r_y_offset + 8 - gregset->r_y_size;
+ regcache_raw_supply (regcache, SPARC32_Y_REGNUM, regs + offset);
+ }
+ }
+ else
+ {
+ if (regnum == SPARC64_STATE_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC64_STATE_REGNUM,
+ regs + gregset->r_tstate_offset);
+
+ if (regnum == SPARC64_PC_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC64_PC_REGNUM,
+ regs + gregset->r_pc_offset);
+
+ if (regnum == SPARC64_NPC_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC64_NPC_REGNUM,
+ regs + gregset->r_npc_offset);
+
+ if (regnum == SPARC64_Y_REGNUM || regnum == -1)
+ {
+ char buf[8];
+
+ memset (buf, 0, 8);
+ memcpy (buf + 8 - gregset->r_y_size,
+ regs + gregset->r_y_offset, gregset->r_y_size);
+ regcache_raw_supply (regcache, SPARC64_Y_REGNUM, buf);
+ }
+ }
+
+ if (regnum == SPARC_G0_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC_G0_REGNUM, NULL);
+
+ if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
+ {
+ int offset = gregset->r_g1_offset;
+
+ if (sparc32)
+ offset += 4;
+
+ for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
+ {
+ if (regnum == i || regnum == -1)
+ regcache_raw_supply (regcache, i, regs + offset);
+ offset += 8;
+ }
+ }
+
+ if ((regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) || regnum == -1)
+ {
+ /* Not all of the register set variants include Locals and
+ Inputs. For those that don't, we read them off the stack. */
+ if (gregset->r_l0_offset == -1)
+ {
+ ULONGEST sp;
+
+ regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
+ sparc_supply_rwindow (regcache, sp, regnum);
+ }
+ else
+ {
+ int offset = gregset->r_l0_offset;
+
+ if (sparc32)
+ offset += 4;
+
+ for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
+ {
+ if (regnum == i || regnum == -1)
+ regcache_raw_supply (regcache, i, regs + offset);
+ offset += 8;
+ }
+ }
+ }
+}
+
+void
+sparc64_collect_gregset (const struct sparc_gregset *gregset,
+ const struct regcache *regcache,
+ int regnum, void *gregs)
+{
+ int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
+ char *regs = gregs;
+ int i;
+
+ if (sparc32)
+ {
+ if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
+ {
+ int offset = gregset->r_tstate_offset;
+ ULONGEST tstate, psr;
+ char buf[8];
+
+ tstate = extract_unsigned_integer (regs + offset, 8);
+ regcache_raw_collect (regcache, SPARC32_PSR_REGNUM, buf);
+ psr = extract_unsigned_integer (buf, 4);
+ tstate |= (psr & PSR_ICC) << 12;
+ if ((psr & (PSR_VERS | PSR_IMPL)) == PSR_V8PLUS)
+ tstate |= (psr & PSR_XCC) << 20;
+ store_unsigned_integer (buf, 8, tstate);
+ memcpy (regs + offset, buf, 8);
+ }
+
+ if (regnum == SPARC32_PC_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC32_PC_REGNUM,
+ regs + gregset->r_pc_offset + 4);
+
+ if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC32_NPC_REGNUM,
+ regs + gregset->r_npc_offset + 4);
+
+ if (regnum == SPARC32_Y_REGNUM || regnum == -1)
+ {
+ int offset = gregset->r_y_offset + 8 - gregset->r_y_size;
+ regcache_raw_collect (regcache, SPARC32_Y_REGNUM, regs + offset);
+ }
+ }
+ else
+ {
+ if (regnum == SPARC64_STATE_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC64_STATE_REGNUM,
+ regs + gregset->r_tstate_offset);
+
+ if (regnum == SPARC64_PC_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC64_PC_REGNUM,
+ regs + gregset->r_pc_offset);
+
+ if (regnum == SPARC64_NPC_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC64_NPC_REGNUM,
+ regs + gregset->r_npc_offset);
+
+ if (regnum == SPARC64_Y_REGNUM || regnum == -1)
+ {
+ char buf[8];
+
+ regcache_raw_collect (regcache, SPARC64_Y_REGNUM, buf);
+ memcpy (regs + gregset->r_y_offset,
+ buf + 8 - gregset->r_y_size, gregset->r_y_size);
+ }
+ }
+
+ if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
+ {
+ int offset = gregset->r_g1_offset;
+
+ if (sparc32)
+ offset += 4;
+
+ /* %g0 is always zero. */
+ for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
+ {
+ if (regnum == i || regnum == -1)
+ regcache_raw_collect (regcache, i, regs + offset);
+ offset += 8;
+ }
+ }
+
+ if ((regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) || regnum == -1)
+ {
+ /* Not all of the register set variants include Locals and
+ Inputs. For those that don't, we read them off the stack. */
+ if (gregset->r_l0_offset != -1)
+ {
+ int offset = gregset->r_l0_offset;
+
+ if (sparc32)
+ offset += 4;
+
+ for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
+ {
+ if (regnum == i || regnum == -1)
+ regcache_raw_collect (regcache, i, regs + offset);
+ offset += 8;
+ }
+ }
+ }
+}
+
+void
+sparc64_supply_fpregset (struct regcache *regcache,
+ int regnum, const void *fpregs)
+{
+ int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
+ const char *regs = fpregs;
+ int i;
+
+ for (i = 0; i < 32; i++)
+ {
+ if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
+ regcache_raw_supply (regcache, SPARC_F0_REGNUM + i, regs + (i * 4));
+ }
+
+ if (sparc32)
+ {
+ if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC32_FSR_REGNUM,
+ regs + (32 * 4) + (16 * 8) + 4);
+ }
+ else
+ {
+ for (i = 0; i < 16; i++)
+ {
+ if (regnum == (SPARC64_F32_REGNUM + i) || regnum == -1)
+ regcache_raw_supply (regcache, SPARC64_F32_REGNUM + i,
+ regs + (32 * 4) + (i * 8));
+ }
+
+ if (regnum == SPARC64_FSR_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC64_FSR_REGNUM,
+ regs + (32 * 4) + (16 * 8));
+ }
+}
+
+void
+sparc64_collect_fpregset (const struct regcache *regcache,
+ int regnum, void *fpregs)
+{
+ int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
+ char *regs = fpregs;
+ int i;
+
+ for (i = 0; i < 32; i++)
+ {
+ if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
+ regcache_raw_collect (regcache, SPARC_F0_REGNUM + i, regs + (i * 4));
+ }
+
+ if (sparc32)
+ {
+ if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC32_FSR_REGNUM,
+ regs + (32 * 4) + (16 * 8) + 4);
+ }
+ else
+ {
+ for (i = 0; i < 16; i++)
+ {
+ if (regnum == (SPARC64_F32_REGNUM + i) || regnum == -1)
+ regcache_raw_collect (regcache, SPARC64_F32_REGNUM + i,
+ regs + (32 * 4) + (i * 8));
+ }
+
+ if (regnum == SPARC64_FSR_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC64_FSR_REGNUM,
+ regs + (32 * 4) + (16 * 8));
+ }
}
Index: sparc64-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/sparc64-tdep.h,v
retrieving revision 1.2.6.1
diff -u -p -r1.2.6.1 sparc64-tdep.h
--- sparc64-tdep.h 18 Oct 2003 18:25:46 -0000 1.2.6.1
+++ sparc64-tdep.h 2 Nov 2003 20:22:35 -0000
@@ -24,6 +24,11 @@
#include "sparc-tdep.h"
+/* Register offsets for the general-purpose register set. */
+
+/* UltraSPARC doesn't have %psr. */
+#define r_tstate_offset r_psr_offset
+
/* Register numbers of various important registers. */
enum sparc64_regnum
@@ -66,6 +71,25 @@ enum sparc64_regnum
extern void sparc64_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch);
+
+extern void sparc64_supply_gregset (const struct sparc_gregset *gregset,
+ struct regcache *regcache,
+ int regnum, const void *gregs);
+extern void sparc64_collect_gregset (const struct sparc_gregset *gregset,
+ const struct regcache *regcache,
+ int regnum, void *gregs);
+extern void sparc64_supply_fpregset (struct regcache *regcache,
+ int regnum, const void *fpregs);
+extern void sparc64_collect_fpregset (const struct regcache *regcache,
+ int regnum, void *fpregs);
+
+/* Functions and variables exported from sparc64-sol2-tdep.c. */
+
+/* Register offsets for Solaris 2. */
+extern const struct sparc_gregset sparc64_sol2_gregset;
+
+extern void sparc64_sol2_init_abi (struct gdbarch_info info,
+ struct gdbarch *gdbarch);
/* Functions exported from sparc64fbsd-tdep.c. */
Index: config/sparc/linux64.mh
===================================================================
RCS file: config/sparc/linux64.mh
diff -N config/sparc/linux64.mh
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ config/sparc/linux64.mh 2 Nov 2003 20:22:35 -0000
@@ -0,0 +1,11 @@
+# Host: GNU/Linux UltraSPARC
+NAT_FILE= nm-linux.h
+NATDEPFILES= sparc-nat.o sparc64-nat.o sparc64-sol2-nat.o sparc64-linux-nat.o \
+ corelow.o core-regset.o \
+ fork-child.o infptrace.o inftarg.o \
+ proc-service.o thread-db.o lin-lwp.o \
+ linux-proc.o gcore.o linux-nat.o
+
+# The dynamically loaded libthread_db needs access to symbols in the
+# gdb executable.
+LOADLIBES = -ldl -rdynamic
Index: config/sparc/linux64.mt
===================================================================
RCS file: config/sparc/linux64.mt
diff -N config/sparc/linux64.mt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ config/sparc/linux64.mt 2 Nov 2003 20:22:35 -0000
@@ -0,0 +1,5 @@
+# Target: GNU/Linux UltraSPARC
+TDEPFILES= sparc64-tdep.o sparc64-sol2-tdep.o sparc64-linux-tdep.o \
+ sparc-tdep.o sparc-sol2-tdep.o sparc-linux-tdep.o \
+ solib.o solib-svr4.o solib-legacy.o
+TM_FILE= tm-linux.h