From 15b8867d9ec82299441188388bbed4a7ca62eba6 Mon Sep 17 00:00:00 2001
From: Atle Nissestad <atle@nissestad.no>
Date: Mon, 3 Dec 2007 23:34:28 +0100
Subject: [PATCH] gdbserver: Added initial support for nios2 in gdbserver

Note: This is untested code and not expected to work as is.

Signed-off-by: Atle Nissestad <atle@nissestad.no>
---
 user/gdbserver/gdbserver/Makefile.in       |    4 +
 user/gdbserver/gdbserver/configure.srv     |    4 +
 user/gdbserver/gdbserver/linux-nios2-low.c |   88 ++++++++++++++++++++++++++++
 user/gdbserver/regformats/reg-nios2.dat    |   47 +++++++++++++++
 4 files changed, 143 insertions(+), 0 deletions(-)
 create mode 100644 user/gdbserver/gdbserver/linux-nios2-low.c
 create mode 100644 user/gdbserver/regformats/reg-nios2.dat

diff --git a/user/gdbserver/gdbserver/Makefile.in b/user/gdbserver/gdbserver/Makefile.in
index 429ca55..a5a3c9e 100644
--- a/user/gdbserver/gdbserver/Makefile.in
+++ b/user/gdbserver/gdbserver/Makefile.in
@@ -284,6 +284,7 @@ linux-ia64-low.o: linux-ia64-low.c $(linux_low_h) $(server_h)
 linux-m32r-low.o: linux-m32r-low.c $(linux_low_h) $(server_h)
 linux-mips-low.o: linux-mips-low.c $(linux_low_h) $(server_h) \
 	$(gdb_proc_service_h)
+linux-nios2-low.o: linux-nios2-low.c $(linux_low_h) $(server_h)
 linux-ppc-low.o: linux-ppc-low.c $(linux_low_h) $(server_h)
 linux-ppc64-low.o: linux-ppc64-low.c $(linux_low_h) $(server_h)
 linux-s390-low.o: linux-s390-low.c $(linux_low_h) $(server_h)
@@ -325,6 +326,9 @@ reg-m68k.c : $(srcdir)/../regformats/reg-m68k.dat $(regdat_sh)
 reg-mips.o : reg-mips.c $(regdef_h)
 reg-mips.c : $(srcdir)/../regformats/reg-mips.dat $(regdat_sh)
 	sh $(regdat_sh) $(srcdir)/../regformats/reg-mips.dat reg-mips.c
+reg-nios2.o : reg-nios2.c $(regdef_h)
+reg-nios2.c : $(srcdir)/../regformats/reg-nios2.dat $(regdat_sh)
+	sh $(regdat_sh) $(srcdir)/../regformats/reg-nios2.dat reg-nios2.c
 reg-ppc.o : reg-ppc.c $(regdef_h)
 reg-ppc.c : $(srcdir)/../regformats/reg-ppc.dat $(regdat_sh)
 	sh $(regdat_sh) $(srcdir)/../regformats/reg-ppc.dat reg-ppc.c
diff --git a/user/gdbserver/gdbserver/configure.srv b/user/gdbserver/gdbserver/configure.srv
index 42ab123..5abac70 100644
--- a/user/gdbserver/gdbserver/configure.srv
+++ b/user/gdbserver/gdbserver/configure.srv
@@ -77,6 +77,10 @@ case "${target}" in
 			srv_linux_usrregs=yes
 			srv_linux_thread_db=yes
 			;;
+  nios2-*-linux*)	srv_regobj=reg-nios2.o
+			srv_tgtobj="linux-low.o linux-nios2-low.o"
+			srv_linux_usrregs=yes
+			;;
   powerpc64-*-linux*)	srv_regobj=reg-ppc64.o
 			srv_tgtobj="linux-low.o linux-ppc64-low.o"
 			srv_linux_usrregs=yes
diff --git a/user/gdbserver/gdbserver/linux-nios2-low.c b/user/gdbserver/gdbserver/linux-nios2-low.c
new file mode 100644
index 0000000..4ea2b26
--- /dev/null
+++ b/user/gdbserver/gdbserver/linux-nios2-low.c
@@ -0,0 +1,88 @@
+/* GNU/Linux/Nios2 specific low level interface for the remote server for GDB */
+
+#include "server.h"
+#include "linux-low.h"
+
+#ifdef HAVE_SYS_REG_H
+#include <sys/reg.h>
+#endif
+
+#include <asm/ptrace.h>
+
+/* FIXME: Definitions in gdb/nios2-tdep.c and asm/ptrace.h does not quite agree... */
+static int nios2_regmap[] =
+{
+  PTR_R0  * 4, PTR_R1  * 4, PTR_R2  * 4, PTR_R3  * 4,
+  PTR_R4  * 4, PTR_R5  * 4, PTR_R6  * 4, PTR_R7  * 4,
+  PTR_R8  * 4, PTR_R9  * 4, PTR_R10 * 4, PTR_R11 * 4,
+  PTR_R12 * 4, PTR_R13 * 4, PTR_R14 * 4, PTR_R15 * 4,
+
+  PTR_R16 * 4, PTR_R17 * 4, PTR_R18 * 4, PTR_R19 * 4,
+  PTR_R20 * 4, PTR_R21 * 4, PTR_R22 * 4, PTR_R23 * 4,
+  PTR_R24 * 4, PTR_R25 * 4,
+
+  PTR_GP  * 4, PTR_SP  * 4, PTR_FP  * 4, PTR_EA  * 4,
+  PTR_BA  * 4, PTR_RA  * 4,
+  (PTR_RA + 1) * 4, (PTR_RA + 2) * 4, (PTR_RA + 3) * 4,
+  (PTR_RA + 4) * 4, (PTR_RA + 5) * 4, (PTR_RA + 6) * 4
+};
+
+#define nios2_num_regs (sizeof(nios2_regmap) / sizeof(nios2_regmap[0]))
+
+static int
+nios2_cannot_store_register (int regno)
+{
+  return (regno >= nios2_num_regs);
+}
+
+static int
+nios2_cannot_fetch_register (int regno)
+{
+  return (regno >= nios2_num_regs);
+}
+
+static CORE_ADDR
+nios2_get_pc ()
+{
+  unsigned long pc;
+  collect_register_by_name ("pc", &pc);
+  return pc;
+}
+
+static void
+nios2_set_pc (CORE_ADDR pc)
+{
+  unsigned long newpc = pc;
+  supply_register_by_name ("pc", &newpc);
+}
+
+static const unsigned long nios2_breakpoint = 0x003da03a;
+#define nios2_breakpoint_len 4
+
+static int
+nios2_breakpoint_at (CORE_ADDR where)
+{
+  unsigned long insn;
+
+  (*the_target->read_memory) (where, (char *) &insn, nios2_breakpoint_len);
+  if (insn == nios2_breakpoint)
+    return 1;
+
+  /* If necessary, recognize more trap instructions here.  GDB only uses the
+     one.  */
+  return 0;
+}
+
+struct linux_target_ops the_low_target = {
+  nios2_num_regs,
+  nios2_regmap,
+  nios2_cannot_fetch_register,
+  nios2_cannot_store_register,
+  nios2_get_pc,
+  nios2_set_pc,
+  (const char *) &nios2_breakpoint,
+  nios2_breakpoint_len,
+  NULL,
+  0,
+  nios2_breakpoint_at,
+};
diff --git a/user/gdbserver/regformats/reg-nios2.dat b/user/gdbserver/regformats/reg-nios2.dat
new file mode 100644
index 0000000..6881ad1
--- /dev/null
+++ b/user/gdbserver/regformats/reg-nios2.dat
@@ -0,0 +1,47 @@
+name:nios2
+expedite:sp,fp,pc
+32:zero
+32:at
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:r13
+32:r14
+32:r15
+32:r16
+32:r17
+32:r18
+32:r19
+32:r20
+32:r21
+32:r22
+32:r23
+32:et
+32:bt
+32:gp
+32:sp
+32:fp
+32:ea
+32:ba
+32:ra
+32:pc
+32:status
+32:estatus
+32:bstatus
+32:ienable
+32:ipending
+32:cpuid
+32:ctl6
+32:ctl7
+32:pteaddr
+32:tlbacc
+32:tlbmisc
+
-- 
1.5.3.3

