[PATCH 2/5] gdbserver for nds32

Wei-cheng Wang cole945@gmail.com
Mon Jul 8 09:28:00 GMT 2013


2013-07-08  Wei-Cheng Wang  <cole945@gmail.com>

	* Makefine.in (SFILES): Add linux-nds32-low.c.
	(nds32-linux.c, nds32-freg0-linux.c, nds32-freg1-linux.c
	nds32-freg2-linux.c, nds32-freg3-linux.c): New.
	(clean): nds32-linux.c, nds32-freg0-linux.c, nds32-freg1-linux.c
	nds32-freg2-linux.c and nds32-freg3-linux.c.
	* configure.srv (nds32*-*-linux*): New target.
	* linux-nds32-low.c: New file.

---

diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 2cbf208..de08744 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -143,6 +143,7 @@ SFILES=	$(srcdir)/gdbreplay.c
$(srcdir)/inferiors.c $(srcdir)/dll.c \
 	$(srcdir)/linux-ia64-low.c $(srcdir)/linux-low.c \
 	$(srcdir)/linux-m32r-low.c \
 	$(srcdir)/linux-m68k-low.c $(srcdir)/linux-mips-low.c \
+	$(srcdir)/linux-nds32-low.c \
 	$(srcdir)/linux-nios2-low.c \
 	$(srcdir)/linux-ppc-low.c \
 	$(srcdir)/linux-s390-low.c \
@@ -318,6 +319,8 @@ clean:
 	rm -f $(IPA_LIB)
 	rm -f aarch64.c
 	rm -f reg-arm.c reg-bfin.c i386.c reg-ia64.c reg-m32r.c reg-m68k.c
+	rm -f nds32-linux.c nds32-freg0-linux.c nds32-freg1-linux.c
+	rm -f nds32-freg2-linux.c nds32-freg3-linux.c
 	rm -f reg-sh.c reg-sparc.c reg-spu.c amd64.c i386-linux.c
 	rm -f reg-cris.c reg-crisv32.c amd64-linux.c reg-xtensa.c
 	rm -f reg-tilegx.c reg-tilegx32.c
@@ -612,6 +615,16 @@ mips64-linux.c :
$(srcdir)/../regformats/mips64-linux.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips64-linux.dat mips64-linux.c
 mips64-dsp-linux.c : $(srcdir)/../regformats/mips64-dsp-linux.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips64-dsp-linux.dat
mips64-dsp-linux.c
+nds32-linux.c : $(srcdir)/../regformats/nds32-linux.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/nds32-linux.dat nds32-linux.c
+nds32-freg0-linux.c : $(srcdir)/../regformats/nds32-freg0-linux.dat
$(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/nds32-freg0-linux.dat
nds32-freg0-linux.c
+nds32-freg1-linux.c : $(srcdir)/../regformats/nds32-freg1-linux.dat
$(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/nds32-freg1-linux.dat
nds32-freg1-linux.c
+nds32-freg2-linux.c : $(srcdir)/../regformats/nds32-freg2-linux.dat
$(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/nds32-freg2-linux.dat
nds32-freg2-linux.c
+nds32-freg3-linux.c : $(srcdir)/../regformats/nds32-freg3-linux.dat
$(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/nds32-freg3-linux.dat
nds32-freg3-linux.c
 nios2-linux.c :	$(srcdir)/../regformats/nios2-linux.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/nios2-linux.dat nios2-linux.c
 powerpc-32.c : $(srcdir)/../regformats/rs6000/powerpc-32.dat $(regdat_sh)
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index 879d0de..5991609 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -209,6 +209,23 @@ case "${target}" in
 			srv_linux_usrregs=yes
 			srv_linux_thread_db=yes
 			;;
+  nds32*-*-linux*)	srv_regobj="nds32-linux.o"
+			srv_regobj="${srv_regobj} nds32-freg0-linux.o"
+			srv_regobj="${srv_regobj} nds32-freg1-linux.o"
+			srv_regobj="${srv_regobj} nds32-freg2-linux.o"
+			srv_regobj="${srv_regobj} nds32-freg3-linux.o"
+			srv_tgtobj="linux-low.o linux-osdata.o linux-nds32-low.o linux-procfs.o"
+			srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+			srv_xmlfiles="nds32-linux.xml"
+			srv_xmlfiles="${srv_xmlfiles} nds32-core.xml"
+			srv_xmlfiles="${srv_xmlfiles} nds32-freg0.xml"
+			srv_xmlfiles="${srv_xmlfiles} nds32-freg1.xml"
+			srv_xmlfiles="${srv_xmlfiles} nds32-freg2.xml"
+			srv_xmlfiles="${srv_xmlfiles} nds32-freg3.xml"
+			srv_linux_usrregs=yes
+			srv_linux_regsets=yes
+			srv_linux_thread_db=yes
+			;;
   powerpc*-*-linux*)	srv_regobj="powerpc-32l.o"
 			srv_regobj="${srv_regobj} powerpc-altivec32l.o"
 			srv_regobj="${srv_regobj} powerpc-cell32l.o"
diff --git a/gdb/gdbserver/linux-nds32-low.c b/gdb/gdbserver/linux-nds32-low.c
new file mode 100644
index 0000000..747a023
--- /dev/null
+++ b/gdb/gdbserver/linux-nds32-low.c
@@ -0,0 +1,284 @@
+/* GNU/Linux/NDS32 specific low level interface, for the remote server for
+   GDB.
+
+   Copyright (C) 2009-2013 Free Software Foundation, Inc.
+   Contributed by Andes Technology Corporation.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "server.h"
+#include "linux-low.h"
+
+#include <sys/ptrace.h>
+#include <elf.h>
+
+static int nds32_fpu_freg = -1;
+
+/* Defined in auto-generated files.  */
+void init_registers_nds32_linux (void);
+extern const struct target_desc *tdesc_nds32_linux;
+void init_registers_nds32_freg0_linux (void);
+extern const struct target_desc *tdesc_nds32_freg0_linux;
+void init_registers_nds32_freg1_linux (void);
+extern const struct target_desc *tdesc_nds32_freg1_linux;
+void init_registers_nds32_freg2_linux (void);
+extern const struct target_desc *tdesc_nds32_freg2_linux;
+void init_registers_nds32_freg3_linux (void);
+extern const struct target_desc *tdesc_nds32_freg3_linux;
+
+static int nds32_regmap[] = {
+
+  /* r0 - h1hi should match nds32.core.xml
+     in order to be compatible with nds32-elf */
+
+  /* r0 - r31 */
+  52, 56, 60, 64, 68, 72, 76, 80,
+  84, 88, 92, 96, 100, 104, 108, 112,
+  116, 120, 124, 128, 132, 136, 140, 144,
+  148, 152, -1, -1, 156, 160, 164, 12,
+
+  /* ipc(pc), d0lo, d0hi, d1lo, d1hi */
+  8, 40, 36, 48, 44,
+
+  /* nds32-linux only in nds32.linux */
+  /* orig_r0, fucop */
+  16, 168
+};
+#define nds32_num_regs (sizeof (nds32_regmap) / sizeof (nds32_regmap[0]))
+
+static const unsigned char NDS32_BREAK[] = { 0x64, 0x00, 0x00, 0x0A };
+static const unsigned char NDS32_BREAK16[] = { 0xEA, 0x00 };
+
+static int
+nds32_cannot_store_register (int regno)
+{
+  return (regno >= nds32_num_regs);
+}
+
+static int
+nds32_cannot_fetch_register (int regno)
+{
+  return (regno >= nds32_num_regs);
+}
+
+static void
+nds32_fill_gregset (struct regcache *regcache, void *buf)
+{
+  int i;
+
+  for (i = 0; i < nds32_num_regs; i++)
+    if (nds32_regmap[i] != -1)
+      collect_register (regcache, i, ((char *) buf) + nds32_regmap[i]);
+}
+
+static void
+nds32_store_gregset (struct regcache *regcache, const void *buf)
+{
+  int i;
+  char zerobuf[8];
+
+  memset (zerobuf, 0, 8);
+  for (i = 0; i < nds32_num_regs; i++)
+    if (nds32_regmap[i] != -1)
+      supply_register (regcache, i, ((char *) buf) + nds32_regmap[i]);
+    else
+      supply_register (regcache, i, zerobuf);
+}
+
+static void
+nds32_fill_fpregset (struct regcache *regcache, void *buf)
+{
+  int i, num, base;
+
+  num = 4 << nds32_fpu_freg;
+  base = find_regno (regcache->tdesc, "fd0");
+  for (i = 0; i < num; i++)
+    collect_register (regcache, base + i, (char *) buf + i * 8);
+
+  collect_register_by_name (regcache, "fpscr", (char *) buf + 32 * 8);
+}
+
+static void
+nds32_store_fpregset (struct regcache *regcache, const void *buf)
+{
+  int i, num, base;
+
+  num = 4 << nds32_fpu_freg;
+  base = find_regno (regcache->tdesc, "fd0");
+  for (i = 0; i < num; i++)
+    supply_register (regcache, base + i, (char *) buf + i * 8);
+
+  supply_register_by_name (regcache, "fpscr", (char *) buf + 32 * 8);
+}
+
+extern int debug_threads;
+
+static CORE_ADDR
+nds32_get_pc (struct regcache *regcache)
+{
+  unsigned long pc;
+  collect_register_by_name (regcache, "pc", &pc);
+  if (debug_threads)
+    fprintf (stderr, "stop pc is %08lx\n", pc);
+  return pc;
+}
+
+static void
+nds32_set_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  unsigned long newpc = pc;
+  supply_register_by_name (regcache, "pc", &newpc);
+}
+
+static int
+nds32_breakpoint_at (CORE_ADDR where)
+{
+  unsigned char insn[4];
+
+  (*the_target->read_memory) (where, insn, 4);
+
+  if (memcmp (insn, NDS32_BREAK, 4) == 0)
+    return 1;
+  else if (memcmp (insn, NDS32_BREAK16, 2) == 0)
+    return 1;
+  else
+    return 0;
+}
+
+/* We only place breakpoints in empty marker functions, and thread locking
+   is outside of the function.  So rather than importing software single-step,
+   we can just run until exit.  */
+
+static CORE_ADDR
+nds32_reinsert_addr (void)
+{
+  struct regcache *regcache = get_thread_regcache (current_inferior, 1);
+  unsigned long pc;
+
+  collect_register_by_name (regcache, "lp", &pc);
+  return pc;
+}
+
+static void
+nds32_arch_setup (void)
+{
+  const struct target_desc *tdesc = tdesc_nds32_linux;
+
+  nds32_fpu_freg = -1;
+
+#if defined (__NDS32_EXT_FPU_SP__) || defined (__NDS32_EXT_FPU_DP__)
+    {
+      /* To find out the FPU register configuration, we should 1. Check whether
+	 COP/FPU extensions if set in CPU_VER.CFGID. 2. Check whether CP0EX and
+	 CP0ISFPU are set in CUCOP_EXIST. 3. Check FPCFG.FREG with fmfcfg
+	 instruction.
+
+	 If COP/FPU doesn't exist, executing fmfcfg will cause
+	 reserved-instruction exception.  However, both CPU_VER and CUCOP_EXIST
+	 are system registers and inaccessible from user programs.  In the
+	 future, kernel should provide these information through AUXV HWCAP.
+	 Currently, we only check whether FPU SP/DP Extension is set.  */
+
+      int fpcfg = 0;
+
+      __asm__ ("fmfcfg %0\n\t" : "=r" (fpcfg));
+      nds32_fpu_freg = (fpcfg >> 2) & 0x3;
+    }
+
+  switch (nds32_fpu_freg)
+    {
+    case 0:
+      tdesc = tdesc_nds32_freg0_linux;
+      break;
+    case 1:
+      tdesc = tdesc_nds32_freg1_linux;
+      break;
+    case 2:
+      tdesc = tdesc_nds32_freg2_linux;
+      break;
+    case 3:
+      tdesc = tdesc_nds32_freg3_linux;
+      break;
+    }
+#endif
+
+  current_process ()->tdesc = tdesc;
+}
+
+/* used by linux-low.c for PTRACE_[GS]ETREGS */
+static struct regset_info nds32_regsets[] = {
+  { PTRACE_GETREGS, PTRACE_SETREGS, 0, 18 * 4,
+    GENERAL_REGS,
+    nds32_fill_gregset, nds32_store_gregset },
+  { PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, 32 * 8 + 4,
+    EXTENDED_REGS,
+    nds32_fill_fpregset, nds32_store_fpregset },
+  { 0, 0, 0, -1, -1, NULL, NULL }
+};
+
+static struct regsets_info nds32_regsets_info =
+{
+  nds32_regsets, /* regsets */
+  0, /* num_regsets */
+  NULL, /* disabled_regsets */
+};
+
+static struct usrregs_info nds32_usrregs_info =
+{
+  nds32_num_regs,
+  nds32_regmap,
+};
+
+static struct regs_info regs_info =
+{
+  NULL, /* regset_bitmap */
+  &nds32_usrregs_info,
+  &nds32_regsets_info,
+};
+
+static const struct regs_info *
+nds32_regs_info (void)
+{
+  return &regs_info;
+}
+
+struct linux_target_ops the_low_target = {
+  nds32_arch_setup,
+  nds32_regs_info,
+  nds32_cannot_fetch_register,
+  nds32_cannot_store_register,
+  NULL, /* fetch_register */
+  nds32_get_pc,
+  nds32_set_pc,
+  NDS32_BREAK16,
+  sizeof(NDS32_BREAK16),
+  nds32_reinsert_addr,
+  0,
+  nds32_breakpoint_at,
+};
+
+void
+initialize_low_arch (void)
+{
+  /* Initialize the Linux target descriptions.  */
+  init_registers_nds32_linux ();
+  init_registers_nds32_freg0_linux ();
+  init_registers_nds32_freg1_linux ();
+  init_registers_nds32_freg2_linux ();
+  init_registers_nds32_freg3_linux ();
+
+  initialize_regsets_info (&nds32_regsets_info);
+}
--



More information about the Gdb-patches mailing list