This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH 1/5] Code for nds32 target
- From: Wei-cheng Wang <cole945 at gmail dot com>
- To: gdb-patches at sourceware dot org
- Date: Mon, 8 Jul 2013 17:27:46 +0800
- Subject: [PATCH 1/5] Code for nds32 target
2013-07-08 Wei-Cheng Wang <cole945@gmail.com>
* Makefile.in (ALL_TARGET_OBS): Add nds32-tdep.o, nds32-linux-tdep.o,
nds32-utils.o and nds32-remote.o.
(ALLDEPFILES): Add nds32-tdep.c, nds32-linux-tdep.c, nds32-utils.c and
nds32-remote.c.
* configure.host: Add nds32*-linux* as host.
* configure.tgt: Add nds32* and nds32*-linux* as target.
* nds32-linux-nat.c: New file.
* nds32-linux-tdep.c: New file.
* nds32-linux-tdep.h: New file.
* nds32-remote.c: New file.
* nds32-remote.h: New file.
* nds32-tdep.c: New file.
* nds32-tdep.h: New file.
* nds32-utils.c: New file.
* nds32-utils.h: New file.
* config/nds32/linux.mh: New file.
* features/Makefile (WHICH): Add nds32-linux, nds32-freg0-linux,
nds32-freg1-linux and nds32-freg2-linux.
* features/nds32-linux.xml: New file.
* features/nds32-core.xml: New file.
* features/nds32-freg0.xml: New file.
* features/nds32-freg1.xml: New file.
* features/nds32-freg2.xml: New file.
* features/nds32-freg3.xml: New file.
* features/nds32-freg3-linux.xml: New file.
* features/nds32-freg0-linux.xml: New file.
* features/nds32-freg1-linux.xml: New file.
* features/nds32-freg2-linux.xml: New file.
* features/nds32-linux.c: New file (autogenerated).
* features/nds32-freg0-linux.c: New file (autogenerated).
* features/nds32-freg1-linux.c: New file (autogenerated).
* features/nds32-freg2-linux.c: New file (autogenerated).
* features/nds32-freg3-linux.c: New file (autogenerated).
* regformats/nds32-linux.dat: New file (autogenerated).
* regformats/nds32-freg0-linux.dat: New file (autogenerated).
* regformats/nds32-freg1-linux.dat: New file (autogenerated).
* regformats/nds32-freg2-linux.dat: New file (autogenerated).
* regformats/nds32-freg3-linux.dat: New file (autogenerated).
---
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 4694adc..a116fea 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -574,6 +574,7 @@ ALL_TARGET_OBS = \
moxie-tdep.o \
msp430-tdep.o \
mt-tdep.o \
+ nds32-tdep.o nds32-linux-tdep.o nds32-utils.o nds32-remote.o \
nios2-tdep.o nios2-linux-tdep.o \
nto-tdep.o \
ppc-linux-tdep.o ppcfbsd-tdep.o ppcnbsd-tdep.o ppcobsd-tdep.o \
@@ -1519,6 +1520,7 @@ ALLDEPFILES = \
mipsnbsd-nat.c mipsnbsd-tdep.c \
mips64obsd-nat.c mips64obsd-tdep.c \
msp430-tdep.c \
+ nds32-tdep.c nds32-linux-tdep.c nds32-utils.c nds32-remote.c \
nios2-tdep.c nios2-linux-tdep.c \
nbsd-nat.c nbsd-tdep.c obsd-tdep.c \
solib-osf.c \
diff --git a/gdb/config/nds32/linux.mh b/gdb/config/nds32/linux.mh
new file mode 100644
index 0000000..eab0e57
--- /dev/null
+++ b/gdb/config/nds32/linux.mh
@@ -0,0 +1,10 @@
+# Host: nds32 based machine running GNU/Linux
+
+NAT_FILE= config/nm-linux.h
+NATDEPFILES= inf-ptrace.o fork-child.o \
+ nds32-linux-nat.o \
+ proc-service.o linux-thread-db.o \
+ linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
+NAT_CDEPS = $(srcdir)/proc-service.list
+
+LOADLIBES= -ldl $(RDYNAMIC)
diff --git a/gdb/configure.host b/gdb/configure.host
index 85f4491..a4c4135 100644
--- a/gdb/configure.host
+++ b/gdb/configure.host
@@ -54,6 +54,7 @@ sh*) gdb_host_cpu=sh ;;
tilegx*) gdb_host_cpu=tilegx ;;
x86_64*) gdb_host_cpu=i386 ;;
m32r*) gdb_host_cpu=m32r ;;
+nds32*) gdb_host_cpu=nds32 ;;
xtensa*) gdb_host_cpu=xtensa ;;
*) gdb_host_cpu=$host_cpu ;;
@@ -126,6 +127,8 @@ mips*-*-netbsd* | mips*-*-knetbsd*-gnu)
gdb_host=nbsd ;;
mips64*-*-openbsd*) gdb_host=obsd64 ;;
+nds32*-linux*) gdb_host=linux ;;
+
powerpc-*-aix* | rs6000-*-*)
gdb_host=aix ;;
powerpc*-*-freebsd*) gdb_host=fbsd ;;
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 260a0df..a65f483 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -401,6 +401,20 @@ mt-*-*)
gdb_target_obs="mt-tdep.o"
;;
+nds32*-*-linux*)
+ # Target: GNU/Linux NDS32
+ gdb_target_obs="nds32-tdep.o nds32-linux-tdep.o nds32-utils.o nds32-remote.o \
+ glibc-tdep.o solib-svr4.o symfile-mem.o linux-tdep.o"
+ build_gdbserver=yes
+ gdb_sim=../sim/nds32/libsim.a
+ ;;
+
+nds32*)
+ # Target: AndesTech nds32 core
+ gdb_target_obs="nds32-tdep.o nds32-utils.o nds32-remote.o monitor.o dsrec.o"
+ gdb_sim=../sim/nds32/libsim.a
+ ;;
+
nios2*-*-linux*)
# Target: Altera Nios II running Linux
gdb_target_obs="nios2-tdep.o nios2-linux-tdep.o solib-svr4.o \
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index aee57d2..53f3bed 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -42,6 +42,8 @@ WHICH = aarch64 \
i386/x32-avx i386/x32-avx-linux \
mips-linux mips-dsp-linux \
mips64-linux mips64-dsp-linux \
+ nds32-linux nds32-freg0-linux nds32-freg1-linux nds32-freg2-linux \
+ nds32-freg3-linux \
nios2-linux \
rs6000/powerpc-32 \
rs6000/powerpc-32l rs6000/powerpc-altivec32l rs6000/powerpc-e500l \
@@ -74,6 +76,11 @@ mips-expedite = r29,pc
mips-dsp-expedite = r29,pc
mips64-expedite = r29,pc
mips64-dsp-expedite = r29,pc
+nds32-linux-expedite = fp,sp,pc
+nds32-freg0-linux-expedite = fp,sp,pc
+nds32-freg1-linux-expedite = fp,sp,pc
+nds32-freg2-linux-expedite = fp,sp,pc
+nds32-freg3-linux-expedite = fp,sp,pc
nios2-linux-expedite = sp,pc
powerpc-expedite = r1,pc
rs6000/powerpc-cell32l-expedite = r1,pc,r0,orig_r3,r4
diff --git a/gdb/features/feature_to_c.sh b/gdb/features/feature_to_c.sh
old mode 100644
new mode 100755
diff --git a/gdb/features/nds32-core.xml b/gdb/features/nds32-core.xml
new file mode 100644
index 0000000..8de8059
--- /dev/null
+++ b/gdb/features/nds32-core.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.nds32.core">
+ <reg name="r0" bitsize="32" regnum="0"/>
+ <reg name="r1" bitsize="32"/>
+ <reg name="r2" bitsize="32"/>
+ <reg name="r3" bitsize="32"/>
+ <reg name="r4" bitsize="32"/>
+ <reg name="r5" bitsize="32"/>
+ <reg name="r6" bitsize="32"/>
+ <reg name="r7" bitsize="32"/>
+ <reg name="r8" bitsize="32"/>
+ <reg name="r9" bitsize="32"/>
+ <reg name="r10" bitsize="32"/>
+ <reg name="r11" bitsize="32"/>
+ <reg name="r12" bitsize="32"/>
+ <reg name="r13" bitsize="32"/>
+ <reg name="r14" bitsize="32"/>
+ <reg name="r15" bitsize="32" regnum="15"/>
+ <reg name="r16" bitsize="32"/>
+ <reg name="r17" bitsize="32"/>
+ <reg name="r18" bitsize="32"/>
+ <reg name="r19" bitsize="32"/>
+ <reg name="r20" bitsize="32"/>
+ <reg name="r21" bitsize="32"/>
+ <reg name="r22" bitsize="32"/>
+ <reg name="r23" bitsize="32"/>
+ <reg name="r24" bitsize="32"/>
+ <reg name="r25" bitsize="32"/>
+ <!-- r26, r27 is reserved for linux kernel
+ keep the space for compatibility,
+ but hide them from users -->
+ <reg name="" bitsize="32"/>
+ <reg name="" bitsize="32"/>
+
+ <reg name="fp" bitsize="32" type="data_ptr" regnum="28"/>
+ <reg name="gp" bitsize="32" type="data_ptr"/>
+ <reg name="lp" bitsize="32" type="code_ptr"/>
+ <reg name="sp" bitsize="32" type="data_ptr"/>
+
+ <reg name="pc" bitsize="32" type="code_ptr"/>
+
+ <reg name="d0lo" bitsize="32"/>
+ <reg name="d0hi" bitsize="32"/>
+ <reg name="d1lo" bitsize="32"/>
+ <reg name="d1hi" bitsize="32"/>
+
+ <reg name="orig_r0" bitsize="32" regnum="37" group="system"/>
+ <reg name="fucpr" bitsize="32" regnum="38" group="system"/>
+</feature>
diff --git a/gdb/features/nds32-freg0-linux.c b/gdb/features/nds32-freg0-linux.c
new file mode 100644
index 0000000..ecea1ce
--- /dev/null
+++ b/gdb/features/nds32-freg0-linux.c
@@ -0,0 +1,67 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: nds32-freg0-linux.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_nds32_freg0_linux;
+static void
+initialize_tdesc_nds32_freg0_linux (void)
+{
+ struct target_desc *result = allocate_target_description ();
+ struct tdesc_feature *feature;
+
+ set_tdesc_architecture (result, bfd_scan_arch ("n1h"));
+
+ set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.nds32.core");
+ tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "", 26, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "", 27, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "fp", 28, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "gp", 29, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "lp", 30, 1, NULL, 32, "code_ptr");
+ tdesc_create_reg (feature, "sp", 31, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "pc", 32, 1, NULL, 32, "code_ptr");
+ tdesc_create_reg (feature, "d0lo", 33, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d0hi", 34, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d1lo", 35, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d1hi", 36, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "orig_r0", 37, 1, "system", 32, "int");
+ tdesc_create_reg (feature, "fucpr", 38, 1, "system", 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.nds32.fpu");
+ tdesc_create_reg (feature, "fd0", 39, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd1", 40, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd2", 41, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd3", 42, 1, NULL, 64, "ieee_single");
+
+ tdesc_nds32_freg0_linux = result;
+}
diff --git a/gdb/features/nds32-freg0-linux.xml
b/gdb/features/nds32-freg0-linux.xml
new file mode 100644
index 0000000..5af24d0
--- /dev/null
+++ b/gdb/features/nds32-freg0-linux.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>nds32</architecture>
+ <osabi>GNU/Linux</osabi>
+ <xi:include href="nds32-core.xml"/>
+ <xi:include href="nds32-freg0.xml"/>
+</target>
diff --git a/gdb/features/nds32-freg0.xml b/gdb/features/nds32-freg0.xml
new file mode 100644
index 0000000..2287222
--- /dev/null
+++ b/gdb/features/nds32-freg0.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.nds32.fpu">
+ <reg name="fd0" bitsize="64" type="ieee_single"/>
+ <reg name="fd1" bitsize="64" type="ieee_single"/>
+ <reg name="fd2" bitsize="64" type="ieee_single"/>
+ <reg name="fd3" bitsize="64" type="ieee_single"/>
+</feature>
diff --git a/gdb/features/nds32-freg1-linux.c b/gdb/features/nds32-freg1-linux.c
new file mode 100644
index 0000000..8023081
--- /dev/null
+++ b/gdb/features/nds32-freg1-linux.c
@@ -0,0 +1,71 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: nds32-freg1-linux.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_nds32_freg1_linux;
+static void
+initialize_tdesc_nds32_freg1_linux (void)
+{
+ struct target_desc *result = allocate_target_description ();
+ struct tdesc_feature *feature;
+
+ set_tdesc_architecture (result, bfd_scan_arch ("n1h"));
+
+ set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.nds32.core");
+ tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "", 26, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "", 27, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "fp", 28, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "gp", 29, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "lp", 30, 1, NULL, 32, "code_ptr");
+ tdesc_create_reg (feature, "sp", 31, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "pc", 32, 1, NULL, 32, "code_ptr");
+ tdesc_create_reg (feature, "d0lo", 33, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d0hi", 34, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d1lo", 35, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d1hi", 36, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "orig_r0", 37, 1, "system", 32, "int");
+ tdesc_create_reg (feature, "fucpr", 38, 1, "system", 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.nds32.fpu");
+ tdesc_create_reg (feature, "fd0", 39, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd1", 40, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd2", 41, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd3", 42, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd4", 43, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd5", 44, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd6", 45, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd7", 46, 1, NULL, 64, "ieee_single");
+
+ tdesc_nds32_freg1_linux = result;
+}
diff --git a/gdb/features/nds32-freg1-linux.xml
b/gdb/features/nds32-freg1-linux.xml
new file mode 100644
index 0000000..656e3b9
--- /dev/null
+++ b/gdb/features/nds32-freg1-linux.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>nds32</architecture>
+ <osabi>GNU/Linux</osabi>
+ <xi:include href="nds32-core.xml"/>
+ <xi:include href="nds32-freg1.xml"/>
+</target>
diff --git a/gdb/features/nds32-freg1.xml b/gdb/features/nds32-freg1.xml
new file mode 100644
index 0000000..1d0dfd2
--- /dev/null
+++ b/gdb/features/nds32-freg1.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.nds32.fpu">
+ <reg name="fd0" bitsize="64" type="ieee_single"/>
+ <reg name="fd1" bitsize="64" type="ieee_single"/>
+ <reg name="fd2" bitsize="64" type="ieee_single"/>
+ <reg name="fd3" bitsize="64" type="ieee_single"/>
+ <reg name="fd4" bitsize="64" type="ieee_single"/>
+ <reg name="fd5" bitsize="64" type="ieee_single"/>
+ <reg name="fd6" bitsize="64" type="ieee_single"/>
+ <reg name="fd7" bitsize="64" type="ieee_single"/>
+</feature>
diff --git a/gdb/features/nds32-freg2-linux.c b/gdb/features/nds32-freg2-linux.c
new file mode 100644
index 0000000..9640710
--- /dev/null
+++ b/gdb/features/nds32-freg2-linux.c
@@ -0,0 +1,79 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: nds32-freg2-linux.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_nds32_freg2_linux;
+static void
+initialize_tdesc_nds32_freg2_linux (void)
+{
+ struct target_desc *result = allocate_target_description ();
+ struct tdesc_feature *feature;
+
+ set_tdesc_architecture (result, bfd_scan_arch ("n1h"));
+
+ set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.nds32.core");
+ tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "", 26, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "", 27, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "fp", 28, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "gp", 29, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "lp", 30, 1, NULL, 32, "code_ptr");
+ tdesc_create_reg (feature, "sp", 31, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "pc", 32, 1, NULL, 32, "code_ptr");
+ tdesc_create_reg (feature, "d0lo", 33, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d0hi", 34, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d1lo", 35, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d1hi", 36, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "orig_r0", 37, 1, "system", 32, "int");
+ tdesc_create_reg (feature, "fucpr", 38, 1, "system", 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.nds32.fpu");
+ tdesc_create_reg (feature, "fd0", 39, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd1", 40, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd2", 41, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd3", 42, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd4", 43, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd5", 44, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd6", 45, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd7", 46, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd8", 47, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd9", 48, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd10", 49, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd11", 50, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd12", 51, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd13", 52, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd14", 53, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd15", 54, 1, NULL, 64, "ieee_single");
+
+ tdesc_nds32_freg2_linux = result;
+}
diff --git a/gdb/features/nds32-freg2-linux.xml
b/gdb/features/nds32-freg2-linux.xml
new file mode 100644
index 0000000..8fa0e0d
--- /dev/null
+++ b/gdb/features/nds32-freg2-linux.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>nds32</architecture>
+ <osabi>GNU/Linux</osabi>
+ <xi:include href="nds32-core.xml"/>
+ <xi:include href="nds32-freg2.xml"/>
+</target>
diff --git a/gdb/features/nds32-freg2.xml b/gdb/features/nds32-freg2.xml
new file mode 100644
index 0000000..6b4c1d3
--- /dev/null
+++ b/gdb/features/nds32-freg2.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.nds32.fpu">
+ <reg name="fd0" bitsize="64" type="ieee_single"/>
+ <reg name="fd1" bitsize="64" type="ieee_single"/>
+ <reg name="fd2" bitsize="64" type="ieee_single"/>
+ <reg name="fd3" bitsize="64" type="ieee_single"/>
+ <reg name="fd4" bitsize="64" type="ieee_single"/>
+ <reg name="fd5" bitsize="64" type="ieee_single"/>
+ <reg name="fd6" bitsize="64" type="ieee_single"/>
+ <reg name="fd7" bitsize="64" type="ieee_single"/>
+ <reg name="fd8" bitsize="64" type="ieee_single"/>
+ <reg name="fd9" bitsize="64" type="ieee_single"/>
+ <reg name="fd10" bitsize="64" type="ieee_single"/>
+ <reg name="fd11" bitsize="64" type="ieee_single"/>
+ <reg name="fd12" bitsize="64" type="ieee_single"/>
+ <reg name="fd13" bitsize="64" type="ieee_single"/>
+ <reg name="fd14" bitsize="64" type="ieee_single"/>
+ <reg name="fd15" bitsize="64" type="ieee_single"/>
+</feature>
diff --git a/gdb/features/nds32-freg3-linux.c b/gdb/features/nds32-freg3-linux.c
new file mode 100644
index 0000000..f0dc18b
--- /dev/null
+++ b/gdb/features/nds32-freg3-linux.c
@@ -0,0 +1,95 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: nds32-freg3-linux.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_nds32_freg3_linux;
+static void
+initialize_tdesc_nds32_freg3_linux (void)
+{
+ struct target_desc *result = allocate_target_description ();
+ struct tdesc_feature *feature;
+
+ set_tdesc_architecture (result, bfd_scan_arch ("n1h"));
+
+ set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.nds32.core");
+ tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "", 26, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "", 27, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "fp", 28, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "gp", 29, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "lp", 30, 1, NULL, 32, "code_ptr");
+ tdesc_create_reg (feature, "sp", 31, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "pc", 32, 1, NULL, 32, "code_ptr");
+ tdesc_create_reg (feature, "d0lo", 33, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d0hi", 34, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d1lo", 35, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d1hi", 36, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "orig_r0", 37, 1, "system", 32, "int");
+ tdesc_create_reg (feature, "fucpr", 38, 1, "system", 32, "int");
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.nds32.fpu");
+ tdesc_create_reg (feature, "fd0", 39, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd1", 40, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd2", 41, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd3", 42, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd4", 43, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd5", 44, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd6", 45, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd7", 46, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd8", 47, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd9", 48, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd10", 49, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd11", 50, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd12", 51, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd13", 52, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd14", 53, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd15", 54, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd16", 55, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd17", 56, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd18", 57, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd19", 58, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd20", 59, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd21", 60, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd22", 61, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd23", 62, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd24", 63, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd25", 64, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd26", 65, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd27", 66, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd28", 67, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd29", 68, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd30", 69, 1, NULL, 64, "ieee_single");
+ tdesc_create_reg (feature, "fd31", 70, 1, NULL, 64, "ieee_single");
+
+ tdesc_nds32_freg3_linux = result;
+}
diff --git a/gdb/features/nds32-freg3-linux.xml
b/gdb/features/nds32-freg3-linux.xml
new file mode 100644
index 0000000..b472420
--- /dev/null
+++ b/gdb/features/nds32-freg3-linux.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>nds32</architecture>
+ <osabi>GNU/Linux</osabi>
+ <xi:include href="nds32-core.xml"/>
+ <xi:include href="nds32-freg3.xml"/>
+</target>
diff --git a/gdb/features/nds32-freg3.xml b/gdb/features/nds32-freg3.xml
new file mode 100644
index 0000000..766e570
--- /dev/null
+++ b/gdb/features/nds32-freg3.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.nds32.fpu">
+ <reg name="fd0" bitsize="64" type="ieee_single"/>
+ <reg name="fd1" bitsize="64" type="ieee_single"/>
+ <reg name="fd2" bitsize="64" type="ieee_single"/>
+ <reg name="fd3" bitsize="64" type="ieee_single"/>
+ <reg name="fd4" bitsize="64" type="ieee_single"/>
+ <reg name="fd5" bitsize="64" type="ieee_single"/>
+ <reg name="fd6" bitsize="64" type="ieee_single"/>
+ <reg name="fd7" bitsize="64" type="ieee_single"/>
+ <reg name="fd8" bitsize="64" type="ieee_single"/>
+ <reg name="fd9" bitsize="64" type="ieee_single"/>
+ <reg name="fd10" bitsize="64" type="ieee_single"/>
+ <reg name="fd11" bitsize="64" type="ieee_single"/>
+ <reg name="fd12" bitsize="64" type="ieee_single"/>
+ <reg name="fd13" bitsize="64" type="ieee_single"/>
+ <reg name="fd14" bitsize="64" type="ieee_single"/>
+ <reg name="fd15" bitsize="64" type="ieee_single"/>
+ <reg name="fd16" bitsize="64" type="ieee_single"/>
+ <reg name="fd17" bitsize="64" type="ieee_single"/>
+ <reg name="fd18" bitsize="64" type="ieee_single"/>
+ <reg name="fd19" bitsize="64" type="ieee_single"/>
+ <reg name="fd20" bitsize="64" type="ieee_single"/>
+ <reg name="fd21" bitsize="64" type="ieee_single"/>
+ <reg name="fd22" bitsize="64" type="ieee_single"/>
+ <reg name="fd23" bitsize="64" type="ieee_single"/>
+ <reg name="fd24" bitsize="64" type="ieee_single"/>
+ <reg name="fd25" bitsize="64" type="ieee_single"/>
+ <reg name="fd26" bitsize="64" type="ieee_single"/>
+ <reg name="fd27" bitsize="64" type="ieee_single"/>
+ <reg name="fd28" bitsize="64" type="ieee_single"/>
+ <reg name="fd29" bitsize="64" type="ieee_single"/>
+ <reg name="fd30" bitsize="64" type="ieee_single"/>
+ <reg name="fd31" bitsize="64" type="ieee_single"/>
+</feature>
diff --git a/gdb/features/nds32-linux.c b/gdb/features/nds32-linux.c
new file mode 100644
index 0000000..3dee14d
--- /dev/null
+++ b/gdb/features/nds32-linux.c
@@ -0,0 +1,61 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: nds32-linux.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_nds32_linux;
+static void
+initialize_tdesc_nds32_linux (void)
+{
+ struct target_desc *result = allocate_target_description ();
+ struct tdesc_feature *feature;
+
+ set_tdesc_architecture (result, bfd_scan_arch ("n1h"));
+
+ set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.nds32.core");
+ tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "", 26, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "", 27, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "fp", 28, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "gp", 29, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "lp", 30, 1, NULL, 32, "code_ptr");
+ tdesc_create_reg (feature, "sp", 31, 1, NULL, 32, "data_ptr");
+ tdesc_create_reg (feature, "pc", 32, 1, NULL, 32, "code_ptr");
+ tdesc_create_reg (feature, "d0lo", 33, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d0hi", 34, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d1lo", 35, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "d1hi", 36, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "orig_r0", 37, 1, "system", 32, "int");
+ tdesc_create_reg (feature, "fucpr", 38, 1, "system", 32, "int");
+
+ tdesc_nds32_linux = result;
+}
diff --git a/gdb/features/nds32-linux.xml b/gdb/features/nds32-linux.xml
new file mode 100644
index 0000000..74e41ce
--- /dev/null
+++ b/gdb/features/nds32-linux.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>nds32</architecture>
+ <osabi>GNU/Linux</osabi>
+ <xi:include href="nds32-core.xml"/>
+</target>
diff --git a/gdb/nds32-linux-nat.c b/gdb/nds32-linux-nat.c
new file mode 100644
index 0000000..2f87822
--- /dev/null
+++ b/gdb/nds32-linux-nat.c
@@ -0,0 +1,299 @@
+/* Common target dependent code for GDB on nds32 systems.
+
+ Copyright (C) 2006-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 "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "gdb_string.h"
+#include "regcache.h"
+#include "target.h"
+#include "linux-nat.h"
+#include "target-descriptions.h"
+#include "auxv.h"
+
+#include <elf/common.h>
+#include <sys/user.h>
+#include <sys/ptrace.h>
+#include <sys/utsname.h>
+#include <sys/procfs.h>
+
+/* Prototypes for supply_gregset etc. */
+#include "gregset.h"
+
+/* Defines ps_err_e, struct ps_prochandle. */
+#include "gdb_proc_service.h"
+
+#include "nds32-tdep.h"
+#include "nds32-linux-tdep.h"
+#include "features/nds32-linux.c"
+
+void _initialize_nds32_linux_nat (void);
+
+#define GET_THREAD_ID(PTID) get_thread_id (PTID)
+
+/* On GNU/Linux, threads are implemented as pseudo-processes, in which
+ case we may be tracing more than one process at a time. In that
+ case, inferior_ptid will contain the main process ID and the
+ individual thread (process) ID. get_thread_id () is used to get
+ the thread id if it's available, and the process id otherwise. */
+
+int
+get_thread_id (ptid_t ptid)
+{
+ int tid = TIDGET (ptid);
+
+ if (0 == tid)
+ tid = PIDGET (ptid);
+ return tid;
+}
+
+/* Fetch a general register of the process and store into register
+ cache REGCACHE. See: arch/nds32/include/asm/ptrace.h */
+
+static void
+fetch_register (struct regcache *regcache, int regno)
+{
+ int ret, tid;
+ elf_gregset_t regs;
+
+ /* Check whether the size of gregset is consistent with kernel. */
+ gdb_assert (sizeof (elf_gregset_t) >= (sizeof (long) * 50));
+
+ /* Get the thread id for the ptrace call. */
+ tid = GET_THREAD_ID (inferior_ptid);
+
+ ret = ptrace (PTRACE_GETREGS, tid, 0, ®s);
+ if (ret < 0)
+ {
+ warning (_("Unable to fetch general register."));
+ return;
+ }
+
+ if (regno >= NDS32_R0_REGNUM && regno < NDS32_LINUX_NUM_GPRS
+ && nds32_ptreg_map[regno] != -1)
+ regcache_raw_supply (regcache, regno,
+ (char *) ®s[nds32_ptreg_map[regno]]);
+}
+
+/* Fetch all general registers of the process and store into register
+ cache REGCACHE. */
+
+static void
+fetch_regs (struct regcache *regcache)
+{
+ int ret, regno, tid;
+ elf_gregset_t regs;
+
+ /* Get the thread id for the ptrace call. */
+ tid = GET_THREAD_ID (inferior_ptid);
+
+ ret = ptrace (PTRACE_GETREGS, tid, 0, ®s);
+ if (ret < 0)
+ {
+ warning (_("Unable to fetch general registers."));
+ return;
+ }
+
+ for (regno = NDS32_R0_REGNUM; regno < NDS32_LINUX_NUM_GPRS; regno++)
+ {
+ if (nds32_ptreg_map[regno] == -1)
+ continue;
+ regcache_raw_supply (regcache, regno,
+ (char *) ®s[nds32_ptreg_map[regno]]);
+ }
+}
+
+/* Store all general registers of the process from the values in
+ register cache REGCACHE. */
+
+static void
+store_register (const struct regcache *regcache, int regno)
+{
+ int ret, tid;
+ elf_gregset_t regs;
+
+ if (REG_VALID != regcache_register_status (regcache, regno))
+ return;
+
+ /* Get the thread id for the ptrace call. */
+ tid = GET_THREAD_ID (inferior_ptid);
+
+ /* Get the general registers from the process. */
+ ret = ptrace (PTRACE_GETREGS, tid, 0, ®s);
+ if (ret < 0)
+ {
+ warning (_("Unable to fetch general registers."));
+ return;
+ }
+
+ if (regno >= NDS32_R0_REGNUM && regno < NDS32_LINUX_NUM_GPRS
+ && nds32_ptreg_map[regno] != -1)
+ regcache_raw_collect (regcache, regno,
+ (char *) ®s[nds32_ptreg_map[regno]]);
+
+ ret = ptrace (PTRACE_SETREGS, tid, 0, ®s);
+ if (ret < 0)
+ {
+ warning (_("Unable to store general register."));
+ return;
+ }
+}
+
+static void
+store_regs (const struct regcache *regcache)
+{
+ int ret, regno, tid;
+ elf_gregset_t regs;
+
+ /* Get the thread id for the ptrace call. */
+ tid = GET_THREAD_ID (inferior_ptid);
+
+ /* Fetch the general registers. */
+ ret = ptrace (PTRACE_GETREGS, tid, 0, ®s);
+ if (ret < 0)
+ {
+ warning (_("Unable to fetch general registers."));
+ return;
+ }
+
+ for (regno = 0; regno < NDS32_LINUX_NUM_GPRS; regno++)
+ {
+ if (nds32_ptreg_map[regno] == -1)
+ continue;
+ if (REG_VALID != regcache_register_status (regcache, regno))
+ regcache_raw_collect (regcache, regno,
+ (char *) ®s[nds32_ptreg_map[regno]]);
+ }
+
+ ret = ptrace (PTRACE_SETREGS, tid, 0, ®s);
+
+ if (ret < 0)
+ {
+ warning (_("Unable to store general registers."));
+ return;
+ }
+}
+
+/* Fetch registers from the child process. Fetch all registers if
+ REGNO == -1, otherwise fetch all general registers or all floating
+ point registers depending upon the value of REGNO. */
+
+static void
+nds32_linux_fetch_inferior_registers (struct target_ops *ops,
+ struct regcache *regcache,
+ int regno)
+{
+ /* TODO: Handle AUDIO and FPU registers. */
+
+ if (-1 == regno)
+ fetch_regs (regcache);
+ else
+ fetch_register (regcache, regno);
+}
+
+/* Store registers back into the inferior. Store all registers if
+ REGNO == -1, otherwise store all general registers or all floating
+ point registers depending upon the value of REGNO. */
+
+static void
+nds32_linux_store_inferior_registers (struct target_ops *ops,
+ struct regcache *regcache,
+ int regno)
+{
+ /* TODO: Handle AUDIO and FPU registers. */
+
+ if (-1 == regno)
+ store_regs (regcache);
+ else
+ store_register (regcache, regno);
+}
+
+/* Wrapper functions for the standard regset handling, used by
+ thread debugging. */
+
+void
+fill_gregset (const struct regcache *regcache,
+ gdb_gregset_t *gregsetp, int regno)
+{
+ nds32_linux_collect_gregset (NULL, regcache, regno, gregsetp, 0);
+}
+
+void
+supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
+{
+ nds32_linux_supply_gregset (NULL, regcache, -1, gregsetp, 0);
+}
+
+void
+fill_fpregset (const struct regcache *regcache,
+ gdb_fpregset_t *fpregsetp, int regno)
+{
+ warning (_("fill_fpregset not implemented"));
+}
+
+/* Fill GDB's register array with the floating-point register values
+ in *fpregsetp. */
+
+void
+supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
+{
+ warning (_("supply_fpregset not implemented"));
+}
+
+/* Fetch the thread-local storage pointer for libthread_db. */
+
+#if 0
+/* TODO: TLS is not supported, yet. */
+
+ps_err_e
+ps_get_thread_area (const struct ps_prochandle *ph,
+ lwpid_t lwpid, int idx, void **base)
+{
+}
+#endif
+
+static const struct target_desc *
+nds32_linux_read_description (struct target_ops *ops)
+{
+ CORE_ADDR nds32_hwcap = 0;
+
+ /* TODO: FPU registers. */
+
+ return tdesc_nds32_linux;
+}
+
+void
+_initialize_nds32_linux_nat (void)
+{
+ struct target_ops *t;
+
+ /* Fill in the generic GNU/Linux methods. */
+ t = linux_target ();
+
+ /* Add our register access methods. */
+ t->to_fetch_registers = nds32_linux_fetch_inferior_registers;
+ t->to_store_registers = nds32_linux_store_inferior_registers;
+
+ t->to_read_description = nds32_linux_read_description;
+
+ /* Register the target. */
+ linux_nat_add_target (t);
+ initialize_tdesc_nds32_linux ();
+}
diff --git a/gdb/nds32-linux-tdep.c b/gdb/nds32-linux-tdep.c
new file mode 100644
index 0000000..79d51cd
--- /dev/null
+++ b/gdb/nds32-linux-tdep.c
@@ -0,0 +1,320 @@
+/* Common target dependent code for GDB on nds32 systems.
+
+ Copyright (C) 2006-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 "defs.h"
+#include "gdbcore.h"
+#include "frame.h"
+#include "value.h"
+#include "regcache.h"
+#include "inferior.h"
+#include "osabi.h"
+#include "reggroups.h"
+#include "regset.h"
+#include "target-descriptions.h"
+
+#include "gdb_string.h"
+
+#include "glibc-tdep.h"
+#include "solib-svr4.h"
+
+#include "trad-frame.h"
+#include "frame-unwind.h"
+
+#include "nds32-tdep.h"
+#include "nds32-linux-tdep.h"
+
+extern struct nds32_gdb_config nds32_config;
+
+void _initialize_nds32_linux_tdep (void);
+
+/* Recognizing signal handler frames. */
+
+/* GNU/Linux has two flavors of signals. Normal signal handlers, and
+ "realtime" (RT) signals. The RT signals can provide additional
+ information to the signal handler if the SA_SIGINFO flag is set
+ when establishing a signal handler using `sigaction'. It is not
+ unlikely that future versions of GNU/Linux will support SA_SIGINFO
+ for normal signals too. */
+
+/* When the NDS32 Linux kernel calls a signal handler and the
+ SA_RESTORER flag isn't set, the return address points to a bit of
+ code on the stack. This function returns whether the PC appears to
+ be within this bit of code.
+
+ The instructions for normal and realtime signals are
+ syscall #__NR_sigreturn ( 0x26 0x01 0xDC 0x0B)
+ or
+ syscall #__NR_rt_sigreturn ( 0x26 0x02 0xB4 0x0B)
+
+ Checking for the code sequence should be somewhat reliable, because
+ the effect is to call the system call sigreturn. This is unlikely
+ to occur anywhere other than in a signal trampoline.
+
+ It kind of sucks that we have to read memory from the process in
+ order to identify a signal trampoline, but there doesn't seem to be
+ any other way. Therefore we only do the memory reads if no
+ function name could be identified, which should be the case since
+ the code is on the stack.
+
+ Detection of signal trampolines for handlers that set the
+ SA_RESTORER flag is in general not possible. Unfortunately this is
+ what the GNU C Library has been doing for quite some time now.
+ However, as of version 2.1.2, the GNU C Library uses signal
+ trampolines (named __restore and __restore_rt) that are identical
+ to the ones used by the kernel. Therefore, these trampolines are
+ supported too. */
+
+/* syscall #0x5077 */
+static const unsigned char NDS32_SIGRETURN_INSN[] =
+{
+ 0x64, 0x0a, 0x0e, 0xeb
+};
+
+/* syscall #0x50ad */
+static const unsigned char NDS32_RT_SIGRETURN_INSN[] =
+{
+ 0x64, 0x0a, 0x15, 0xab
+};
+
+int nds32_linux_sc_reg_offset[] =
+{
+ /* r0 - r9 */
+ 12, 16, 20, 24, 28, 32, 36, 40, 44, 48,
+ /* r10 - r19 */
+ 52, 56, 60, 64, 68, 72, 76, 80, 84, 88,
+ /* r20 - r25, 26, 27 */
+ 92, 96, 100, 104, 108, 112, -1, -1,
+ /* fp, gp, lr, sp */
+ 116, 120, 124, 128,
+ /* pc, d0lo, d0hi, d1lo, d1hi */
+ 148, 140, 144, 132, 136
+};
+
+struct nds32_frame_cache
+{
+ CORE_ADDR base, pc;
+ struct trad_frame_saved_reg *saved_regs;
+};
+
+/* Find start of signal frame. */
+
+static CORE_ADDR
+nds32_linux_sigtramp_start (struct frame_info *this_frame)
+{
+ const int SIGLEN = sizeof (NDS32_SIGRETURN_INSN);
+ CORE_ADDR pc = get_frame_pc (this_frame);
+ gdb_byte buf[SIGLEN];
+
+ if (!safe_frame_unwind_memory (this_frame, pc, buf, SIGLEN))
+ return 0;
+
+ if (memcmp (buf, NDS32_SIGRETURN_INSN, SIGLEN) != 0)
+ return 0;
+
+ return pc;
+}
+
+/* Find start of rt_signal frame. */
+
+static CORE_ADDR
+nds32_linux_rt_sigtramp_start (struct frame_info *this_frame)
+{
+ const int SIGLEN = sizeof (NDS32_RT_SIGRETURN_INSN);
+ CORE_ADDR pc = get_frame_pc (this_frame);
+ gdb_byte buf[SIGLEN];
+
+ if (!safe_frame_unwind_memory (this_frame, pc, buf, SIGLEN))
+ return 0;
+
+ if (memcmp (buf, NDS32_RT_SIGRETURN_INSN, SIGLEN) != 0)
+ return 0;
+
+ return pc;
+}
+
+/* Return whether the frame preceding NEXT_FRAME corresponds to a
+ GNU/Linux sigtramp routine. */
+
+static int
+nds32_linux_sigtramp_p (struct frame_info *this_frame)
+{
+ CORE_ADDR pc = get_frame_pc (this_frame);
+ const char *name;
+
+ find_pc_partial_function (pc, &name, NULL, NULL);
+
+ /* If we have NAME, we can optimize the search. The trampolines are
+ named __restore and __restore_rt. However, they aren't dynamically
+ exported from the shared C library, so the trampoline may appear to
+ be part of the preceding function. This should always be sigaction,
+ __sigaction, or __libc_sigaction (all aliases to the same function). */
+ if (name == NULL)
+ return (nds32_linux_sigtramp_start (this_frame) != 0
+ || nds32_linux_rt_sigtramp_start (this_frame) != 0);
+
+ return (strcmp ("__default_sa_restorer", name) == 0
+ || strcmp ("__default_rt_sa_restorer", name) == 0);
+}
+
+/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */
+#define NDS32_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 0x18
+
+/* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
+ routine, return the address of the associated sigcontext structure. */
+
+static CORE_ADDR
+nds32_linux_sigcontext_addr (struct frame_info *this_frame)
+{
+ CORE_ADDR pc;
+ CORE_ADDR sp;
+ gdb_byte buf[4];
+
+ sp = get_frame_sp (this_frame);
+
+ /* sigcontext is at sp for sigtramp */
+ pc = nds32_linux_sigtramp_start (this_frame);
+ if (pc)
+ return sp;
+
+ pc = nds32_linux_rt_sigtramp_start (this_frame);
+ if (pc)
+ {
+ CORE_ADDR ucontext_addr;
+ int r2;
+
+ /* Cole, Dec. 31th, 2010
+ sigcontext is stored in frame->uc.uc_mcontext, Therefore,
+ there are two ways to get sigcontext.
+ The first way, direct access it in the stack.In this way,
+ we needs more knowledge of rt_sigtramp
+ The second way, &us is passed as parameter 3 of handler,
+ that would be R2 in NDS32 ABI.As long as we use generic
+ ucontext struct, I think it's easier to get sigcontext. */
+
+ r2 = get_frame_register_unsigned (this_frame, NDS32_R0_REGNUM + 2);
+ sp = r2;
+ /* This value is dependent on kernel. */
+ sp += NDS32_LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
+ return sp;
+ }
+
+ error (_("Couldn't recognize signal trampoline."));
+ return 0;
+}
+
+/* Supply GPR regset.
+
+ Fill GDB register array with the general-purpose register values
+ in *GREGSETP. */
+
+void
+nds32_linux_supply_gregset (const struct regset *regset,
+ struct regcache *regcache, int regnum,
+ const void *gregs, size_t size)
+{
+ int i;
+ const char *regp = gregs;
+
+ /* pseudo_shift = size == 200 ? 24 : 0; */
+ for (i = NDS32_R0_REGNUM; i < NDS32_LINUX_NUM_GPRS; i++)
+ {
+ /* FIXME: Review me after <linux/user.h>, <asm/ptrace.h>, and SR regs
+ spec clear. [Harry@Mar.14.2006] */
+ if (nds32_ptreg_map[i] == -1)
+ continue;
+
+ regcache_raw_supply (regcache, i, regp + nds32_ptreg_map[i] * 4);
+ }
+}
+
+/* Collect GPR regset. */
+
+void
+nds32_linux_collect_gregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *gregs_buf, size_t len)
+{
+ gdb_byte *regp = gregs_buf;
+ int regno;
+
+ for (regno = NDS32_R0_REGNUM; regno < NDS32_LINUX_NUM_GPRS; regno++)
+ {
+ if (nds32_ptreg_map[regno] == -1)
+ continue;
+
+ if (regnum == -1 || regnum == regno)
+ regcache_raw_collect (regcache, regno,
+ regp + nds32_ptreg_map[regno] * 4);
+ }
+}
+
+/* Implement gdbarch_regset_from_core_section method. */
+
+static const struct regset *
+nds32_linux_regset_from_core_section (struct gdbarch *core_arch,
+ const char *sect_name, size_t sect_size)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (core_arch);
+
+ if (strcmp (sect_name, ".reg") == 0)
+ return regset_alloc (core_arch, nds32_linux_supply_gregset,
+ nds32_linux_collect_gregset);
+
+ /* TODO: fpreg ".reg2" */
+ return NULL;
+}
+
+static void
+nds32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+ const struct target_desc *tdesc = info.target_desc;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;
+ const struct tdesc_feature *feature;
+
+ tdep->sigtramp_p = nds32_linux_sigtramp_p;
+ tdep->sigcontext_addr = nds32_linux_sigcontext_addr;
+ tdep->sc_pc_offset = 37 * 4; /* sc.fault_address */
+ tdep->sc_sp_offset = 32 * 4; /* sc.sp */
+ tdep->sc_lp_offset = 31 * 4; /* sc.lp */
+ tdep->sc_fp_offset = 29 * 4; /* sc.fp */
+
+ tdep->sc_reg_offset = nds32_linux_sc_reg_offset;
+ tdep->sc_num_regs = ARRAY_SIZE (nds32_linux_sc_reg_offset);
+
+ /* GNU/Linux uses SVR4-style shared libraries. */
+ set_solib_svr4_fetch_link_map_offsets (gdbarch,
+ svr4_ilp32_fetch_link_map_offsets);
+
+ /* Core file support. */
+ /* FIXME: Cole, Dec 31th, 2010
+ It seems this doesn't work? */
+ set_gdbarch_regset_from_core_section (gdbarch,
+ nds32_linux_regset_from_core_section);
+
+ set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
+}
+
+void
+_initialize_nds32_linux_tdep (void)
+{
+ gdbarch_register_osabi (bfd_arch_nds32, 0, GDB_OSABI_LINUX,
+ nds32_linux_init_abi);
+}
diff --git a/gdb/nds32-linux-tdep.h b/gdb/nds32-linux-tdep.h
new file mode 100644
index 0000000..40684fe
--- /dev/null
+++ b/gdb/nds32-linux-tdep.h
@@ -0,0 +1,77 @@
+/* Common target dependent code for GDB on nds32 systems.
+
+ Copyright (C) 2006-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/>. */
+
+#ifndef NDS32_LINUX_TDEP_H
+#define NDS32_LINUX_TDEP_H
+
+extern struct target_desc *tdesc_nds32_linux;
+
+void nds32_linux_supply_gregset (const struct regset *regset,
+ struct regcache *regcache, int regnum,
+ const void *gregs, size_t size);
+void nds32_linux_collect_gregset (const struct regset *regset,
+ const struct regcache *regcache, int regnum,
+ void *gregs_buf, size_t len);
+
+/* Mapping between the general-purpose registers in `struct user'
+ format and GDB's register array layout.
+
+ FIXME: fix me after <linux/user.h>, <asm/ptrace.h>,
+ and SR regs spec clear. [Harry@Mar.14.2006]
+
+ Current remap layout depend on Tom's implementation in kernel header,
+ in ptrace.h and IR spec 0.1 (Jan.20.2006 version)
+ [Harry@Mar.16.2006]
+
+ Note: -1 means unable to get from ptrace syscall
+
+ Renumber according to arch/nds32/include/asm/ptrace.h
+ Not sure whether NDS32_r0 or NDS32_ORIG_r0 represents real $r0.
+ (current use NDS32_ORIG_r0)
+ Registers not mapped: NDS32_FUCOP_CTL, NDS32_osp. (42 & 43)
+ [Rudolph@Aug.18.2010] */
+
+/* Map gdb regnum to pt_regs index. */
+static int nds32_ptreg_map[] =
+{
+ /* nds32-core */
+
+ /* r0 - r25 */
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38,
+ /* r26 and r27 are reserved for kernel */
+ -1, -1,
+ /* fp, gp, lp, sp */
+ 39, 40, 41, 3,
+ /* pc */
+ 2,
+ /* d0lo, d0hi, d1lo, d1hi */
+ 10, 9, 12, 11,
+
+ /* nds32-linux */
+
+ /* orig_r0, fucop */
+ 4, 42
+};
+
+#define NDS32_LINUX_NUM_GPRS (ARRAY_SIZE(nds32_ptreg_map))
+
+#endif
diff --git a/gdb/nds32-remote.c b/gdb/nds32-remote.c
new file mode 100644
index 0000000..c088f0d
--- /dev/null
+++ b/gdb/nds32-remote.c
@@ -0,0 +1,778 @@
+/* Common target dependent code for GDB on nds32 systems.
+
+ Copyright (C) 2006-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 "defs.h"
+#include "gdb_string.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "gdbtypes.h"
+#include "cli/cli-decode.h"
+#include "remote.h"
+#include "regcache.h"
+#include "user-regs.h"
+#include "inferior.h" /* get_inferior_args () */
+#include "top.h" /* set_prompt () */
+#include "ui-out.h" /* current_uiout */
+#include "exceptions.h" /* TRY_CATCH */
+#include <ctype.h>
+
+#include "nds32-remote.h"
+#include "nds32-tdep.h"
+
+char *nds32_qparts [] =
+{
+ "qPart:nds32:ask:de",
+ "qPart:nds32:ask:mach",
+ "qPart:nds32:ask:base16",
+ "qPart:nds32:ask:pex1",
+ "qPart:nds32:ask:pex2",
+ "qPart:nds32:ask:div",
+ "qPart:nds32:ask:abi",
+ "qPart:nds32:ask:mfusr_pc",
+ "qPart:nds32:ask:fpu",
+ "qPart:nds32:ask:audio",
+ "qPart:nds32:ask:string",
+ "qPart:nds32:ask:reduced_regs",
+ "qPart:nds32:ask:video",
+ "qPart:nds32:ask:ifc",
+ "qPart:nds32:ask:elf_ver",
+ "qPart:nds32:ask:l2c",
+ "qPart:nds32:ask:mac",
+ "qPart:nds32:ask:cpu", /* core0, cpu, etc */
+ "qPart:nds32:ask:target", /* SID, ICE */
+
+ "qPart:nds32:request:InvalidateCache",
+ "qPart:nds32:request:MemAccBus",
+ "qPart:nds32:request:MemAccCPU"
+};
+
+enum nds32_qparts_enum
+{
+ NDS32_Q_ENDIAN,
+ NDS32_Q_MACH,
+ NDS32_Q_BASE16,
+ NDS32_Q_PEX1,
+ NDS32_Q_PEX2,
+ NDS32_Q_DIV,
+ NDS32_Q_ABI,
+ NDS32_Q_MFUSR_PC,
+ NDS32_Q_FPU,
+ NDS32_Q_AUDIO,
+ NDS32_Q_STRING,
+ NDS32_Q_REDUCED_REGS,
+ NDS32_Q_VIDEO,
+ NDS32_Q_IFC,
+ NDS32_Q_ELF_VER,
+ NDS32_Q_L2C,
+ NDS32_Q_MAC,
+ NDS32_Q_CPU,
+ NDS32_Q_TARGET,
+
+ NDS32_Q_INVALIDATE_CACHE,
+ NDS32_Q_ACC_BUS,
+ NDS32_Q_ACC_CPU,
+ NDS32_Q_END
+};
+
+enum nds32_remote_type
+{
+ nds32_rt_unknown = 0,
+ nds32_rt_sid,
+ nds32_rt_ice,
+ nds32_rt_ocd,
+};
+
+struct
+{
+ /* Target type of remote, SID, ICE or OpenOCD. */
+ enum nds32_remote_type type;
+ /* CPU/CORE name read from remote. */
+ char cpu[16];
+ /* Default endian of remote. */
+ enum bfd_endian endian;
+} nds32_remote_info;
+
+void
+nds32_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
+ int *kindptr)
+{
+ if ((*pcptr) & 1)
+ error (_("bad address %p for inserting breakpoint"), (void *) *pcptr);
+
+ /* ICEman/AICE have trouble on reading memory when the pcptr is P/A,
+ but CPU is in V/A mode. This code prevent GDB from reading memory.
+ ICEman will read memory itself if needed.
+
+ See: Bug 7430 - GDB can't set a hardware break point with PA
+ if IT/DT is on. */
+
+ *kindptr = 2;
+}
+
+/* Wrapper for execute a GDB CLI command. */
+
+static void
+nds32_execute_command (char *cmd, char *arg, int from_tty)
+{
+ int len;
+ char *line;
+
+ if (arg == NULL)
+ arg = "";
+ len = strlen (arg) + strlen (cmd) + 2;
+ if (len > 1024)
+ error (_("Command line too long."));
+
+ line = alloca (len);
+ memset (line, 0, len);
+ if (arg != NULL)
+ snprintf (line, len, "%s %s", cmd, arg);
+ else
+ snprintf (line, len, "%s", cmd);
+ execute_command (line, from_tty);
+}
+
+static void
+nds32_restore_remote_timeout (void *p)
+{
+ int value = *(int *) p;
+
+ remote_timeout = value;
+}
+
+/* Reset-target.
+ Set remote_timeout to 1000 sec to avoid timeout. */
+
+static void
+nds32_reset_target_command (char *args, int from_tty)
+{
+ int saved_remote_timeout = remote_timeout;
+ struct cleanup *back_to;
+
+ back_to = make_cleanup (nds32_restore_remote_timeout, &saved_remote_timeout);
+ remote_timeout = 1000;
+ nds32_execute_command ("monitor reset target", NULL, from_tty);
+ registers_changed ();
+ do_cleanups (back_to);
+}
+
+/* Callback for "nds32 reset-hold" command. */
+
+static void
+nds32_reset_hold_command (char *args, int from_tty)
+{
+ int saved_remote_timeout = remote_timeout;
+ struct cleanup *back_to;
+
+ back_to =
+ make_cleanup (nds32_restore_remote_timeout, &saved_remote_timeout);
+ remote_timeout = 1000;
+ nds32_execute_command ("monitor reset hold", NULL, from_tty);
+ registers_changed ();
+ do_cleanups (back_to);
+}
+
+/* Callback for "nds32 pipeline on" command. */
+
+static void
+nds32_pipeline_on_command (char *args, int from_tty)
+{
+ char cmd[256];
+
+ snprintf (cmd, sizeof (cmd), "monitor set %s pipeline-on 1",
+ args == NULL ? "cpu" : args);
+ nds32_execute_command (cmd, NULL, from_tty);
+}
+
+/* Callback for "nds32 pipeline off" command. */
+
+static void
+nds32_pipeline_off_command (char *args, int from_tty)
+{
+ char cmd[256];
+
+ snprintf (cmd, sizeof (cmd), "monitor set %s pipeline-on 0",
+ args == NULL ? "cpu" : args);
+ nds32_execute_command (cmd, NULL, from_tty);
+}
+
+/* Callback for "nds32 pipeline" command. */
+
+static void
+nds32_pipeline_command (char *args, int from_tty)
+{
+ error (_("Usage: nds32 pipeline (on|off) [cpu]"));
+}
+
+/* Callback for "nds32 query" command. */
+
+static void
+nds32_query_command (char *args, int from_tty)
+{
+ error (_("Usage: nds32 query (profiling|perf-meter) [cpu] [human|ide]"));
+}
+
+/* Callback for "nds32 reset" command. */
+
+static void
+nds32_reset_command (char *args, int from_tty)
+{
+ error (_("Usage: nds32 reset (profiling|perf-meter) [cpu]"));
+}
+
+/* Pretty-print for profiling data. */
+
+static void
+nds32_print_human_table (int col, int row, const char *scsv)
+{
+ int i;
+ struct cleanup *table_cleanup = NULL;
+ struct cleanup *row_cleanup = NULL;
+ char *buf = NULL;
+ char **col_fldname;
+ char **col_hdrtext;
+ int *col_width;
+ enum ui_align *col_align;
+ struct bound_minimal_symbol msymbol;
+ CORE_ADDR addr;
+ char symbol_text[256];
+
+ buf = xstrdup (scsv);
+ make_cleanup (xfree, buf);
+
+ /* Allocate header structures. */
+ col_fldname = (char **) xmalloc (sizeof (col_fldname[0]) * col);
+ col_hdrtext = (char **) xmalloc (sizeof (col_hdrtext[0]) * col);
+ col_width = (int *) xmalloc (sizeof (col_width[0]) * col);
+ col_align = (enum ui_align *) xmalloc (sizeof (col_align[0]) * col);
+
+ make_cleanup (xfree, col_fldname);
+ make_cleanup (xfree, col_hdrtext);
+ make_cleanup (xfree, col_width);
+ make_cleanup (xfree, col_align);
+
+ /* Parsing column header. */
+ i = 0;
+ while (*buf != '\0' && i < col)
+ {
+ CORE_ADDR addr = 0;
+ char *sc = strchr (buf, ';');
+
+ *sc = '\0';
+ col_fldname[i] = buf;
+ col_hdrtext[i] = col_fldname[i];
+ if (col_fldname[i][0] == '%')
+ col_width[i] = 6;
+ else
+ col_width[i] = strlen (col_hdrtext[i]) + 1;
+
+ col_align[i] = ui_right;
+
+ i++;
+ buf = sc + 1;
+ }
+
+ gdb_assert (col == i);
+
+ /* Output table. */
+ table_cleanup = make_cleanup_ui_out_table_begin_end
+ (current_uiout, col, row - 1, "ProfilingTable");
+ for (i = 0; i < col; i++)
+ ui_out_table_header (current_uiout, col_width[i], col_align[i],
+ col_fldname[i], col_hdrtext[i]);
+
+ ui_out_table_body (current_uiout);
+
+ /* Parse buf into col/row. */
+ i = 0;
+ row_cleanup = make_cleanup_ui_out_tuple_begin_end (current_uiout, "row");
+ while (*buf != '\0')
+ {
+ char *sc = strchr (buf, ';');
+ int offset;
+
+ *sc = '\0';
+ switch (i)
+ {
+ case 0:
+ ui_out_field_string (current_uiout, col_fldname[i], buf);
+
+ /* Assume first column is address. */
+ strcpy (symbol_text, "\n");
+ addr = strtol (buf, NULL, 16);
+ msymbol = lookup_minimal_symbol_by_pc (addr);
+ if (!msymbol.minsym)
+ break;
+
+ offset = addr - SYMBOL_VALUE_ADDRESS (msymbol.minsym);
+ if (offset)
+ snprintf (symbol_text, sizeof (symbol_text), "%s + 0x%x\n",
+ SYMBOL_PRINT_NAME (msymbol.minsym), offset);
+ else
+ snprintf (symbol_text, sizeof (symbol_text), "%s\n",
+ SYMBOL_PRINT_NAME (msymbol.minsym));
+ break;
+ case 1: case 2: case 3: case 4: case 5: case 6:
+ ui_out_field_string (current_uiout, col_fldname[i], buf);
+ break;
+ }
+
+ i++;
+ buf = sc + 1;
+ if (i == col)
+ {
+ ui_out_text (current_uiout, symbol_text);
+ do_cleanups (row_cleanup);
+ i = 0;
+ row_cleanup = make_cleanup_ui_out_tuple_begin_end
+ (current_uiout, "row");
+ }
+ }
+
+ do_cleanups (table_cleanup);
+}
+
+/* Callback for "nds32 query profiling" command. */
+
+static void
+nds32_query_profiling_command (char *args, int from_tty)
+{
+ /* For profiling, there will be multiple responses. */
+ int row, col;
+ struct ui_file *res;
+ int i;
+ long int pkt_size;
+ char *pkt_buf = NULL;
+ struct ui_file_buffer ui_buf;
+ char *arg_cpu = "cpu";
+ int arg_human = TRUE;
+ struct cleanup *back_to = NULL;
+ char **argv = NULL;
+ char *p;
+
+ /* Initial size. It may be resized by getpkt. */
+ pkt_size = 1024;
+
+ res = mem_fileopen ();
+ back_to = make_cleanup_ui_file_delete (res);
+
+ ui_buf.buf_size = 2048;
+ ui_buf.buf = xmalloc (ui_buf.buf_size);
+ pkt_buf = xmalloc (pkt_size);
+
+ make_cleanup (free_current_contents, &ui_buf.buf);
+ make_cleanup (free_current_contents, &pkt_buf);
+ make_cleanup_restore_ui_file (&gdb_stdtarg);
+
+ gdb_stdtarg = res;
+
+ if (args != NULL)
+ {
+ /* Parse arguments. */
+ argv = gdb_buildargv (args);
+ make_cleanup_freeargv (argv);
+ }
+
+ for (i = 0; argv && argv[i]; i++)
+ {
+ switch (i)
+ {
+ case 0:
+ arg_cpu = argv[i];
+ break;
+ case 1:
+ arg_human = strcmp (argv[i], "ide"); /* default human */
+ break;
+ }
+ }
+
+ /* Fill BUF with monitor command. */
+ snprintf ((char *) ui_buf.buf, ui_buf.buf_size, "set %s profiling ide-query",
+ args == NULL ? "cpu" : arg_cpu);
+ target_rcmd ((char *) ui_buf.buf, res);
+ memset (ui_buf.buf, 0, ui_buf.buf_size);
+ ui_file_put (res, do_ui_file_put_memcpy, &ui_buf);
+
+ if (!arg_human)
+ {
+ fprintf_unfiltered (gdb_stdtarg,
+ "=profiling,reason=\"fast_l1_profiling\",data=\"%s\"\n",
+ ui_buf.buf);
+ goto bye;
+ }
+
+ /* The first response is Row=%d;Column=%d;
+ and then comes 'Row' rows, including head row */
+ i = sscanf ((char *) ui_buf.buf, "Row=%d;Column=%d;", &row, &col);
+ if (i != 2)
+ error (_("Failed to query profiling data"));
+
+ p = (char *) ui_buf.buf;
+
+ /* Skip "Row=r;Column=c;". */
+ for (i = 0; i < 2 && p; i++)
+ p = strchr (p + 1, ';');
+ p++;
+
+ /* Print human-mode table here. */
+ nds32_print_human_table (col, row, p);
+
+bye:
+ do_cleanups (back_to);
+}
+
+/* Callback for "nds32 query perfmeter" command. */
+
+static void
+nds32_query_perfmeter_command (char *args, int from_tty)
+{
+ /* For perfmeter, there will be only one response. */
+ char cmd[128];
+
+ snprintf (cmd, sizeof (cmd), "set %s perf-meter query",
+ args == NULL ? "cpu" : args);
+ target_rcmd (cmd, gdb_stdtarg);
+}
+
+/* Callback for "nds32 reset profiling" command. */
+
+static void
+nds32_reset_profiling_command (char *args, int from_tty)
+{
+ char cmd[256];
+
+ snprintf (cmd, sizeof (cmd), "set %s profiling reset",
+ args == NULL ? "cpu" : args);
+ target_rcmd (cmd, gdb_stdtarg);
+}
+
+/* Callback for "nds32 reset perfmeter" command. */
+
+static void
+nds32_reset_perfmeter_command (char *args, int from_tty)
+{
+ char cmd[256];
+
+ snprintf (cmd, sizeof (cmd), "set %s perf-meter reset",
+ args == NULL ? "cpu" : args);
+ target_rcmd (cmd, gdb_stdtarg);
+}
+
+static void
+nds32_remote_info_init (void)
+{
+ nds32_remote_info.type = nds32_rt_unknown;
+ nds32_remote_info.endian = BFD_ENDIAN_UNKNOWN;
+ strcpy (nds32_remote_info.cpu, "cpu");
+}
+
+/* Query target information. */
+
+static struct value *
+nds32_target_type_make_value (struct gdbarch *gdbarch, struct internalvar *var,
+ void *ignore)
+{
+ int val = 0;
+
+ if (strcmp (target_shortname, "remote") == 0
+ || strcmp (target_shortname, "extended-remote") == 0)
+ val = target_has_registers ? nds32_remote_info.type
+ : nds32_rt_unknown;
+
+ return value_from_longest (builtin_type (gdbarch)->builtin_int,
+ val);
+}
+
+static int
+nds32_query_target_using_qpart (void)
+{
+ char *buf;
+ long size = 64;
+ struct cleanup *back_to;
+ int ret = FALSE;
+
+ /* The buffer passed to getpkt must be allocated using xmalloc,
+ because it might be xrealloc by read_frame.
+ See remote.c for details. `buf' must be freed before return. */
+ buf = xmalloc (size);
+
+ /* Let caller clean it up. */
+ back_to = make_cleanup (free_current_contents, &buf);
+
+ /* qPart:nds32:ask:target - SID or ICE. */
+ nds32_remote_info.type = nds32_rt_unknown;
+ putpkt (nds32_qparts[NDS32_Q_TARGET]);
+ getpkt (&buf, &size, 0);
+ if (strcmp (buf, "SID") == 0)
+ nds32_remote_info.type = nds32_rt_sid;
+ else if (strcmp (buf, "ICE") == 0)
+ nds32_remote_info.type = nds32_rt_ice;
+ else
+ goto out;
+
+ /* qPart:nds32:ask:cpu - prompt, e.g., "core0(gdb) ". */
+ putpkt (nds32_qparts[NDS32_Q_CPU]);
+ getpkt (&buf, &size, 0);
+ if (strlen (buf) > 0 && buf[0] != 'E')
+ {
+ const int csize = sizeof (nds32_remote_info.cpu);
+ memset (nds32_remote_info.cpu, 0, csize);
+ strncpy (nds32_remote_info.cpu, buf, csize - 1);
+ }
+
+ /* qPart:nds32:ask:de - endian, e.g., LE or BE. */
+ putpkt (nds32_qparts[NDS32_Q_ENDIAN]);
+ getpkt (&buf, &size, 0);
+ if (strcmp (buf, "LE") == 0)
+ nds32_remote_info.endian = BFD_ENDIAN_LITTLE;
+ else if (strcmp (buf, "BE") == 0)
+ nds32_remote_info.endian = BFD_ENDIAN_BIG;
+ else
+ nds32_remote_info.endian = BFD_ENDIAN_UNKNOWN;
+ ret = TRUE;
+
+out:
+ do_cleanups (back_to);
+ return ret;
+}
+
+static int
+nds32_query_target_using_qrcmd (void)
+{
+ struct cleanup *back_to;
+ struct ui_file *res;
+ struct ui_file_buffer ui_buf;
+ char buf[64];
+ int ret = FALSE;
+ volatile struct gdb_exception except;
+ int len;
+
+ /* ui_file for qRcmd. */
+ res = mem_fileopen ();
+ back_to = make_cleanup_ui_file_delete (res);
+
+ /* ui_file_buffer for reading ui_file. */
+ ui_buf.buf_size = 64;
+ ui_buf.buf = xmalloc (ui_buf.buf_size);
+ make_cleanup (free_current_contents, &ui_buf.buf);
+
+ /* make_cleanup outside TRY_CACHE,
+ because it save and reset cleanup-chain. */
+ make_cleanup_restore_ui_file (&gdb_stdtarg);
+ /* Supress error messages from gdbserver
+ if gdbserver doesn't support the monitor command. */
+ gdb_stdtarg = res;
+
+ TRY_CATCH (except, RETURN_MASK_ERROR)
+ {
+ target_rcmd ("nds query target", res);
+ }
+ if (except.reason < 0)
+ goto out;
+
+ /* Read data in ui_file. */
+ memset (ui_buf.buf, 0, ui_buf.buf_size);
+ ui_file_put (res, do_ui_file_put_memcpy, &ui_buf);
+
+ /* Trim trailing newline characters. */
+ len = strlen ((char *) ui_buf.buf);
+ while (isspace (ui_buf.buf[len - 1]) && len > 0)
+ len--;
+ ui_buf.buf[len] = '\0';
+
+ if (strcmp ((char *) ui_buf.buf, "OCD") == 0)
+ nds32_remote_info.type = nds32_rt_ocd;
+ else
+ {
+ printf_unfiltered (_("Unknown remote target %s\n"),
+ ui_buf.buf);
+ goto out;
+ }
+
+ ret = TRUE;
+out:
+ do_cleanups (back_to);
+ return ret;
+}
+
+static void
+nds32_query_target_command (char *arg, int from_tty)
+{
+ nds32_remote_info_init ();
+
+ if (strcmp (target_shortname, "remote") != 0)
+ return;
+ /* FIXME if we don't know, use ELF. */
+
+ /* Try to find out the type of target - SID, ICE or OCD. */
+ if (!nds32_query_target_using_qpart ())
+ nds32_query_target_using_qrcmd ();
+
+end_query:
+ /* Set cpu name if ICE and CPU!="cpu". */
+ if (strcmp ("cpu", nds32_remote_info.cpu) != 0)
+ {
+ char buf[64];
+ snprintf (buf, sizeof (buf), "%s(gdb) ", nds32_remote_info.cpu);
+ set_prompt (buf);
+ }
+ else
+ {
+ /* Restore to DEFAULT_PROMPT. */
+ set_prompt ("(gdb) ");
+ }
+}
+
+/* This is only used for SID. Set command-line string. */
+
+static void
+nds32_set_gloss_command (char *arg, int from_tty)
+{
+ int i;
+ struct ui_file *out;
+ char *arg0;
+ char *args;
+ char *f;
+ char cmdline[0x1000]; /* 4K for max command line. */
+ struct cleanup *back_to;
+ asection *s = NULL;
+ const char *sectnames[] = { ".text", "code", ".bss", "bss" };
+
+ /* set gloss for SID only. */
+ if (nds32_remote_info.type != nds32_rt_sid)
+ return;
+
+ back_to = make_cleanup (null_cleanup, 0);
+ if (exec_bfd == NULL)
+ error (_("Cannot set gloss without executable.\n"
+ "Use the \"file\" or \"exec-file\" command."));
+
+ /* ui_file for target_rcmd. */
+ out = stdio_fileopen (stdout);
+ make_cleanup_ui_file_delete (out);
+
+ /* start_code, end_code, start_bss, end_bss,
+ brk, command-line. */
+ for (s = exec_bfd->sections; s; s = s->next)
+ {
+ bfd_vma start, size;
+ const char *attr;
+
+ for (i = 0; i < ARRAY_SIZE (sectnames); i += 2)
+ if (strcmp (bfd_get_section_name (exec_bfd, s), sectnames[i]) == 0)
+ break;
+
+ if (i >= ARRAY_SIZE (sectnames))
+ continue;
+
+ start = bfd_get_section_vma (exec_bfd, s);
+ size = bfd_section_size (exec_bfd, s);
+
+ /* Set gloss (start|end)_XXX. */
+ snprintf (cmdline, sizeof (cmdline), "set gloss start_%s %u",
+ sectnames[i + 1], (unsigned int) start);
+ target_rcmd (cmdline, out);
+ snprintf (cmdline, sizeof (cmdline), "set gloss end_%s %u",
+ sectnames[i + 1], (unsigned int) (start + size));
+ target_rcmd (cmdline, out);
+ }
+
+ /* Set gloss command-line for "set args". */
+ arg0 = bfd_get_filename(exec_bfd);
+ args = get_inferior_args ();
+
+ f = strrchr (arg0, '/');
+ if (f == NULL)
+ f = strrchr (arg0, '\\');
+
+ if (f == NULL)
+ f = "a.out";
+ else
+ f++; /* skip separator. */
+
+ snprintf (cmdline, sizeof (cmdline),
+ "set gloss command-line \"%s %s\"", f, args);
+ target_rcmd (cmdline, out);
+
+ do_cleanups (back_to);
+}
+
+static struct cmd_list_element *nds32_pipeline_cmdlist;
+static struct cmd_list_element *nds32_query_cmdlist;
+static struct cmd_list_element *nds32_reset_cmdlist;
+static struct cmd_list_element *nds32_maint_cmdlist;
+
+static const struct internalvar_funcs nds32_target_type_funcs =
+{
+ nds32_target_type_make_value,
+ NULL,
+ NULL
+};
+
+void
+nds32_init_remote_cmds (void)
+{
+ nds32_remote_info_init ();
+
+ /* nds32 set-gloss COMMAND_LINE */
+ add_cmd ("set-gloss", class_files, nds32_set_gloss_command,
+ _("Check elf/target compatibility before loading. "
+ "Throwing error if failed."),
+ &nds32_cmdlist);
+
+ /* nds32 reset-target */
+ add_cmd ("reset-target", no_class, nds32_reset_target_command,
+ _("Turn on pipeline for profiling."), &nds32_cmdlist);
+ /* nds32 reset-hold */
+ add_cmd ("reset-hold", no_class, nds32_reset_hold_command,
+ _("Turn off pipeline for profiling."), &nds32_cmdlist);
+
+ /* nds32 pipeline (on|off) */
+ add_prefix_cmd ("pipeline", no_class, nds32_pipeline_command,
+ _("nds32-sid profiling commands."),
+ &nds32_pipeline_cmdlist, "nds32 ", 0, &nds32_cmdlist);
+ add_cmd ("on", no_class, nds32_pipeline_on_command,
+ _("Turn on pipeline for profiling."), &nds32_pipeline_cmdlist);
+ add_cmd ("off", no_class, nds32_pipeline_off_command,
+ _("Turn off pipeline for profiling."), &nds32_pipeline_cmdlist);
+
+ /* nds32 query (profiling|perf-meter|target) */
+ add_prefix_cmd ("query", no_class, nds32_query_command,
+ _("Query remote data."), &nds32_query_cmdlist, "query ",
+ 0, &nds32_cmdlist);
+ add_cmd ("profiling", no_class, nds32_query_profiling_command,
+ _("Query profiling results."), &nds32_query_cmdlist);
+ add_cmd ("perf-meter", no_class, nds32_query_perfmeter_command,
+ _("Query perf-meter results."), &nds32_query_cmdlist);
+ add_cmd ("target", no_class, nds32_query_target_command,
+ _("Query target information."), &nds32_query_cmdlist);
+
+ /* nds32 reset (profiling|perf-meter) */
+ add_prefix_cmd ("reset", no_class, nds32_reset_command,
+ _("Reset profiling."), &nds32_reset_cmdlist, "reset ",
+ 0, &nds32_cmdlist);
+ add_cmd ("profiling", no_class, nds32_reset_profiling_command,
+ _("Query profiling results."), &nds32_reset_cmdlist);
+ add_cmd ("perf-meter", no_class, nds32_reset_perfmeter_command,
+ _("Query perf-meter results."), &nds32_reset_cmdlist);
+
+ create_internalvar_type_lazy ("_nds32_target_type", &nds32_target_type_funcs,
+ NULL);
+}
diff --git a/gdb/nds32-remote.h b/gdb/nds32-remote.h
new file mode 100644
index 0000000..629f8b6
--- /dev/null
+++ b/gdb/nds32-remote.h
@@ -0,0 +1,28 @@
+/* Common target dependent code for GDB on nds32 systems.
+
+ Copyright (C) 2006-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/>. */
+
+#ifndef NDS32_REMOTE_H
+#define NDS32_REMOTE_H
+
+void nds32_init_remote_cmds (void);
+void nds32_remote_breakpoint_from_pc (struct gdbarch *gdbarch,
+ CORE_ADDR *pcptr, int *kindptr);
+
+#endif
diff --git a/gdb/nds32-tdep.c b/gdb/nds32-tdep.c
new file mode 100644
index 0000000..f861807
--- /dev/null
+++ b/gdb/nds32-tdep.c
@@ -0,0 +1,2802 @@
+/* Common target dependent code for GDB on nds32 systems.
+
+ Copyright (C) 2006-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 <assert.h>
+#include <stdint.h>
+
+#include "defs.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "gdb_string.h"
+#include "value.h"
+#include "reggroups.h"
+#include "inferior.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "osabi.h"
+#include "language.h"
+#include "arch-utils.h"
+#include "regcache.h"
+#include "trad-frame.h"
+#include "dis-asm.h"
+#include "gdb_assert.h"
+#include "user-regs.h"
+#include "elf-bfd.h"
+#include "dwarf2-frame.h"
+#include "ui-file.h"
+#include "remote.h"
+#include "target-descriptions.h"
+#include "sim-regno.h"
+#include "gdb/sim-nds32.h"
+
+#include "nds32-tdep.h"
+#include "nds32-utils.h"
+#include "nds32-remote.h"
+#include "elf/nds32.h"
+#include "opcode/nds32.h"
+
+/* Simple macro for chop LSB immediate bits from an instruction. */
+#define CHOP_BITS(insn, n) (insn & ~__MASK (n))
+
+extern void _initialize_nds32_tdep (void);
+
+struct nds32_gdb_config nds32_config;
+
+/* The standard register names. */
+static char *nds32_regnames[] =
+{
+ /* 32 GPRs. */
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "fp", "gp", "lp", "sp",
+
+ /* 5 User Registers. */
+ "pc", "d0lo", "d0hi", "d1lo", "d1hi",
+};
+
+/* Mnemonic names for registers. */
+struct nds32_register_alias
+{
+ const char *name;
+ const char *alias;
+};
+
+/* Register alias for user_reg_map_name_to_regnum (). */
+struct nds32_register_alias nds32_register_aliases[] =
+{
+ {"r15", "ta"},
+ {"r26", "p0"},
+ {"r27", "p1"},
+ {"fp", "r28"},
+ {"gp", "r29"},
+ {"lp", "r30"},
+ {"sp", "r31"},
+
+ {"ir0", "psw"},
+ {"ir1", "ipsw"},
+ {"ir2", "p_psw"},
+ {"ir3", "ivb"},
+ {"ir4", "eva"},
+ {"ir5", "p_eva"},
+ {"ir6", "itype"},
+ {"ir7", "p_itype"},
+ {"ir8", "merr"},
+ {"ir9", "ipc"},
+ {"ir10", "p_ipc"},
+ {"ir11", "oipc"},
+ {"ir12", "p_p0"},
+ {"ir13", "p_p1"},
+ {"ir14", "int_mask"},
+ {"ir15", "int_pend"},
+
+ {"cr0", "cpu_ver"},
+ {"cr1", "icm_cfg"},
+ {"cr2", "dcm_cfg"},
+ {"cr3", "mmu_cfg"},
+ {"cr4", "msc_cfg"},
+ {"cr5", "core_id"},
+ {"cr6", "fucop_exist"},
+
+ {"mr0", "mmu_ctl"},
+ {"mr1", "l1_pptb"},
+ {"mr2", "tlb_vpn"},
+ {"mr3", "tlb_data"},
+ {"mr4", "tlb_misc"},
+ {"mr5", "vlpt_idx"},
+ {"mr6", "ilmb"},
+ {"mr7", "dlmb"},
+ {"mr8", "cache_ctl"},
+ {"mr9", "hsmp_saddr"},
+ {"mr10", "hsmp_eaddr"},
+
+ {"pfr0", "pfmc0"},
+ {"pfr1", "pfmc1"},
+ {"pfr2", "pfmc2"},
+ {"pfr3", "pfm_ctl"},
+
+ {"dmar0", "dma_cfg"},
+ {"dmar1", "dma_gcsw"},
+ {"dmar2", "dma_chnsel"},
+ {"dmar3", "dma_act"},
+ {"dmar4", "dma_setup"},
+ {"dmar5", "dma_isaddr"},
+ {"dmar6", "dma_esaddr"},
+ {"dmar7", "dma_tcnt"},
+ {"dmar8", "dma_status"},
+ {"dmar9", "dma_2dset"},
+ {"dmar10", "dma_2dsctl"},
+};
+
+/* Value of a register alias. BATON is register name of the alias,
+ because system registers do not have fixed register number.
+ We must look-up them when access. */
+
+static struct value *
+nds32_value_of_reg (struct frame_info *frame, const void *baton)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ int regnum;
+
+ regnum = user_reg_map_name_to_regnum (gdbarch, (const char *) baton, -1);
+
+ return value_of_register (regnum, frame);
+}
+
+/* gdbarch_frame_align () */
+
+static CORE_ADDR
+nds32_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
+{
+ /* 8-byte aligned. */
+ return sp & ~(8 - 1);
+}
+
+/* Implement the gdbarch_breakpoint_from_pc method. */
+
+static const gdb_byte *
+nds32_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
+ int *lenptr)
+{
+ static const gdb_byte NDS32_BREAK16[] = { 0xEA, 0x00 };
+ const unsigned char *bp;
+
+ gdb_assert (pcptr);
+ gdb_assert (lenptr);
+
+ if ((*pcptr) & 1)
+ error (_("Bad address %p for inserting breakpoint.\n"
+ "Address must be at least 2-byte aligned."), (void *) *pcptr);
+
+ /* Always insert 16-bit break instruction. */
+ *lenptr = 2;
+ return NDS32_BREAK16;
+}
+
+/* Implement the gdbarch_dwarf2_reg_to_regnum method.
+ Map DWARF regnum from GCC to GDB regnum. */
+
+static int
+nds32_dwarf_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int num)
+{
+ const int GPR = 0;
+ const int DXR = 34;
+ const int FSR = 38;
+ const int FDR = FSR + 32;
+
+ if (num >= 0 && num < 32) /* R0 - R31 */
+ return num;
+ else if (num >= DXR && num < DXR + 4) /* D0/D1 */
+ return num - DXR + NDS32_D0LO_REGNUM;
+ else if (num >= FSR && num < FSR + 32) /* FS */
+ return num - FSR + user_reg_map_name_to_regnum (gdbarch, "fs0",
+ strlen ("fs0"));
+ else if (num >= FDR && num < FDR + 32) /* FD */
+ return num - FDR + user_reg_map_name_to_regnum (gdbarch, "fd0",
+ strlen ("fd0"));
+
+ /* No match, return a inaccessible register number. */
+ return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
+}
+
+static int
+nds32_register_sim_regno (struct gdbarch *gdbarch, int regnum)
+{
+ const char *reg_name;
+ /* Use target-descriptions for register mapping. */
+
+ /* Only makes sense to supply raw registers. */
+ gdb_assert (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch));
+
+ if (regnum < NDS32_NUM_REGS)
+ return regnum;
+ if (regnum >= NDS32_SIM_FD0_REGNUM && regnum < NDS32_SIM_FD0_REGNUM + 32)
+ return SIM_NDS32_FD0_REGNUM + regnum - NDS32_SIM_FD0_REGNUM;
+ switch (regnum)
+ {
+ case NDS32_SIM_IFCLP_REGNUM:
+ return SIM_NDS32_IFCLP_REGNUM;
+ case NDS32_SIM_ITB_REGNUM:
+ return SIM_NDS32_ITB_REGNUM;
+ case NDS32_SIM_PSW_REGNUM:
+ return SIM_NDS32_PSW_REGNUM;
+ }
+
+ return LEGACY_SIM_REGNO_IGNORE;
+}
+
+/* Create types for registers and insert them to type table by name. */
+
+static void
+nds32_alloc_types (struct gdbarch *gdbarch)
+{
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ struct type *type, *stype1, *stype2;
+
+ tdep->type_tab = nds32_alloc_type_tab (24);
+
+ /* fucpr */
+ type = arch_flags_type (gdbarch, "builtin_type_nds32_fucpr", 4);
+ append_flags_type_flag (type, 0, "CP0EN");
+ append_flags_type_flag (type, 1, "CP1EN");
+ append_flags_type_flag (type, 2, "CP2EN");
+ append_flags_type_flag (type, 3, "CP3EN");
+ append_flags_type_flag (type, 31, "AUEN");
+ nds32_type_insert (tdep->type_tab, "fucpr", type);
+
+ /* fpcfg */
+ type = nds32_init_enum (gdbarch, "builtin_type_nds32_fpcfg");
+ nds32_append_enum (type, 0, "8SP_4DP");
+ nds32_append_enum (type, 1, "16SP_8DP");
+ nds32_append_enum (type, 2, "32SP_16DP");
+ nds32_append_enum (type, 3, "32SP_32DP");
+ stype1 = type;
+
+ type = nds32_init_type (gdbarch, "builtin_fpcfg_type", USE_FLAGS);
+ nds32_append_flag (type, 0, "SP");
+ nds32_append_flag (type, 1, "DP");
+ nds32_append_bitfield (type, stype1, 2, 3, "FREG");
+ nds32_append_flag (type, 4, "FMA");
+ nds32_append_bitfield (type, bt->builtin_uint8, 22, 26, "IMVER");
+ nds32_append_bitfield (type, bt->builtin_uint8, 27, 31, "AVER");
+ nds32_type_insert (tdep->type_tab, "fpcfg", type);
+
+ /* fpcsr */
+ type = nds32_init_enum (gdbarch, "builtin_type_nds32_fpcsr_rm");
+ nds32_append_enum (type, 0, "RTNE");
+ nds32_append_enum (type, 1, "RTPI");
+ nds32_append_enum (type, 2, "RTMI");
+ nds32_append_enum (type, 3, "RTZ");
+ stype1 = type;
+
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_fpcsr", USE_FLAGS);
+ nds32_append_bitfield (type, stype1, 0, 1, "RM");
+ nds32_append_flag (type, 2, "IVO");
+ nds32_append_flag (type, 3, "DBZ");
+ nds32_append_flag (type, 4, "OVF");
+ nds32_append_flag (type, 5, "UDF");
+ nds32_append_flag (type, 6, "IEX");
+ nds32_append_flag (type, 7, "IVOE");
+ nds32_append_flag (type, 8, "DBZE");
+ nds32_append_flag (type, 9, "OVFE");
+ nds32_append_flag (type, 10, "UDFE");
+ nds32_append_flag (type, 11, "IEXE");
+ nds32_append_flag (type, 12, "DNZ");
+ nds32_append_flag (type, 13, "IVOT");
+ nds32_append_flag (type, 14, "DBZT");
+ nds32_append_flag (type, 15, "OVFT");
+ nds32_append_flag (type, 16, "UDFT");
+ nds32_append_flag (type, 17, "IEXT");
+ nds32_append_flag (type, 18, "DNIT");
+ nds32_append_flag (type, 19, "RIT");
+ nds32_type_insert (tdep->type_tab, "fpcsr", type);
+
+ /* ir0 - processor status word register
+ ir1 - interruption PSW register
+ ir2 - previous IPSW register */
+ type = nds32_init_enum (gdbarch, "builtin_type_nds32_psw_intl");
+ nds32_append_enum (type, 0, "NO");
+ nds32_append_enum (type, 1, "Lv1");
+ nds32_append_enum (type, 2, "Lv2");
+ nds32_append_enum (type, 3, "Lv3");
+ stype1 = type;
+
+ type = nds32_init_enum (gdbarch, "builtin_type_nds32_psw_pow");
+ nds32_append_enum (type, 0, "User");
+ nds32_append_enum (type, 1, "Superuser");
+ nds32_append_enum (type, 2, "Reserved(2)");
+ nds32_append_enum (type, 3, "Reserved(3)");
+ stype2 = type;
+
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_psw", USE_FLAGS);
+ nds32_append_flag (type, 0, "GIE");
+ nds32_append_bitfield (type, stype1, 1, 2, "INTL");
+ nds32_append_bitfield (type, stype2, 3, 4, "POM");
+ nds32_append_flag (type, 5, "BE");
+ nds32_append_flag (type, 6, "IT");
+ nds32_append_flag (type, 7, "DT");
+ nds32_append_flag (type, 8, "IME");
+ nds32_append_flag (type, 9, "DME");
+ nds32_append_flag (type, 10, "DEX");
+ nds32_append_flag (type, 11, "HSS");
+ nds32_append_flag (type, 12, "DRBE");
+ nds32_append_flag (type, 13, "AEN");
+ nds32_append_flag (type, 14, "WBNA");
+ nds32_append_flag (type, 15, "IFCON");
+ nds32_append_flag (type, 20, "OV");
+ nds32_type_insert (tdep->type_tab, "ir0", type);
+ nds32_type_insert (tdep->type_tab, "ir1", type);
+ nds32_type_insert (tdep->type_tab, "ir2", type);
+
+ /* ir3 - Interrupt Vector Base Register */
+ type = nds32_init_enum (gdbarch, "builtin_type_nds32_ivb_esz");
+ nds32_append_enum (type, 0, "4_byte");
+ nds32_append_enum (type, 1, "16_byte");
+ nds32_append_enum (type, 2, "64_byte");
+ nds32_append_enum (type, 3, "256_byte");
+ stype1 = type;
+
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_ivb", USE_FLAGS);
+ nds32_append_flag (type, 13, "EVIC");
+ nds32_append_bitfield (type, stype1, 14, 15, "ESZ");
+ nds32_append_bitfield (type, bt->builtin_uint16, 16, 31, "IVBASE");
+ nds32_type_insert (tdep->type_tab, "ir3", type);
+
+ /* ir6 - Interruption Type Register
+ ir7 - Previous ITYPE */
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_itype", USE_FLAGS);
+ nds32_append_bitfield (type, bt->builtin_uint8, 0, 3, "ETYPE");
+ nds32_append_flag (type, 4, "INST");
+ nds32_append_bitfield (type, bt->builtin_uint16, 16, 30, "SWID");
+ nds32_type_insert (tdep->type_tab, "ir6", type);
+ nds32_type_insert (tdep->type_tab, "ir7", type);
+
+ /* ir14 - Interruption Masking Register */
+ type = arch_flags_type (gdbarch, "builtin_type_nds32_int_mask", 4);
+ append_flags_type_flag (type, 0, "H0IM");
+ append_flags_type_flag (type, 1, "H1IM");
+ append_flags_type_flag (type, 2, "H2IM");
+ append_flags_type_flag (type, 3, "H3IM");
+ append_flags_type_flag (type, 4, "H4IM");
+ append_flags_type_flag (type, 5, "H5IM");
+ append_flags_type_flag (type, 16, "SIM");
+ append_flags_type_flag (type, 29, "ALZ");
+ append_flags_type_flag (type, 30, "IDIVZE");
+ append_flags_type_flag (type, 31, "DSSIM");
+ nds32_type_insert (tdep->type_tab, "ir14", type);
+
+ /* ir18 - Interruption Prioirty Register */
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_int_pri", NO_FLAGS);
+ nds32_append_bitfield (type, bt->builtin_uint8, 0, 1, "H0PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 2, 3, "H1PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 4, 5, "H2PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 6, 7, "H3PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 8, 9, "H4PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 10, 11, "H5PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 12, 13, "H6PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 14, 15, "H7PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 16, 17, "H8PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 18, 19, "H9PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 20, 21, "H10PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 22, 23, "H11PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 24, 25, "H12PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 26, 27, "H13PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 28, 29, "H14PRI");
+ nds32_append_bitfield (type, bt->builtin_uint8, 30, 31, "H15PRI");
+ nds32_type_insert (tdep->type_tab, "ir18", type);
+
+ /* mr0 - MMU Control Register */
+ type = nds32_init_enum (gdbarch, "builtin_type_nds32_mmuctl_ntc");
+ nds32_append_enum (type, 0, "NCA_NCO");
+ nds32_append_enum (type, 1, "NCA_CO");
+ nds32_append_enum (type, 2, "CA_WB");
+ nds32_append_enum (type, 3, "CA_WT");
+ stype1 = type;
+
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_mmu_ctl", USE_FLAGS);
+ nds32_append_flag (type, 0, "D");
+ nds32_append_bitfield (type, stype1, 1, 2, "NTC0");
+ nds32_append_bitfield (type, stype1, 3, 4, "NTC1");
+ nds32_append_bitfield (type, stype1, 5, 6, "NTC2");
+ nds32_append_bitfield (type, stype1, 7, 8, "NTC3");
+ nds32_append_flag (type, 9, "TBALCK");
+ nds32_append_flag (type, 10, "MPZIU");
+ nds32_append_bitfield (type, bt->builtin_uint8, 11, 12, "NTM0");
+ nds32_append_bitfield (type, bt->builtin_uint8, 13, 14, "NTM1");
+ nds32_append_bitfield (type, bt->builtin_uint8, 15, 16, "NTM2");
+ nds32_append_bitfield (type, bt->builtin_uint8, 17, 18, "NTM3");
+ nds32_append_flag (type, 19, "DREE");
+ nds32_type_insert (tdep->type_tab, "mr0", type);
+
+ /* mr1 */
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_l1_pptb", USE_FLAGS);
+ nds32_append_flag (type, 0, "NV");
+ nds32_append_bitfield (type, bt->builtin_uint32, 12, 31, "L1_PPT_BASE");
+ nds32_type_insert (tdep->type_tab, "mr1", type);
+
+ /* mr2 */
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_tlb_vpn", NO_FLAGS);
+ nds32_append_bitfield (type, bt->builtin_uint32, 12, 31, "VPN");
+ nds32_type_insert (tdep->type_tab, "mr2", type);
+
+ /* mr3 */
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_tlb_data", USE_FLAGS);
+ nds32_append_flag (type, 0, "V");
+ nds32_append_bitfield (type, bt->builtin_uint8, 1, 3, "M");
+ nds32_append_flag (type, 4, "D");
+ nds32_append_flag (type, 5, "X");
+ nds32_append_flag (type, 6, "A");
+ nds32_append_flag (type, 7, "G");
+ nds32_append_bitfield (type, bt->builtin_uint8, 8, 10, "C");
+ nds32_append_bitfield (type, bt->builtin_uint32, 12, 31, "PPN");
+ nds32_type_insert (tdep->type_tab, "mr3", type);
+
+ /* mr4 - TLB Access Misc Register */
+ type = nds32_init_enum (gdbarch, "builtin_type_nds32_tlb_misc_acc_psz");
+ nds32_append_enum (type, 0, "4KB");
+ nds32_append_enum (type, 1, "8KB");
+ nds32_append_enum (type, 2, "16KB");
+ nds32_append_enum (type, 3, "64KB");
+ nds32_append_enum (type, 4, "256KB");
+ nds32_append_enum (type, 5, "1MB");
+ nds32_append_enum (type, 6, "4MB");
+ nds32_append_enum (type, 7, "16MB");
+ nds32_append_enum (type, 8, "64MB");
+ nds32_append_enum (type, 9, "256MB");
+ stype1 = type;
+
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_tlb_misc", NO_FLAGS);
+ nds32_append_bitfield (type, stype1, 0, 3, "ACC_PSZ");
+ nds32_append_bitfield (type, bt->builtin_uint32, 4, 12, "CID");
+ nds32_type_insert (tdep->type_tab, "mr4", type);
+
+ /* mr6 */
+ type = nds32_init_enum (gdbarch, "builtin_type_nds32_ilm_size");
+ nds32_append_enum (type, 0, "4KB");
+ nds32_append_enum (type, 1, "8KB");
+ nds32_append_enum (type, 2, "16KB");
+ nds32_append_enum (type, 3, "32KB");
+ nds32_append_enum (type, 4, "64KB");
+ nds32_append_enum (type, 5, "128KB");
+ nds32_append_enum (type, 6, "256KB");
+ nds32_append_enum (type, 7, "512KB");
+ nds32_append_enum (type, 8, "1024KB");
+ nds32_append_enum (type, 9, "1KB");
+ nds32_append_enum (type, 10, "2KB");
+ nds32_append_enum (type, 15, "0KB");
+ stype1 = type;
+
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_ilmb", NO_FLAGS);
+ nds32_append_bitfield (type, bt->builtin_uint8, 0, 0, "IEN");
+ nds32_append_bitfield (type, stype1, 1, 4, "ILMSZ");
+ nds32_append_bitfield (type, bt->builtin_data_ptr, 0, 31, "(raw)");
+ nds32_type_insert (tdep->type_tab, "mr6", type);
+
+ /* mr7 */
+ type = nds32_init_enum (gdbarch, "builtin_type_nds32_dlm_size");
+ nds32_append_enum (type, 0, "4KB");
+ nds32_append_enum (type, 1, "8KB");
+ nds32_append_enum (type, 2, "16KB");
+ nds32_append_enum (type, 3, "32KB");
+ nds32_append_enum (type, 4, "64KB");
+ nds32_append_enum (type, 5, "128KB");
+ nds32_append_enum (type, 6, "256KB");
+ nds32_append_enum (type, 7, "512KB");
+ nds32_append_enum (type, 8, "1024KB");
+ nds32_append_enum (type, 9, "1KB");
+ nds32_append_enum (type, 10, "2KB");
+ nds32_append_enum (type, 15, "0KB");
+ stype1 = type;
+
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_dlmb", NO_FLAGS);
+ nds32_append_bitfield (type, bt->builtin_uint8, 0, 0, "DEN");
+ nds32_append_bitfield (type, stype1, 1, 4, "DLMSZ");
+ nds32_append_bitfield (type, bt->builtin_uint8, 5, 5, "DBM");
+ nds32_append_bitfield (type, bt->builtin_uint8, 6, 6, "DBB");
+ nds32_append_bitfield (type, bt->builtin_data_ptr, 0, 31, "(raw)");
+ nds32_type_insert (tdep->type_tab, "mr7", type);
+
+ /* mr8 - Cache Control Register */
+ type = arch_flags_type (gdbarch, "builtin_type_nds32_cache_ctl", 4);
+ append_flags_type_flag (type, 0, "IC_EN");
+ append_flags_type_flag (type, 1, "DC_EN");
+ append_flags_type_flag (type, 2, "ICALCK");
+ append_flags_type_flag (type, 3, "DCALCK");
+ append_flags_type_flag (type, 4, "DCCWF");
+ append_flags_type_flag (type, 5, "DCPMW");
+ nds32_type_insert (tdep->type_tab, "mr8", type);
+
+ /* dr40 - EDM Configuration Register */
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_edm_cfg", USE_FLAGS);
+ nds32_append_bitfield (type, bt->builtin_uint8, 0, 2, "BC");
+ nds32_append_flag (type, 3, "DIMU");
+ nds32_append_flag (type, 4, "DALM");
+ nds32_append_bitfield (type, bt->builtin_uint16, 16, 31, "VER");
+ nds32_type_insert (tdep->type_tab, "dr40", type);
+
+ /* dmar0 - DMA Configuration Register */
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_dma_cfg", USE_FLAGS);
+ nds32_append_bitfield (type, bt->builtin_uint8, 0, 1, "NCHN");
+ nds32_append_flag (type, 2, "UNEA");
+ nds32_append_flag (type, 3, "2DET");
+ nds32_append_bitfield (type, bt->builtin_uint16, 16, 31, "VER");
+ nds32_type_insert (tdep->type_tab, "dmar0", type);
+
+ /* cr0 - CPU Version Register */
+ type = arch_flags_type (gdbarch, "builtin_type_nds32_cpuver_cfgid", 2);
+ append_flags_type_flag (type, 0, "PERF_EXT");
+ append_flags_type_flag (type, 1, "16_EXT");
+ append_flags_type_flag (type, 2, "PERF_EXT2");
+ append_flags_type_flag (type, 3, "COP_EXT");
+ append_flags_type_flag (type, 4, "STR_EXT");
+ stype1 = type;
+
+ type = nds32_init_enum (gdbarch, "builtin_type_nds32_cpuver_cpuid");
+ nds32_append_enum (type, 0x8, "N8");
+ nds32_append_enum (type, 0x9, "N9");
+ nds32_append_enum (type, 0xA, "N10");
+ nds32_append_enum (type, 0xC, "N12");
+ nds32_append_enum (type, 0xD, "N13");
+ nds32_append_enum (type, 0xE, "N14");
+ stype2 = type;
+
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_cpuver", NO_FLAGS);
+ nds32_append_bitfield (type, stype1, 0, 15, "CFGID");
+ nds32_append_bitfield (type, bt->builtin_uint8, 16, 23, "REV");
+ nds32_append_bitfield (type, stype2, 24, 31, "CPUID");
+ nds32_type_insert (tdep->type_tab, "cr0", type);
+
+ /* cr4 - Misc Configuration Register */
+ type = nds32_init_type (gdbarch, "builtin_type_nds32_msc_cfg", USE_FLAGS);
+ nds32_append_flag (type, 0, "EDM");
+ nds32_append_flag (type, 1, "LMDMA");
+ nds32_append_flag (type, 2, "PFM");
+ nds32_append_flag (type, 3, "HSMP");
+ nds32_append_flag (type, 4, "TRACE");
+ nds32_append_flag (type, 5, "DIV");
+ nds32_append_flag (type, 6, "MAC");
+ nds32_append_bitfield (type, bt->builtin_uint8, 7, 8, "AUDIO");
+ nds32_append_flag (type, 9, "L2c");
+ nds32_append_flag (type, 10, "RDREG");
+ nds32_append_flag (type, 11, "ADR24");
+ nds32_append_flag (type, 12, "INTLC");
+ nds32_append_bitfield (type, bt->builtin_uint8, 13, 15, "BASEV");
+ nds32_append_flag (type, 16, "NOD");
+ nds32_append_flag (type, 17, "IMV");
+ nds32_append_flag (type, 18, "IMR");
+ nds32_append_flag (type, 19, "IFC");
+ nds32_append_flag (type, 20, "MCU");
+ nds32_type_insert (tdep->type_tab, "cr4", type);
+
+ /* cr6 - FPU and Coprocessor Existence Configuration Register */
+ type = arch_flags_type (gdbarch, "builtin_type_nds32_fucop_exist", 4);
+ append_flags_type_flag (type, 0, "CP0EX");
+ append_flags_type_flag (type, 1, "CP1EX");
+ append_flags_type_flag (type, 2, "CP2EX");
+ append_flags_type_flag (type, 3, "CP3EX");
+ append_flags_type_flag (type, 31, "AUEX");
+ nds32_type_insert (tdep->type_tab, "cr6", type);
+}
+
+/* gdbarch_register_type ()
+
+ Return the GDB type object for the "standard" data type
+ of data in register N.
+ It get pretty messy here. I need enum-types and bit-fields
+ for better representation. But they cannot be done by
+ tdesc-xml. */
+
+static struct type *
+nds32_register_type (struct gdbarch *gdbarch, int regnum)
+{
+ int num_regs = gdbarch_num_regs (gdbarch);
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ struct type *type;
+ const char *reg_name;
+
+ /* Currently, only FSR are supported. */
+ if (regnum >= num_regs && regnum < num_regs + 32)
+ return builtin_type (gdbarch)->builtin_float;
+ else if (regnum >= num_regs)
+ return NULL;
+
+ /* NDS32 predefined types for specific registers. */
+ if (tdep->type_tab == NULL)
+ nds32_alloc_types (gdbarch);
+
+ reg_name = user_reg_map_regnum_to_name (gdbarch, regnum);
+ if (reg_name == NULL)
+ reg_name = "";
+ type = nds32_type_lookup (tdep->type_tab, reg_name);
+ if (type)
+ return type;
+
+ /* Type provided by target-description. */
+ if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
+ {
+ type = tdesc_register_type (gdbarch, regnum);
+ if (type)
+ return type;
+ }
+
+ /* Floating pointer registers. e.g., fs0 or fd0. */
+ if (strlen (reg_name) >= 3 && reg_name[0] == 'f' && reg_name[2] >= '0'
+ && reg_name[2] <= '9')
+ {
+ if (reg_name[1] == 's')
+ return bt->builtin_float;
+ else if (reg_name[1] == 'd')
+ return bt->builtin_double;
+ }
+
+ /* GPRs. */
+ if (regnum == NDS32_PC_REGNUM || regnum == NDS32_LP_REGNUM)
+ return bt->builtin_func_ptr;
+ else if (regnum == NDS32_SP_REGNUM || regnum == NDS32_FP_REGNUM
+ || regnum == NDS32_GP_REGNUM)
+ return bt->builtin_data_ptr;
+ else if (regnum < 32)
+ return bt->builtin_int32;
+
+ /* We don't know. Display it in hex-form. */
+ return bt->builtin_data_ptr;
+}
+
+/* nds32 register groups. */
+static struct reggroup *nds32_cr_reggroup;
+static struct reggroup *nds32_ir_reggroup;
+static struct reggroup *nds32_mr_reggroup;
+static struct reggroup *nds32_dr_reggroup;
+static struct reggroup *nds32_pfr_reggroup;
+static struct reggroup *nds32_dmar_reggroup;
+static struct reggroup *nds32_racr_reggroup;
+static struct reggroup *nds32_idr_reggroup;
+static struct reggroup *nds32_audio_reggroup;
+
+static void
+nds32_init_reggroups (void)
+{
+ /* gpr usr sr */
+ nds32_cr_reggroup = reggroup_new ("cr", USER_REGGROUP);
+ nds32_ir_reggroup = reggroup_new ("ir", USER_REGGROUP);
+ nds32_mr_reggroup = reggroup_new ("mr", USER_REGGROUP);
+ nds32_dr_reggroup = reggroup_new ("dr", USER_REGGROUP);
+ nds32_pfr_reggroup = reggroup_new ("pfr", USER_REGGROUP);
+ nds32_dmar_reggroup = reggroup_new ("dmar", USER_REGGROUP);
+ nds32_racr_reggroup = reggroup_new ("racr", USER_REGGROUP);
+ nds32_idr_reggroup = reggroup_new ("idr", USER_REGGROUP);
+
+ nds32_audio_reggroup = reggroup_new ("audio", USER_REGGROUP);
+}
+
+static void
+nds32_add_reggroups (struct gdbarch *gdbarch)
+{
+ /* Target-independent groups. */
+ reggroup_add (gdbarch, general_reggroup);
+ reggroup_add (gdbarch, float_reggroup);
+ reggroup_add (gdbarch, all_reggroup);
+ reggroup_add (gdbarch, system_reggroup);
+
+ /* System register groups. */
+ reggroup_add (gdbarch, nds32_cr_reggroup);
+ reggroup_add (gdbarch, nds32_ir_reggroup);
+ reggroup_add (gdbarch, nds32_mr_reggroup);
+ reggroup_add (gdbarch, nds32_dr_reggroup);
+ reggroup_add (gdbarch, nds32_pfr_reggroup);
+ reggroup_add (gdbarch, nds32_dmar_reggroup);
+ reggroup_add (gdbarch, nds32_racr_reggroup);
+ reggroup_add (gdbarch, nds32_idr_reggroup);
+}
+
+/* Implement the gdbarch_register_reggroup_p method. */
+
+static int
+nds32_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+ struct reggroup *group)
+{
+ int i;
+ struct reggroup *groups[] =
+ {
+ nds32_cr_reggroup, nds32_ir_reggroup, nds32_mr_reggroup,
+ nds32_dr_reggroup, nds32_pfr_reggroup, nds32_dmar_reggroup,
+ nds32_racr_reggroup, nds32_idr_reggroup
+ };
+ static const char *prefix[] =
+ {
+ "cr", "ir", "mr", "dr", "pfr", "dmar", "racr", "idr"
+ };
+
+ gdb_assert (sizeof (groups) == sizeof (prefix));
+
+ /* GPRs. */
+ if (group == general_reggroup)
+ return regnum <= NDS32_PC_REGNUM;
+
+ /* System Registers are grouped by prefix. */
+ else if (group == system_reggroup)
+ return (regnum > NDS32_PC_REGNUM)
+ && TYPE_CODE (register_type (gdbarch, regnum)) != TYPE_CODE_FLT;
+
+ for (i = 0; i < ARRAY_SIZE (groups); i++)
+ {
+ if (group == groups[i])
+ {
+ const char *regname = tdesc_register_name (gdbarch, regnum);
+
+ if (!regname)
+ return 0;
+ return strstr (regname, prefix[i]) == regname;
+ }
+ }
+
+ return default_register_reggroup_p (gdbarch, regnum, group);
+}
+
+/* This function is called when
+ 1. Target-description is used, and the register is pseudo.
+ 2. Target-description is NOT used,
+ i. and the target is simulator.
+ ii. or the target is legacy target. */
+
+/* Implement the tdesc_pseudo_register_name method. */
+
+static const char *
+nds32_register_name (struct gdbarch *gdbarch, int regnum)
+{
+ static char *fpu_pseudo_names[] =
+ {
+ "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
+ "fs8", "fs9", "fs10", "fs11", "fs12", "fs13", "fs14", "fs15",
+ "fs16", "fs17", "fs18", "fs19", "fs20", "fs21", "fs22", "fs23",
+ "fs24", "fs25", "fs26", "fs27", "fs28", "fs29", "fs30", "fs31"
+ };
+ static char *sim_names[] =
+ {
+ "fd0", "fd1", "fd2", "fd3", "fd4", "fd5", "fd6", "fd7",
+ "fd8", "fd9", "fd10", "fd11", "fd12", "fd13", "fd14", "fd15",
+ "fd16", "fd17", "fd18", "fd19", "fd20", "fd21", "fd22", "fd23",
+ "fd24", "fd25", "fd26", "fd27", "fd28", "fd29", "fd30", "fd31",
+ "ifclp", "itb", "ir0"
+ };
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int num_regs = gdbarch_num_regs (gdbarch);
+
+ /* Currently, only pseudo FSR are supported. */
+ if (regnum >= num_regs && regnum < num_regs + 32)
+ return fpu_pseudo_names[regnum - num_regs];
+
+ /* GPRs. */
+ if (regnum < ARRAY_SIZE (nds32_regnames))
+ return nds32_regnames[regnum];
+
+ /* Registers beteen NUM_REGS and SMI_NUM_REGS are
+ simulator registers. */
+ if (regnum >= NDS32_NUM_REGS && regnum < NDS32_SIM_NUM_REGS)
+ return sim_names[regnum - NDS32_NUM_REGS];
+
+ warning (_("Unknown nds32 pseudo register %d."), regnum);
+ return NULL;
+}
+
+/* Implement the gdbarch_pseudo_register_read method.
+
+ For legacy target, target-description and FPRs are not support.
+ Use Rcmd to access FPU registers. */
+
+static enum register_status
+nds32_pseudo_register_read (struct gdbarch *gdbarch,
+ struct regcache *regcache, int regnum,
+ gdb_byte *buf)
+{
+ char name_buf[8];
+ gdb_byte reg_buf[8];
+ int offset;
+ enum register_status status = REG_UNKNOWN;
+
+ /* Sanity check. */
+ regnum -= gdbarch_num_regs (gdbarch);
+ if (regnum > gdbarch_num_pseudo_regs (gdbarch))
+ return status;
+
+ /* Currently, only FSR are supported. */
+ if (regnum < 32)
+ {
+ int fd_regnum;
+
+ /* fs0 is always the high-part of fd0. */
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ offset = (regnum & 1) ? 4 : 0;
+ else
+ offset = (regnum & 1) ? 0 : 4;
+
+ sprintf (name_buf, "fd%d", regnum >> 1);
+ fd_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
+ strlen (name_buf));
+ status = regcache_raw_read (regcache, fd_regnum, reg_buf);
+ if (status == REG_VALID)
+ memcpy (buf, reg_buf + offset, 4);
+ }
+
+ return status;
+}
+
+/* Implement the gdbarch_pseudo_register_write method. */
+
+static void
+nds32_pseudo_register_write (struct gdbarch *gdbarch,
+ struct regcache *regcache, int regnum,
+ const gdb_byte *buf)
+{
+ char name_buf[8];
+ gdb_byte reg_buf[8];
+ int offset;
+
+ /* Sanity check. */
+ regnum -= gdbarch_num_regs (gdbarch);
+ if (regnum > gdbarch_num_pseudo_regs (gdbarch))
+ return;
+
+ /* Currently, only FSR are supported. */
+ if (regnum < 32)
+ {
+ int fd_regnum;
+
+ /* fs0 is always the high-part of fd0. */
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ offset = (regnum & 1) ? 4 : 0;
+ else
+ offset = (regnum & 1) ? 0 : 4;
+
+ sprintf (name_buf, "fd%d", regnum >> 1);
+ fd_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
+ strlen (name_buf));
+ regcache_raw_read (regcache, fd_regnum, reg_buf);
+ memcpy (reg_buf + offset, buf, 4);
+ regcache_raw_write (regcache, fd_regnum, reg_buf);
+ }
+
+ return;
+}
+
+/* Skip prologue should be conservative, and frame-unwind should be
+ relative-aggressive.*/
+
+static int
+nds32_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
+ CORE_ADDR scan_limit, CORE_ADDR *pl_endptr)
+{
+ uint32_t insn;
+ CORE_ADDR cpc = -1; /* Candidate PC if no suitable PC is found. */
+ LONGEST return_value;
+
+ /* If there is no buffer to store result, ignore this prologue decoding. */
+ if (pl_endptr == NULL)
+ {
+ return 0;
+ }
+
+ /* Look up end of prologue */
+ for (; pc < scan_limit; )
+ {
+ insn = read_memory_unsigned_integer (pc, 4, BFD_ENDIAN_BIG);
+
+ if ((insn & 0x80000000) == 0)
+ {
+ /* 32-bit instruction */
+
+ pc += 4;
+ if (insn == N32_ALU1 (ADD, REG_GP, REG_TA, REG_GP))
+ {
+ /* add $gp, $ta, $gp */
+ continue;
+ }
+ else if (CHOP_BITS (insn, 15) == N32_TYPE2 (ADDI, REG_SP, REG_SP, 0))
+ {
+ /* addi $sp, $sp, imm15 */
+ cpc = pc;
+ continue;
+ }
+ else if (CHOP_BITS (insn, 15) == N32_TYPE2 (ADDI, REG_FP, REG_FP, 0))
+ {
+ /* addi $fp, $sp, imm15 */
+ cpc = pc;
+ continue;
+ }
+ else if (insn == N32_ALU2 (MFUSR, REG_TA, 31, 0))
+ {
+ /* mfusr $ta, PC ; group=0, sub=0x20=mfusr */
+ continue;
+ }
+ else if (CHOP_BITS (insn, 20) == N32_TYPE1 (MOVI, REG_TA, 0))
+ {
+ /* movi $ta, imm20s */
+ continue;
+ }
+ else if (CHOP_BITS (insn, 20) == N32_TYPE1 (SETHI, REG_GP, 0))
+ {
+ /* sethi $gp, imm20 */
+ continue;
+ }
+ else if (CHOP_BITS (insn, 15) == N32_TYPE2 (ORI, REG_GP, REG_GP, 0))
+ {
+ /* ori $gp, $gp, imm15 */
+ continue;
+ }
+ else if (CHOP_BITS (insn, 15) == N32_TYPE2 (SWI, REG_LP, REG_FP, 0))
+ {
+ /* Unlike swi, we should stop when lwi. */
+ /* swi $lp, [$sp + (imm15s<<2)] */
+ continue;
+ }
+ else if (CHOP_BITS (insn, 15) == N32_TYPE2 (SWI_BI, REG_LP, REG_FP, 0))
+ {
+ /* swi.bi $rt, [$sp], (imm15s<<2) */
+ continue;
+ }
+ else if (N32_OP6 (insn) == N32_OP6_LSMW && (insn & __BIT (5)))
+ {
+ /* bit-5 for SMW */
+
+ /* smwa?.(a|b)(d|i)m? rb,[ra],re,enable4 */
+
+ int rb, re, ra, enable4, i;
+ int aligned;
+ int m = 0;
+ int di; /* dec=-1 or inc=1 */
+ char enb4map[2][4] = {
+ {0, 1, 2, 3} /* smw */,
+ {3, 1, 2, 0} /* smwa */};
+ LONGEST base = ~1 + 1;
+
+ rb = N32_RT5 (insn);
+ ra = N32_RA5 (insn);
+ re = N32_RB5 (insn);
+ enable4 = (insn >> 6) & 0x0F;
+ aligned = (insn & 3) ? 1 : 0;
+ di = (insn & (1 << 3)) ? -1 : 1;
+
+ switch (ra)
+ {
+ case NDS32_FP_REGNUM:
+ case NDS32_SP_REGNUM:
+ cpc = pc;
+ continue; /* found and continue */
+ default:
+ break;
+ }
+ }
+
+ if (N32_OP6 (insn) == N32_OP6_COP && N32_COP_CP (insn) == 0
+ && (N32_COP_SUB (insn) == N32_FPU_FSS
+ || N32_COP_SUB (insn) == N32_FPU_FSD)
+ && (N32_RA5 (insn) == REG_SP || N32_RA5 (insn) == REG_FP))
+ {
+ /* CP shoud be CP0 */
+ /* fs[sd][.bi] $fst, [$sp + ($r0 << sv)] */
+ continue;
+ }
+
+ /* fssi $fst, [$ra + (imm12s << 2)]
+ fssi.bi $fst, [$ra], (imm12s << 2)
+ fsdi $fdt, [$ra + (imm12s << 2)]
+ fsdi.bi $fdt, [$ra], (imm12s << 2) */
+ if ((N32_OP6 (insn) == N32_OP6_SWC || N32_OP6 (insn) == N32_OP6_SDC)
+ && (N32_RA5 (insn) == REG_SP || N32_RA5 (insn) == REG_FP))
+ {
+ /* BI bit is dont-care. */
+ continue;
+ }
+
+ pc -= 4;
+ break;
+ }
+ else
+ {
+ /* 16-bit instruction */
+ pc += 2;
+ insn >>= 16;
+
+ /* 1. If the instruction is j/b, then we stop
+ i.e., OP starts with 10, and beqzs8, bnezs8.
+ 2. If the operations will change sp/fp or based on sp/fp,
+ then we are in the prologue.
+ 3. If we don't know what's it, then stop. */
+
+ if (CHOP_BITS (insn, 10) == N16_TYPE10 (ADDI10S, 0))
+ {
+ /* addi10s */
+ continue;
+ }
+ else if (__GF (insn, 7, 8) == N16_T25_PUSH25)
+ {
+ /* push25 */
+ continue;
+ }
+ else if (insn == N16_TYPE55 (MOV55, REG_FP, REG_SP))
+ {
+ /* mov55 fp, sp */
+ continue;
+ }
+
+ /* swi450 */
+ switch (insn & ~__MF (-1, 5, 4))
+ {
+ case N16_TYPE45 (SWI450, 0, REG_SP):
+ case N16_TYPE45 (SWI450, 0, REG_FP):
+ break;
+ }
+ /* swi37 - implied fp */
+ if (__GF (insn, 11, 4) == N16_T37_XWI37
+ && (insn & __BIT (7)))
+ continue;
+
+ /* swi37sp - implied */
+ if (__GF (insn, 11, 4) == N16_T37_XWI37SP
+ && (insn & __BIT (7)))
+ continue;
+
+ /* If the a instruction is not accepted,
+ don't go futher. */
+ pc -= 2;
+ break;
+ }
+ }
+
+ if (pc >= scan_limit)
+ {
+ /* If we can not find end of prologue before scan_limit,
+ we assume that end of prologue is on pc_after_stack_adject. */
+ if (cpc != -1)
+ pc = cpc;
+ }
+
+ *pl_endptr = pc;
+
+ return 0;
+}
+
+/* Implement the gdbarch_skip_prologue method.
+
+ Find the end of function prologue. */
+
+static CORE_ADDR
+nds32_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ CORE_ADDR func_addr, func_end;
+ struct symtab_and_line sal = { 0 };
+ LONGEST return_value;
+ const char *func_name;
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ const int search_limit = 128;
+
+ /* See what the symbol table says */
+ if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
+ {
+ sal = find_pc_line (func_addr, 0);
+
+ if (sal.line != 0 && sal.end <= func_end)
+ {
+ func_end = sal.end;
+ }
+ else
+ {
+ /* Either there's no line info, or the line after the prologue
+ is after the end of the function. In this case, there probably
+ isn't a prologue. */
+ func_end = min (func_end, func_addr + search_limit);
+ }
+ }
+ else
+ func_end = pc + search_limit;
+
+ /* If current instruction is not readable, just quit. */
+ if (!safe_read_memory_integer (pc, 4, byte_order, &return_value))
+ return pc;
+
+ /* Find the end of prologue. */
+ if (nds32_analyze_prologue (gdbarch, pc, func_end, &sal.end) < 0)
+ return pc;
+
+ return sal.end;
+}
+
+struct nds32_unwind_cache
+{
+ /* The previous frame's inner most stack address.
+ Used as this frame ID's stack_addr. */
+ CORE_ADDR prev_sp;
+
+ /* The frame's base, optionally used by the high-level debug info. */
+ CORE_ADDR base;
+ int size;
+
+ /* How far the SP and FP have been offset from the start of
+ the stack frame (as defined by the previous frame's stack
+ pointer). */
+ LONGEST sp_offset;
+ LONGEST fp_offset;
+ int use_frame;
+
+ /* Table indicating the location of each and every register. */
+ struct trad_frame_saved_reg *saved_regs;
+};
+
+static struct nds32_unwind_cache *
+nds32_alloc_frame_cache (struct frame_info *this_frame)
+{
+ struct nds32_unwind_cache *cache;
+ cache = FRAME_OBSTACK_ZALLOC (struct nds32_unwind_cache);
+
+ cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+ cache->size = 0;
+ cache->sp_offset = 0;
+ cache->fp_offset = 0;
+ cache->use_frame = 0;
+ cache->base = 0;
+
+ return cache;
+}
+
+/* Implement the gdbarch_in_function_epilogue_p method. */
+
+static int
+nds32_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ uint32_t insn;
+ int r = 0;
+
+ insn = read_memory_unsigned_integer (addr, 4, BFD_ENDIAN_BIG);
+ if ((insn & 0x80000000) == 0)
+ {
+ /* 32-bit instruction */
+
+ /* ret */
+ if (insn == N32_JREG (JR, 0, REG_LP, 0, 1))
+ r = 1;
+ /* iret */
+ else if (insn == N32_TYPE0 (MISC, N32_MISC_IRET))
+ r = 2;
+ }
+ else
+ {
+ if (insn == N16_TYPE5 (RET5, REG_LP))
+ r = 3;
+ }
+ return r > 0;
+}
+
+/* Put here the code to store, into fi->saved_regs, the addresses of
+ the saved registers of frame described by FRAME_INFO. This
+ includes special registers such as pc and fp saved in special ways
+ in the stack frame. sp is even more special: the address we return
+ for it IS the sp for the next frame. */
+
+static struct nds32_unwind_cache *
+nds32_frame_unwind_cache (struct frame_info *this_frame,
+ void **this_prologue_cache)
+{
+ CORE_ADDR pc, scan_limit;
+ ULONGEST prev_sp;
+ ULONGEST next_base;
+ ULONGEST fp_base;
+ int i;
+ int insn;
+ struct nds32_unwind_cache *info;
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+
+ if ((*this_prologue_cache))
+ return (*this_prologue_cache);
+
+ info = nds32_alloc_frame_cache (this_frame);
+
+ info->base = get_frame_register_unsigned (this_frame, NDS32_FP_REGNUM);
+ (*this_prologue_cache) = info;
+
+ if (info->base == 0)
+ return info;
+
+ pc = get_frame_func (this_frame);
+ scan_limit = get_frame_pc (this_frame);
+
+ for (; pc > 0 && pc < scan_limit; )
+ {
+ insn = read_memory_unsigned_integer (pc, 4, BFD_ENDIAN_BIG);
+
+ if ((insn & 0x80000000) == 0)
+ {
+ /* 32-bit instruction */
+
+ pc += 4;
+ if (insn == N32_ALU1 (ADD, REG_GP, REG_TA, REG_GP))
+ {
+ /* add $gp, $ta, $gp */
+ continue;
+ }
+ if (N32_OP6 (insn) == N32_OP6_ADDI)
+ {
+ int rt = N32_RT5 (insn);
+ int ra = N32_RA5 (insn);
+ int imm15s = N32_IMM15S (insn);
+
+ if (rt == ra && rt == NDS32_SP_REGNUM)
+ {
+ info->sp_offset += imm15s;
+ continue;
+ }
+ else if (rt == NDS32_FP_REGNUM && ra == NDS32_SP_REGNUM)
+ {
+ info->fp_offset = info->sp_offset + imm15s;
+ info->use_frame = 1;
+ continue;
+ }
+ else if (rt == ra)
+ /* Prevent stop analyzing form iframe. */
+ continue;
+ }
+
+ if (insn == N32_ALU2 (MFUSR, REG_TA, 31, 0))
+ {
+ /* mfusr $ta, PC ; group=0, sub=0x20=mfusr */
+ continue;
+ }
+ if (CHOP_BITS (insn, 20) == N32_TYPE1 (MOVI, REG_TA, 0))
+ {
+ /* movi $ta, imm20s */
+ continue;
+ }
+ if (CHOP_BITS (insn, 20) == N32_TYPE1 (SETHI, REG_GP, 0))
+ {
+ /* sethi $gp, imm20 */
+ continue;
+ }
+ if (CHOP_BITS (insn, 15) == N32_TYPE2 (ORI, REG_GP, REG_GP, 0))
+ {
+ /* ori $gp, $gp, imm15 */
+ continue;
+ }
+ if (N32_OP6 (insn) == N32_OP6_LSMW && (insn & __BIT (5)))
+ {
+ /* smwa?.(a|b)(d|i)m? rb,[ra],re,enable4 */
+
+ int rb, re, ra, enable4, i;
+ int aligned;
+ int m = 0;
+ int di; /* dec=-1 or inc=1 */
+ int rn; /* number of registers. */
+ char enb4map[2][4] = {
+ {0, 1, 2, 3} /* smw */,
+ {3, 1, 2, 0} /* smwa */ };
+ /* `base' is the highest/last address for access memory.
+ e.g., [ lp ] ___ base shoule be here.
+ [ fp ]
+ [ r6 ] */
+ LONGEST base = ~1 + 1;
+
+ rb = N32_RT5 (insn);
+ ra = N32_RA5 (insn);
+ re = N32_RB5 (insn);
+ enable4 = (insn >> 6) & 0x0F;
+ aligned = (insn & 3) ? 1 : 0;
+ di = (insn & (1 << 3)) ? -1 : 1;
+
+ rn = 0;
+ rn += (enable4 & 0x1) ? 1 : 0;
+ rn += (enable4 & 0x2) ? 1 : 0;
+ rn += (enable4 & 0x4) ? 1 : 0;
+ rn += (enable4 & 0x8) ? 1 : 0;
+ if (rb < NDS32_FP_REGNUM && re < NDS32_FP_REGNUM)
+ {
+ /* reg-list should not include fp,gp,lp,sp
+ ie, the rb==re==sp case, anyway... */
+ rn += (re - rb) + 1;
+ }
+
+ /* Let's consider how Ra should update. */
+ if (insn & (1 << 0x2)) /* m-bit is set */
+ {
+ m = rn * 4; /* 4*TNReg */
+ }
+ else
+ m = 0; /* don't update Ra */
+
+ switch (ra)
+ {
+ case NDS32_FP_REGNUM:
+ base = info->fp_offset;
+ info->fp_offset += m * di;
+ break;
+ case NDS32_SP_REGNUM:
+ base = info->sp_offset;
+ info->sp_offset += m * di;
+ break;
+ default:
+ /* sorry, only ra==sp || ra==fp is handled */
+ break;
+ }
+ if (base == ~1 + 1)
+ break; /* skip */
+
+ if (insn & (1 << 0x4)) /* b:0, a:1 */
+ base += 4 * di; /* a: use Ra+4 (for i),
+ or Ra-4 (for d) */
+ /* else base = base; b use Ra */
+
+ /* Cole 3th Nov. 2010
+ We should consider both increasing and decreasing case.
+
+ Either case stores registers in the same order.
+ To simplify the code (yes, the loops),
+ I used the same pushing order, but from different side. */
+
+ if (di == 1) /* Increasing. */
+ base += (rn * 4 - 4);
+ /* else, in des case, we already are on the top */
+
+ for (i = 0; i < 4; i++)
+ {
+ if (enable4 & (1 << enb4map[aligned][i]))
+ {
+ info->saved_regs[NDS32_SP_REGNUM -
+ (enb4map[aligned][i])].addr = base;
+ base -= 4;
+ }
+ }
+
+ /* Skip re == rb == sp > fp. */
+ for (i = re; i >= rb && rb < NDS32_FP_REGNUM; i--)
+ {
+ info->saved_regs[i].addr = base;
+ base -= 4;
+ }
+
+ continue;
+ }
+ /* swi $lp, [$sp + (imm15s << 2)] */
+ /* We must check if $rt is $lp to determine it is
+ in prologue or not. */
+ if (CHOP_BITS (insn, 15) == N32_TYPE2 (SWI, REG_LP, REG_FP, 0))
+ {
+ int imm15s;
+
+ /* swi $lp, [$sp + (imm15s<<2)] */
+ imm15s = N32_IMM15S (insn);
+ info->saved_regs[NDS32_LP_REGNUM].addr = info->sp_offset
+ + (imm15s << 2);
+ continue;
+ }
+ /* swi.bi $rt, [$sp], (imm15s << 2) */
+ if (CHOP_BITS (insn, 15) == N32_TYPE2 (SWI_BI, REG_LP, REG_FP, 0))
+ {
+ unsigned int rt5 = 0;
+ unsigned int ra5 = 0;
+ int imm15s = 0;
+ rt5 = N32_RT5 (insn);
+ ra5 = N32_RA5 (insn);
+ imm15s = N32_IMM15S (insn);
+
+ if (ra5 == NDS32_SP_REGNUM)
+ {
+ info->saved_regs[rt5].addr = info->sp_offset;
+ info->sp_offset += (imm15s << 2);
+ }
+ else if (ra5 == NDS32_FP_REGNUM)
+ {
+ info->saved_regs[rt5].addr = info->fp_offset;
+ info->fp_offset += (imm15s << 2);
+ }
+ continue;
+ }
+
+ if (N32_OP6 (insn) == N32_OP6_COP && N32_COP_CP (insn) == 0
+ && (N32_COP_SUB (insn) == N32_FPU_FSS
+ || N32_COP_SUB (insn) == N32_FPU_FSD)
+ && (N32_RA5 (insn) == REG_SP || N32_RA5 (insn) == REG_FP))
+ {
+ /* CP shoud be CP0 */
+ /* fs[sd][.bi] $fst, [$sp + ($r0 << sv)] */
+ continue;
+ }
+
+ /* fssi $fst, [$ra + (imm12s << 2)]
+ fssi.bi $fst, [$ra], (imm12s << 2)
+ fsdi $fdt, [$ra + (imm12s << 2)]
+ fsdi.bi $fdt, [$ra], (imm12s << 2) */
+ if ((N32_OP6 (insn) == N32_OP6_SWC || N32_OP6 (insn) == N32_OP6_SDC)
+ && (N32_RA5 (insn) == REG_SP || N32_RA5 (insn) == REG_FP))
+ {
+ /* fssi and fsdi have the same form. */
+ /* Only .bi form should be handled to adjust reg. */
+ unsigned int ra5 = 0;
+ unsigned int fs5 = 0;
+ int imm12s = 0;
+
+ fs5 = N32_RT5 (insn);
+ ra5 = N32_RA5 (insn);
+ imm12s = N32_IMM12S (insn);
+
+ if (imm12s & 0x800)
+ imm12s = (imm12s - (0x800 << 1));
+
+ switch (ra5)
+ {
+ case NDS32_FP_REGNUM:
+ info->fp_offset += (imm12s << 2);
+ break;
+ case NDS32_SP_REGNUM:
+ info->sp_offset += (imm12s << 2);
+ break;
+ }
+
+ continue;
+ }
+
+ /* TODO: Handle mfsr and addi for interrupt handlers. */
+ break;
+ }
+ else
+ {
+ /* 16-bit instruction */
+ pc += 2;
+ insn >>= 16;
+
+ /* 1. If the instruction is j/b, then we stop
+ i.e., OP starts with 10, and beqzs8, bnezs8.
+ 2. If the operations will change sp/fp or based on sp/fp,
+ then we are in the prologue.
+ 3. If we don't know what's it, then stop. */
+
+ if (__GF (insn, 13, 2) == 2)
+ {
+ /* These are all branch instructions. */
+ pc -= 2;
+ break;
+ }
+ else if (__GF (insn, 9, 6) == 0x34)
+ {
+ /* beqzs8, bnezs8 */
+ pc -= 2;
+ break;
+ }
+
+ if (CHOP_BITS (insn, 10) == N16_TYPE10 (ADDI10S, 0))
+ {
+ /* addi10s */
+ info->sp_offset += N16_IMM10S (insn);
+ continue;
+ }
+
+ if (__GF (insn, 7, 8) == N16_T25_PUSH25)
+ {
+ /* push25 */
+ int imm8u = (insn & 0x1f) << 3;
+ int re = ((insn & 0x60) >> 5) & 0x3;
+ int res[] = {6, 8, 10, 14};
+ int m[] = {4, 6, 8, 12};
+ LONGEST base = info->sp_offset - 4;
+
+ /* Operation 1 - smw.adm R6, [sp], Re, #0xe */
+ info->saved_regs[NDS32_LP_REGNUM].addr = info->sp_offset - 0x4;
+ info->saved_regs[NDS32_GP_REGNUM].addr = info->sp_offset - 0x8;
+ info->saved_regs[NDS32_FP_REGNUM].addr = info->sp_offset - 0xC;
+ info->sp_offset -= m[re] * 4;
+
+ switch (re)
+ {
+ case 3:
+ info->saved_regs[NDS32_R0_REGNUM + 14].addr = info->sp_offset + 0x20;
+ info->saved_regs[NDS32_R0_REGNUM + 13].addr = info->sp_offset + 0x1C;
+ info->saved_regs[NDS32_R0_REGNUM + 12].addr = info->sp_offset + 0x18;
+ info->saved_regs[NDS32_R0_REGNUM + 11].addr = info->sp_offset + 0x14;
+ case 2:
+ info->saved_regs[NDS32_R0_REGNUM + 10].addr = info->sp_offset + 0x10;
+ info->saved_regs[NDS32_R0_REGNUM + 9].addr = info->sp_offset + 0xC;
+ case 1:
+ info->saved_regs[NDS32_R0_REGNUM + 8].addr = info->sp_offset + 0x8;
+ info->saved_regs[NDS32_R0_REGNUM + 7].addr = info->sp_offset + 0x4;
+ case 0:
+ info->saved_regs[NDS32_R0_REGNUM + 6].addr = info->sp_offset;
+ }
+
+ /* Operation 2 - sp = sp - imm5u<<3 */
+ info->sp_offset -= imm8u;
+
+ /* Operation 3 - if (Re >= 1) R8 = concat (PC(31,2), 2`b0) */
+ continue;
+ }
+
+ /* mov55 fp, sp */
+ if (insn == N16_TYPE55 (MOV55, REG_FP, REG_SP))
+ {
+ info->fp_offset = info->sp_offset;
+ info->use_frame = 1;
+ continue;
+ }
+ /* swi450 */
+ switch (insn & ~__MF (-1, 5, 4))
+ {
+ case N16_TYPE45 (SWI450, 0, REG_SP):
+ case N16_TYPE45 (SWI450, 0, REG_FP):
+ break;
+ }
+ /* swi37 - implied fp */
+ if (__GF (insn, 11, 4) == N16_T37_XWI37
+ && (insn & __BIT (7)))
+ continue;
+
+ /* swi37sp - implied */
+ if (__GF (insn, 11, 4) == N16_T37_XWI37SP
+ && (insn & __BIT (7)))
+ continue;
+
+ break;
+ }
+ }
+
+ info->size = -info->sp_offset;
+ /* Compute the previous frame's stack pointer (which is also the
+ frame's ID's stack address), and this frame's base pointer.
+
+ Assume that the FP is this frame's SP but with that pushed
+ stack space added back. */
+ next_base = get_frame_register_unsigned (this_frame, NDS32_SP_REGNUM);
+ prev_sp = next_base + info->size;
+ fp_base = get_frame_register_unsigned (this_frame, NDS32_FP_REGNUM);
+ if (info->use_frame && fp_base > 0)
+ {
+ /* Try to use FP if possible. */
+ prev_sp = fp_base - info->fp_offset;
+ }
+
+ /* Convert that SP/BASE into real addresses. */
+ info->prev_sp = prev_sp;
+ info->base = next_base;
+
+ /* Adjust all the saved registers so that they contain addresses and
+ not offsets. */
+ for (i = 0; i < gdbarch_num_regs (gdbarch) - 1; i++)
+ {
+ if (trad_frame_addr_p (info->saved_regs, i))
+ {
+ info->saved_regs[i].addr = info->prev_sp + info->saved_regs[i].addr;
+ }
+ }
+
+ /* The previous frame's SP needed to be computed.
+ Save the computed value. */
+ trad_frame_set_value (info->saved_regs, NDS32_SP_REGNUM, prev_sp);
+
+ return info;
+}
+
+/* Implement the gdbarch_skip_permanent_breakpoint method. */
+
+static void
+nds32_skip_permanent_breakpoint (struct regcache *regcache)
+{
+ int insn;
+ CORE_ADDR current_pc = regcache_read_pc (regcache);
+
+ /* On nds32, breakpoint may be BREAK or BREAK16. */
+ insn = read_memory_unsigned_integer (current_pc, 4, BFD_ENDIAN_BIG);
+
+ /* FIXME: Review this code. */
+ if (N32_OP6 (insn) == N32_OP6_MISC && N32_SUB5 (insn) == N32_MISC_BREAK)
+ current_pc += 4;
+ else if (__GF (insn, 9, 6) == 35 && N16_IMM9U (insn) < 32)
+ current_pc += 2;
+ else
+ return;
+
+ regcache_write_pc (regcache, current_pc);
+}
+
+/* Implement the gdbarch_read_pc method. */
+
+static CORE_ADDR
+nds32_read_pc (struct regcache *regcache)
+{
+ ULONGEST pc;
+ regcache_cooked_read_unsigned (regcache, NDS32_PC_REGNUM, &pc);
+ return pc;
+}
+
+/* Implement the gdbarch_write_pc method. */
+
+static void
+nds32_write_pc (struct regcache *regcache, CORE_ADDR val)
+{
+ regcache_cooked_write_unsigned (regcache, NDS32_PC_REGNUM, val);
+}
+
+/* Implement the gdbarch_unwind_pc method. */
+
+static CORE_ADDR
+nds32_unwind_pc (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+ /* This snippet code is a mess.
+
+ In most case, LP is the actually register being saved.
+ Hence when unwinding pc for backtrace, LP should be the one.
+ That is, for frames (level > 0), unwinding the PC means
+ unwinding LP from the this_frame.
+
+ However, for a top frame (level==0), unwinding PC means
+ the current program counter (PC).
+ Besides, for dummy frame, PC stored in dummy_frame is the one
+ we want.
+
+ We have to have these cases to make backtrace work properly. */
+
+ CORE_ADDR pc;
+ pc = frame_unwind_register_unsigned (this_frame, NDS32_PC_REGNUM);
+ return pc;
+}
+
+/* Implement the gdbarch_unwind_sp method. */
+
+static CORE_ADDR
+nds32_unwind_sp (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+ return frame_unwind_register_unsigned (this_frame, NDS32_SP_REGNUM);
+}
+
+/* If these is exactly one float point type field in the struct,
+ the alignment of the struct is the size of the float pointer type. */
+
+static int
+nds32_float_in_struct (struct type *type)
+{
+ struct type *actual_type;
+
+ type = check_typedef (type);
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT || TYPE_NFIELDS (type) != 1)
+ return 0;
+
+ actual_type = check_typedef (TYPE_FIELD_TYPE (type, 0));
+ if (TYPE_CODE (actual_type) == TYPE_CODE_FLT)
+ {
+ gdb_assert (TYPE_LENGTH (type) == 8 || TYPE_LENGTH (type) == 4);
+ return TYPE_LENGTH (type);
+ }
+ return 0;
+}
+
+/* Get the alignment of the type.
+
+ The alignment requirement of a structure is the largest alignment
+ requirement of its member, so we should traverse every member to
+ find the largest alignment.
+
+ For example,
+ struct { int a; int b; char c } is 4-byte aligned,
+ and
+ struct {long long a; char c} is 8-byte aligned. */
+
+static int
+nds32_type_align (struct type *type)
+{
+ int align = 0; /* Current max alignment. */
+ int i;
+
+ gdb_assert (type != NULL);
+ if (type == NULL)
+ return 0;
+
+ if (type->main_type->nfields == 0)
+ return type->length;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ return nds32_type_align (TYPE_TARGET_TYPE (type));
+ case TYPE_CODE_ENUM:
+ return TYPE_LENGTH (type);
+ }
+
+ /* For structs with only one float/double are treated as float/double. */
+ align = nds32_float_in_struct (type);
+ if (align)
+ return align;
+
+ for (i = 0; i < TYPE_NFIELDS (type); i++)
+ {
+ int r = nds32_type_align (TYPE_FIELD_TYPE (type, i));
+
+ if (r > align)
+ align = r;
+ }
+
+ return align;
+}
+
+/* Implement the gdbarch_push_dummy_call method. */
+
+static CORE_ADDR
+nds32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+ struct regcache *regcache, CORE_ADDR bp_addr,
+ int nargs, struct value **args, CORE_ADDR sp,
+ int struct_return, CORE_ADDR struct_addr)
+{
+ const int REND = 6; /* Max arguments number. */
+ int goff = 0; /* Current gpr for argument. */
+ int foff = 0; /* Currnet gpr for argument. */
+ int soff = 0; /* Current stack offset. */
+ int i;
+ struct type *type;
+ enum type_code typecode;
+ CORE_ADDR regval;
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int use_spill;
+ int use_fpr;
+ int fs0_regnum = -1, fd0_regnum = -1;
+
+ switch (tdep->nds32_abi)
+ {
+ case NDS32_ABI_V2:
+ case NDS32_ABI_V2FP:
+ use_spill = FALSE;
+ break;
+ default:
+ use_spill = TRUE;
+ break;
+ }
+
+ /* Use FP registers for calling iff when ABI==V2FP. */
+ use_fpr = (tdep->nds32_abi == NDS32_ABI_V2FP);
+ if (use_fpr)
+ {
+ fs0_regnum = user_reg_map_name_to_regnum (gdbarch, "fs0",
strlen ("fs0"));
+ fd0_regnum = user_reg_map_name_to_regnum (gdbarch, "fd0",
strlen ("fd0"));
+ }
+
+ /* Set the return address. For the nds32, the return breakpoint is
+ always at BP_ADDR. */
+ regcache_cooked_write_unsigned (regcache, NDS32_LP_REGNUM, bp_addr);
+
+ /* If STRUCT_RETURN is true, then the struct return address (in
+ STRUCT_ADDR) will consume the first argument-passing register.
+ Both adjust the register count and store that value. */
+ if (struct_return)
+ {
+ regcache_cooked_write_unsigned (regcache, NDS32_R0_REGNUM, struct_addr);
+ goff++;
+ }
+
+ /* Now make sure there's space on the stack */
+ for (i = 0; i < nargs; i++)
+ {
+ struct type *type = value_type (args[i]);
+ int align = nds32_type_align (type);
+
+ gdb_assert (align != 0);
+ sp -= TYPE_LENGTH (type);
+ if (align)
+ {
+ /* FIXME: Handle empty structure? */
+ sp &= ~(align - 1);
+ }
+ }
+
+ /* Stack must be 8-byte aligned. */
+ sp = sp & ~7;
+
+ soff = 0;
+ for (i = 0; i < nargs; i++)
+ {
+ const gdb_byte *val;
+ int align, len;
+
+ type = value_type (args[i]);
+ typecode = TYPE_CODE (type);
+ align = nds32_float_in_struct (type);
+ if (align)
+ typecode = TYPE_CODE_FLT;
+ else
+ align = nds32_type_align (type);
+ len = TYPE_LENGTH (type);
+
+ /* TODO: handle variables-size argument and variable-length arguments
+
+ COLE, GDB cannot know whether a type is variable-sized,
+ so we don't know whether push it as reference or value. */
+
+ val = value_contents (args[i]);
+
+ /* Once we start using stack, all arguments should go to stack
+ When use_fpr, all flt must go to fs/fd; otherwise go to stack. */
+ if (use_fpr && typecode == TYPE_CODE_FLT)
+ {
+ /* Adjust alignment. */
+ foff = (foff + ((align - 1) >> 2)) & ~((align - 1) >> 2);
+
+ if (foff < REND && !soff)
+ {
+ if (use_fpr && fs0_regnum == -1)
+ goto error_no_fpr;
+
+ switch (len)
+ {
+ case 4:
+ regcache_cooked_write (regcache, fs0_regnum + foff, val);
+ foff++;
+ continue;
+ case 8:
+ regcache_cooked_write (regcache, fd0_regnum + foff / 2, val);
+ foff += 2;
+ continue;
+ default:
+ /* Long double? */
+ internal_error (__FILE__, __LINE__,
+ "Do not know how to handle %d-byte double.\n",
+ len);
+ break;
+ }
+ }
+ }
+ else if (!soff)
+ {
+ /* Adjust alignment, and only adjust one time for one argument. */
+ goff = (goff + ((align - 1) >> 2)) & ~((align - 1) >> 2);
+ if (!use_spill && len > (REND - goff) * 4)
+ goff = REND;
+ }
+
+ /*
+ When passing arguments,
+
+ * A composite type not larger than 4 bytes is passed
+ in $rN. The format is as if the value is loaded with
+ load instruction of corresponding size. (i.g., LB, LH, LW)
+
+ For example,
+
+ r0
+ 31 0
+ little: [x x b a]
+ BIG: [x x a b]
+
+ * Otherwise, a composite type is passed in consective registers.
+ The size is rounded up to the nearest multiple of 4.
+ The successive registers hold the parts of the argument as if
+ were loaded using lmw instructions.
+
+ For example,
+
+ r0 r1
+ 31 0 31 0
+ little: [d c b a] [x x x e]
+ BIG: [a b c d] [e x x x]
+
+
+ When push an argument in stack,
+
+ * A composite type not larger than 4 bytes is copied
+ to memory at the next free space, in little-endian.
+ In big-endian, the last byte of the argument is aligned
+ at the next word address. For example,
+
+ sp [ - ] [ b ] hi
+ [ - ] [ a ]
+ [ b ] [ - ]
+ [ a ] [ - ] lo
+ little BIG
+ */
+
+ if (len > 4)
+ len = (len + 0x3) & ~0x3;
+
+ while (len > 0)
+ {
+ if (soff
+ || (typecode == TYPE_CODE_FLT && use_fpr && foff == REND)
+ || goff == REND)
+ {
+ int rlen = (len > 4) ? 4 : len;
+
+ if (byte_order == BFD_ENDIAN_BIG)
+ write_memory (sp + soff + 4 - rlen, val, rlen);
+ else
+ write_memory (sp + soff, val, rlen);
+ soff += 4;
+ }
+ else
+ {
+ regval = extract_unsigned_integer (val, (len > 4) ? 4 : len,
+ byte_order);
+ regcache_cooked_write_unsigned (regcache,
+ goff + NDS32_R0_REGNUM, regval);
+ goff++;
+ }
+
+ len -= register_size (gdbarch, goff);
+ val += register_size (gdbarch, goff);
+ }
+ }
+
+ /* Finally, update the SP register. */
+ regcache_cooked_write_unsigned (regcache, NDS32_SP_REGNUM, sp);
+
+ return sp;
+
+error_no_fpr:
+ /* If use_fpr, but no fs reigster exists, then it is an error. */
+ /* FIXME: Restore stack. */
+ error (_("Fail to call. FS0-FS5 is required."));
+}
+
+/* Given a return value in `regbuf' with a type `valtype',
+ extract and copy its value into `valbuf'. */
+
+static void
+nds32_extract_return_value (struct type *type, struct regcache *regcache,
+ gdb_byte *readbuf)
+{
+ int len = TYPE_LENGTH (type);
+ int typecode = TYPE_CODE (type);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int i;
+ int fs0_regnum, fd0_regnum;
+ int use_fpr;
+
+ use_fpr = (tdep->nds32_abi == NDS32_ABI_V2FP);
+
+ /* TODO: one-float, one-double is special case in V2FP.
+ Passed in FS/FD */
+ gdb_assert (TYPE_LENGTH (type) <= 8);
+ if (nds32_float_in_struct (type))
+ typecode = TYPE_CODE_FLT;
+
+ if (typecode == TYPE_CODE_FLT && use_fpr)
+ {
+ fs0_regnum = user_reg_map_name_to_regnum (gdbarch, "fs0",
strlen ("fs0"));
+ fd0_regnum = user_reg_map_name_to_regnum (gdbarch, "fd0",
strlen ("fd0"));
+
+ if (len == 4)
+ regcache_cooked_read (regcache, fs0_regnum, readbuf);
+ else if (len == 8)
+ regcache_cooked_read (regcache, fd0_regnum, readbuf);
+ else
+ internal_error (__FILE__, __LINE__,
+ _("Cannot extract return value of %d bytes "
+ "long floating point."),
+ len);
+ }
+ else
+ {
+ /* When returning result,
+
+ * A composite type not larger than 4 bytes is returned
+ in $r0. The format is as if the result is loaded with
+ load instruction of corresponding size. (i.g., LB, LH, LW)
+
+ For example,
+
+ r0
+ 31 0
+ little: [x x b a]
+ BIG: [x x a b]
+
+ * Otherwise, a composite type not larger than 8 bytes
+ is returned in $r0 and $r1. In little-endian, the first
+ word is loaded in $r0. In big-endian, the last word
+ is loaded in $r1.
+
+ For example,
+
+ r0 r1
+ 31 0 31 0
+ little: [d c b a] [x x x e]
+ BIG: [x x x a] [b c d e]
+ */
+
+ if (len <= 4)
+ {
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ regcache_raw_read_part (regcache, NDS32_R0_REGNUM, 4 - len, len,
+ readbuf);
+ else
+ regcache_raw_read_part (regcache, NDS32_R0_REGNUM, 0, len,
+ readbuf);
+ }
+ else if (len <= 8)
+ {
+ int partial = len - 4;
+
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ {
+ regcache_raw_read_part (regcache, NDS32_R0_REGNUM, 4 - partial,
+ partial, readbuf);
+ regcache_raw_read (regcache, NDS32_R0_REGNUM + 1,
+ readbuf + partial);
+
+ }
+ else
+ {
+ regcache_raw_read (regcache, NDS32_R0_REGNUM, readbuf);
+ regcache_raw_read_part (regcache, NDS32_R0_REGNUM + 1, 0,
+ partial, readbuf + 4);
+ }
+ }
+ else
+ internal_error (__FILE__, __LINE__,
+ _("Cannot extract return value of %d bytes long."),
+ len);
+ }
+}
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format.
+ Things always get returned in RET1_REGNUM, RET2_REGNUM. */
+
+static void
+nds32_store_return_value (struct type *type, struct regcache *regcache,
+ const gdb_byte *writebuf)
+{
+ int len = TYPE_LENGTH (type);
+ int typecode = TYPE_CODE (type);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int i;
+ int fs0_regnum, fd0_regnum;
+ int use_fpr;
+
+ use_fpr = (tdep->nds32_abi == NDS32_ABI_V2FP);
+
+ /* TODO: one-float, one-double is special case in V2FP.
+ Passed in FS/FD */
+ gdb_assert (TYPE_LENGTH (type) <= 8);
+ if (nds32_float_in_struct (type))
+ typecode = TYPE_CODE_FLT;
+
+ if (typecode == TYPE_CODE_FLT && use_fpr)
+ {
+ fs0_regnum = user_reg_map_name_to_regnum (gdbarch, "fs0",
strlen ("fs0"));
+ fd0_regnum = user_reg_map_name_to_regnum (gdbarch, "fd0",
strlen ("fd0"));
+
+ if (len == 4)
+ regcache_cooked_write (regcache, fs0_regnum, writebuf);
+ else if (len == 8)
+ regcache_cooked_write (regcache, fd0_regnum, writebuf);
+ else
+ internal_error (__FILE__, __LINE__,
+ _("Cannot store return value of %d bytes long "
+ "floating point."),
+ len);
+ }
+ else
+ {
+ if (len <= 4)
+ {
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ regcache_raw_write_part (regcache, NDS32_R0_REGNUM, 4 - len, len,
+ writebuf);
+ else
+ regcache_raw_write_part (regcache, NDS32_R0_REGNUM, 0, len,
+ writebuf);
+ }
+ else if (len <= 8)
+ {
+ int partial = len - 4;
+
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ {
+ regcache_raw_write_part (regcache, NDS32_R0_REGNUM, 4 - partial,
+ partial, writebuf);
+ regcache_raw_write (regcache, NDS32_R0_REGNUM + 1,
+ writebuf + partial);
+
+ }
+ else
+ {
+ regcache_raw_write (regcache, NDS32_R0_REGNUM, writebuf);
+ regcache_raw_write_part (regcache, NDS32_R0_REGNUM + 1, 0,
+ partial, writebuf + 4);
+ }
+ }
+ else
+ internal_error (__FILE__, __LINE__,
+ _("Cannot store return value of %d bytes long."),
+ len);
+ }
+}
+
+/* Implement the gdbarch_return_value method. */
+
+static enum return_value_convention
+nds32_return_value (struct gdbarch *gdbarch, struct value *func_type,
+ struct type *type, struct regcache *regcache,
+ gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+ if (TYPE_LENGTH (type) > 8)
+ {
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ }
+ else
+ {
+ /* `readbuf' is used for 'call' to get the return value.
+ `writebuf' is used for 'return' to set the return value. */
+ if (readbuf != NULL)
+ nds32_extract_return_value (type, regcache, readbuf);
+ if (writebuf != NULL)
+ nds32_store_return_value (type, regcache, writebuf);
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+}
+
+/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
+ dummy frame. The frame ID's base needs to match the TOS value
+ saved by save_dummy_frame_tos(), and the PC match the dummy frame's
+ breakpoint. */
+
+static struct frame_id
+nds32_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+ CORE_ADDR sp, pc;
+
+ sp = get_frame_register_unsigned (this_frame, NDS32_SP_REGNUM);
+ pc = get_frame_pc (this_frame);
+ return frame_id_build (sp, get_frame_pc (this_frame));
+}
+
+/* Given a GDB frame, determine the address of the calling function's
+ frame. This will be used to create a new GDB frame struct. */
+
+static void
+nds32_frame_this_id (struct frame_info *this_frame,
+ void **this_prologue_cache, struct frame_id *this_id)
+{
+ struct nds32_unwind_cache *info;
+ CORE_ADDR base;
+ CORE_ADDR func;
+ struct minimal_symbol *msym_stack;
+ struct frame_id id;
+ enum bfd_endian byte_order_for_code = BFD_ENDIAN_BIG;
+
+ info = nds32_frame_unwind_cache (this_frame, this_prologue_cache);
+
+ /* Get function entry address */
+ func = get_frame_func (this_frame);
+
+ /* Hopefully the prologue analysis either correctly determined the
+ frame's base (which is the SP from the previous frame), or set
+ that base to "NULL". */
+ base = info->prev_sp;
+ if (base == 0)
+ return;
+
+ id = frame_id_build (base, func);
+ (*this_id) = id;
+}
+
+/* Get the value of register REGNUM in previous frame. */
+
+static struct value *
+nds32_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
+{
+ struct nds32_unwind_cache *cache;
+ cache = nds32_frame_unwind_cache (this_frame, this_prologue_cache);
+
+ if (regnum == NDS32_PC_REGNUM)
+ {
+ CORE_ADDR lr;
+ struct frame_info *next_frame;
+
+ lr = frame_unwind_register_unsigned (this_frame, NDS32_LP_REGNUM);
+ return frame_unwind_got_constant (this_frame, regnum, lr);
+ }
+
+ return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
+}
+
+/* The register in previous frame. For example, the previous PC is
+ current LP. */
+
+static struct value *
+nds32_dwarf2_prev_register (struct frame_info *this_frame,
+ void **this_cache, int regnum)
+{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ CORE_ADDR lp;
+
+ switch (regnum)
+ {
+ case NDS32_PC_REGNUM:
+ lp = frame_unwind_register_unsigned (this_frame, NDS32_LP_REGNUM);
+ return frame_unwind_got_constant (this_frame, regnum, lp);
+ default:
+ internal_error (__FILE__, __LINE__,
+ _("Unexpected register %d"), regnum);
+ }
+
+ return NULL;
+}
+
+/* Callback of dwarf2_frame_set_init_reg. */
+
+static void
+nds32_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+ struct dwarf2_frame_state_reg *reg,
+ struct frame_info *this_frame)
+{
+ switch (regnum)
+ {
+ case NDS32_PC_REGNUM:
+ reg->how = DWARF2_FRAME_REG_FN;
+ reg->loc.fn = nds32_dwarf2_prev_register;
+ break;
+ case NDS32_SP_REGNUM:
+ reg->how = DWARF2_FRAME_REG_CFA;
+ break;
+ }
+}
+
+/* Implement the gdbarch_get_longjmp_target method. */
+
+static int
+nds32_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
+{
+ gdb_byte buf[4];
+ CORE_ADDR jmp_buf_p;
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ jmp_buf_p = get_frame_register_unsigned (frame, 0);
+
+ /* Key is in setjmp():
+ lmw.bim r6, [r0], r14
+ lmw.bim r16, [r0], r19, 0xf */
+
+ if (target_read_memory (jmp_buf_p + 15 * 4, buf, 4))
+ return 0;
+
+ *pc = extract_unsigned_integer (buf, 4, byte_order);
+
+ return 1;
+}
+
+static const struct frame_unwind nds32_frame_unwind =
+{
+ NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
+ nds32_frame_this_id,
+ nds32_frame_prev_register,
+ NULL /* unwind_data */,
+ default_frame_sniffer
+};
+
+/* Signal trampolines. */
+
+static struct nds32_unwind_cache *
+nds32_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
+{
+ struct nds32_unwind_cache *cache;
+ CORE_ADDR addr;
+ gdb_byte buf[4];
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+ if (*this_cache)
+ return *this_cache;
+
+ cache = nds32_alloc_frame_cache (this_frame);
+
+ cache->base = get_frame_register_unsigned (this_frame, NDS32_SP_REGNUM);
+
+ addr = tdep->sigcontext_addr (this_frame);
+
+ if (tdep->sc_reg_offset)
+ {
+ int i;
+
+ /* GPRs, PC and d[01](lo|hi) */
+ gdb_assert (tdep->sc_num_regs <= 37);
+
+ for (i = 0; i < tdep->sc_num_regs; i++)
+ if (tdep->sc_reg_offset[i] != -1)
+ cache->saved_regs[i].addr = addr + tdep->sc_reg_offset[i];
+ }
+ else
+ {
+ cache->saved_regs[NDS32_PC_REGNUM].addr = addr + tdep->sc_pc_offset;
+ cache->saved_regs[NDS32_LP_REGNUM].addr = addr + tdep->sc_lp_offset;
+ cache->saved_regs[NDS32_SP_REGNUM].addr = addr + tdep->sc_sp_offset;
+ cache->saved_regs[NDS32_FP_REGNUM].addr = addr + tdep->sc_fp_offset;
+ }
+
+ *this_cache = cache;
+ return cache;
+}
+
+static void
+nds32_sigtramp_frame_this_id (struct frame_info *this_frame,
+ void **this_cache, struct frame_id *this_id)
+{
+ struct nds32_unwind_cache *cache;
+
+ cache = nds32_sigtramp_frame_cache (this_frame, this_cache);
+
+ (*this_id) = frame_id_build (cache->base, get_frame_pc (this_frame));
+}
+
+static struct value *
+nds32_sigtramp_frame_prev_register (struct frame_info *this_frame,
+ void **this_cache, int regnum)
+{
+ struct nds32_unwind_cache *cache;
+
+ /* Make sure we've initialized the cache. */
+ cache = nds32_sigtramp_frame_cache (this_frame, this_cache);
+
+ /* For signal frame, unwind PC for PC and LP for LP;
+ otherwise, we will fail to unwind a leaf-function.
+ This different from unwinding a normal-frame. */
+ return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
+}
+
+static int
+nds32_sigtramp_frame_sniffer (const struct frame_unwind *self,
+ struct frame_info *this_frame,
+ void **this_prologue_cache)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame));
+
+ /* We shouldn't even bother if we don't have a sigcontext_addr
+ handler. */
+ if (tdep->sigcontext_addr == NULL)
+ return 0;
+
+ if (tdep->sigtramp_p != NULL)
+ {
+ if (tdep->sigtramp_p (this_frame))
+ return 1;
+ }
+
+#if 0
+ /* TODO: extend the sniffer as following if (tdep->sigtramp_start != 0) */
+ {
+ CORE_ADDR pc = frame_pc_unwind (this_frame);
+
+ gdb_assert (tdep->sigtramp_end != 0);
+ if (pc >= tdep->sigtramp_start && pc < tdep->sigtramp_end)
+ return &nds32_sigtramp_frame_unwind;
+ }
+#endif
+ return 0;
+}
+
+static const struct frame_unwind nds32_sigtramp_frame_unwind =
+{
+ SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
+ nds32_sigtramp_frame_this_id,
+ nds32_sigtramp_frame_prev_register,
+ NULL /* unwind_data */,
+ nds32_sigtramp_frame_sniffer
+};
+
+static CORE_ADDR
+nds32_frame_base_address (struct frame_info *this_frame, void **this_cache)
+{
+ struct nds32_unwind_cache *info;
+
+ info = nds32_frame_unwind_cache (this_frame, this_cache);
+
+ return info->base;
+}
+
+static const struct frame_base nds32_frame_base =
+{
+ &nds32_frame_unwind,
+ nds32_frame_base_address,
+ nds32_frame_base_address,
+ nds32_frame_base_address
+};
+
+static void
+nds32_simple_overlay_update (struct obj_section *osect)
+{
+ struct minimal_symbol *minsym = NULL;
+
+ minsym = lookup_minimal_symbol (".nds32.fixed.size", NULL, NULL);
+ if (minsym != NULL && osect != NULL)
+ {
+ bfd *obfd = osect->objfile->obfd;
+ asection *bsect = osect->the_bfd_section;
+ if (bfd_section_vma (obfd, bsect) < SYMBOL_VALUE_ADDRESS (minsym))
+ {
+ osect->ovly_mapped = 1;
+ return;
+ }
+ }
+
+ simple_overlay_update (osect);
+}
+
+static int
+gdb_print_insn_nds32 (bfd_vma memaddr, disassemble_info *info)
+{
+ struct gdbarch *gdbarch = info->application_data;
+ struct obj_section * s = find_pc_section (memaddr);
+ struct cleanup *back_to;
+
+ /* Reload symtab if abfd changed.
+ In case there are multiple ITB in different shared objects. */
+ if (s == NULL || info->section != s->the_bfd_section)
+ {
+ xfree (info->symtab);
+ info->symtab = NULL;
+ info->symtab_size = 0;
+ }
+
+ if (info->symtab == NULL && s && s->the_bfd_section)
+ {
+ long storage = bfd_get_symtab_upper_bound (s->objfile->obfd);
+
+ if (storage <= 0)
+ goto done;
+
+ info->section = s->the_bfd_section;
+ info->symtab = xmalloc (storage);
+ info->symtab_size =
+ bfd_canonicalize_symtab (s->the_bfd_section->owner, info->symtab);
+ }
+
+done:
+ return print_insn_nds32 (memaddr, info);
+}
+
+/* Callback for gdbarch_init. */
+
+static struct gdbarch *
+nds32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+ struct gdbarch *gdbarch;
+ struct gdbarch_tdep *tdep;
+ struct gdbarch_list *best_arch;
+ const struct target_desc *tdesc = NULL;
+ unsigned int nds32_abi = NDS32_ABI_AUTO;
+ struct tdesc_arch_data *tdesc_data = NULL;
+ unsigned int eflags = 0;
+ int i;
+
+ /* Extract the elf_flags, if available. */
+ if (info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
+ {
+ eflags = elf_elfheader (info.abfd)->e_flags;
+ nds32_abi = (eflags >> 4) & 0xF;
+ }
+
+ /* Allocate space for the new architecture. */
+ tdep = XCALLOC (1, struct gdbarch_tdep);
+ gdbarch = gdbarch_alloc (&info, tdep);
+
+ if (tdesc_has_registers (info.target_desc))
+ {
+ int valid_p;
+ int fpregs = -1;
+ static const char *const nds32_fp_names[] = { "r28", "fp", NULL };
+ static const char *const nds32_lp_names[] = { "r30", "lp", NULL };
+ static const char *const nds32_sp_names[] = { "r31", "sp", NULL };
+ const struct tdesc_feature *feature;
+
+ /* Validate and initialize target-description here. */
+ tdesc = info.target_desc;
+ tdesc_data = tdesc_data_alloc ();
+
+ info.tdep_info = (void *) tdesc_data;
+
+ feature = tdesc_find_feature (tdesc, "org.gnu.gdb.nds32.core");
+ if (!feature)
+ return 0;
+
+ /* Validate for FP, LP, GP, PC. */
+ valid_p = 1;
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ NDS32_FP_REGNUM,
+ nds32_fp_names);
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ NDS32_LP_REGNUM,
+ nds32_lp_names);
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ NDS32_SP_REGNUM,
+ nds32_sp_names);
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ NDS32_PC_REGNUM, "pc");
+
+ if (!valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ xfree (tdep);
+ gdbarch_free (gdbarch);
+ return NULL;
+ }
+
+ /* Number R0-R27. */
+ for (i = NDS32_R0_REGNUM; i < NDS32_FP_REGNUM; i++)
+ tdesc_numbered_register (feature, tdesc_data, i, nds32_regnames[i]);
+
+ /* Number D0 and D1. */
+ for (i = NDS32_D0LO_REGNUM; i <= NDS32_D1HI_REGNUM; i++)
+ tdesc_numbered_register (feature, tdesc_data, i, nds32_regnames[i]);
+
+ /* Find register configuration of FPU. */
+ feature = tdesc_find_feature (tdesc, "org.gnu.gdb.nds32.fpu");
+ if (feature)
+ {
+ if (tdesc_unnumbered_register (feature, "fd31"))
+ fpregs = 3;
+ else if (tdesc_unnumbered_register (feature, "fd15"))
+ fpregs = 2;
+ else if (tdesc_unnumbered_register (feature, "fd7"))
+ fpregs = 1;
+ else if (tdesc_unnumbered_register (feature, "fd3"))
+ fpregs = 0;
+ }
+ tdep->nds32_fpregs = fpregs;
+
+ /* If FS registers do not exist, make them pseudo registers
+ of FD registers. */
+ if (fpregs != -1 && tdesc_unnumbered_register (feature, "fs0") == 0)
+ {
+ int fsregs = (fpregs + 1) * 8;
+
+ if (fsregs > 32)
+ fsregs = 32;
+
+ set_gdbarch_num_pseudo_regs (gdbarch, fsregs);
+ set_gdbarch_pseudo_register_read (gdbarch, nds32_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch, nds32_pseudo_register_write);
+ set_tdesc_pseudo_register_name (gdbarch, nds32_register_name);
+ }
+
+ set_gdbarch_num_regs (gdbarch, NDS32_NUM_REGS);
+ tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+ }
+ else
+ {
+ /* Simulator or legacy target. */
+
+ /* Physical 32 FD registers. */
+ set_gdbarch_num_regs (gdbarch, NDS32_SIM_NUM_REGS);
+ set_gdbarch_register_name (gdbarch, nds32_register_name);
+
+ /* Pseudo 32 FS registers. */
+ set_gdbarch_num_pseudo_regs (gdbarch, 32);
+ set_gdbarch_pseudo_register_read (gdbarch, nds32_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch, nds32_pseudo_register_write);
+ }
+
+ tdep->nds32_abi = nds32_abi;
+ tdep->eflags = eflags;
+
+ /* Overwrite ABI if set explicitly. */
+ if (nds32_config.use_abi != NDS32_ABI_AUTO)
+ tdep->nds32_abi = nds32_config.use_abi;
+
+ /* Set offsets for signal context. */
+ tdep->sigtramp_p = NULL;
+ tdep->sigcontext_addr = NULL;
+ tdep->sc_pc_offset = -1;
+ tdep->sc_sp_offset = -1;
+ tdep->sc_fp_offset = -1;
+
+ /* If there is already a candidate, use it. */
+ for (best_arch = gdbarch_list_lookup_by_info (arches, &info);
+ best_arch != NULL;
+ best_arch = gdbarch_list_lookup_by_info (best_arch->next, &info))
+ {
+ struct gdbarch_tdep *idep = gdbarch_tdep (best_arch->gdbarch);
+
+ if (nds32_abi != idep->nds32_abi)
+ continue;
+
+ /* Check FPU registers. */
+ if (idep->nds32_fpregs != tdep->nds32_fpregs)
+ continue;
+
+ /* Found a match. */
+ break;
+ }
+
+ if (best_arch != NULL)
+ {
+ xfree (tdep);
+ gdbarch_free (gdbarch);
+ return best_arch->gdbarch;
+ }
+
+ nds32_add_reggroups (gdbarch);
+
+ gdbarch_init_osabi (info, gdbarch);
+
+ /* Override tdesc_register callbacks for system registers. */
+ set_gdbarch_register_reggroup_p (gdbarch, nds32_register_reggroup_p);
+ set_gdbarch_register_type (gdbarch, nds32_register_type);
+
+ set_gdbarch_sp_regnum (gdbarch, NDS32_SP_REGNUM);
+ set_gdbarch_pc_regnum (gdbarch, NDS32_PC_REGNUM);
+ set_gdbarch_read_pc (gdbarch, nds32_read_pc);
+ set_gdbarch_write_pc (gdbarch, nds32_write_pc);
+ set_gdbarch_unwind_sp (gdbarch, nds32_unwind_sp);
+ set_gdbarch_unwind_pc (gdbarch, nds32_unwind_pc);
+ set_gdbarch_in_function_epilogue_p (gdbarch, nds32_in_function_epilogue_p);
+ set_gdbarch_dwarf2_reg_to_regnum (gdbarch, nds32_dwarf_dwarf2_reg_to_regnum);
+ set_gdbarch_register_sim_regno (gdbarch, nds32_register_sim_regno);
+ set_gdbarch_push_dummy_call (gdbarch, nds32_push_dummy_call);
+ set_gdbarch_return_value (gdbarch, nds32_return_value);
+ set_gdbarch_skip_prologue (gdbarch, nds32_skip_prologue);
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ set_gdbarch_breakpoint_from_pc (gdbarch, nds32_breakpoint_from_pc);
+ set_gdbarch_remote_breakpoint_from_pc (gdbarch,
nds32_remote_breakpoint_from_pc);
+ set_gdbarch_frame_align (gdbarch, nds32_frame_align);
+ frame_base_set_default (gdbarch, &nds32_frame_base);
+
+ /* Methods for saving / extracting a dummy frame's ID.
+ The ID's stack address must match the SP value returned by
+ PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos. */
+ set_gdbarch_dummy_id (gdbarch, nds32_dummy_id);
+ set_gdbarch_print_insn (gdbarch, gdb_print_insn_nds32);
+ set_gdbarch_skip_permanent_breakpoint (gdbarch,
+ nds32_skip_permanent_breakpoint);
+ /* Support simple overlay manager. */
+ set_gdbarch_overlay_update (gdbarch, nds32_simple_overlay_update);
+
+ /* Handle longjmp. */
+ set_gdbarch_get_longjmp_target (gdbarch, nds32_get_longjmp_target);
+
+ /* The order of appending is the order it check frame. */
+ dwarf2_frame_set_init_reg (gdbarch, nds32_dwarf2_frame_init_reg);
+ if (nds32_config.use_cfi)
+ dwarf2_append_unwinders (gdbarch);
+ frame_unwind_append_unwinder (gdbarch, &nds32_sigtramp_frame_unwind);
+ frame_unwind_append_unwinder (gdbarch, &nds32_frame_unwind);
+
+ /* Add nds32 register aliases. */
+ /* FIXME: This is a simple workaround to force user-reg being
+ initialized before gdbarch initialized.
+ Without this, calling user_reg_map_name_to_regnum ()
+ will crash. */
+ user_reg_add (gdbarch, "r0", nds32_value_of_reg, "r0");
+ for (i = 0; i < ARRAY_SIZE (nds32_register_aliases); i++)
+ {
+ int regnum;
+
+ regnum = user_reg_map_name_to_regnum
+ (gdbarch, nds32_register_aliases[i].name, -1);
+
+ if (regnum == -1)
+ continue;
+
+ user_reg_add (gdbarch, nds32_register_aliases[i].alias,
+ nds32_value_of_reg, nds32_register_aliases[i].name);
+ }
+
+ return gdbarch;
+}
+
+/* Callback for "nds32 dump" command.
+
+ Dump current register and stack for debug gdb. */
+
+static void
+nds32_dump_command (char *arg, int from_tty)
+{
+ ULONGEST val;
+ ULONGEST sp;
+ FILE *f_script;
+ char cmdline[512];
+ int i;
+
+ if (arg == NULL)
+ {
+ printf_unfiltered (_("Missing filename argument.\n"));
+ return;
+ }
+
+ regcache_raw_read_unsigned (get_current_regcache (), NDS32_SP_REGNUM, &sp);
+
+ sprintf (cmdline, "dump binary memory %s.stack 0x%lx 0x%lx",
+ arg, (long) sp, ((long) sp + 1024 - 1) & ~(1024 - 1));
+ execute_command (cmdline, from_tty);
+
+ sprintf (cmdline, "%s.gdbinit", arg);
+ f_script = fopen (cmdline, "w");
+ if (f_script == NULL)
+ {
+ printf_unfiltered (_("Fail to generate dump .gdbinit."));
+ return ;
+ }
+
+ /* Gather all user registers. */
+ for (i = 0; i <= NDS32_D1HI_REGNUM; i++)
+ {
+ regcache_raw_read_unsigned (get_current_regcache (), i, &val);
+ fprintf (f_script, "set $%s = 0x%lx\n", nds32_regnames[i], (long) val);
+ }
+
+ fprintf (f_script, "restore %s.stack binary 0x%lx\n", arg, (long) sp);
+ fclose (f_script);
+}
+
+static int
+nds32_config_int (const char *str, int def)
+{
+ int val = def;
+
+ if (getenv (str))
+ val = atoi (getenv (str));
+ if (val != def)
+ printf ("%s=%d\n", str, val);
+ return val;
+}
+
+static void
+nds32_load_config (struct nds32_gdb_config *config)
+{
+ config->use_cfi = nds32_config_int ("USE_CFI", 1);
+ config->use_abi = nds32_config_int ("USE_ABI", NDS32_ABI_AUTO);
+}
+
+/* Callback for "nds32" command. */
+
+static void
+nds32_command (char *arg, int from_tty)
+{
+ printf_unfiltered (_("\"nds32\" must be followed by arguments\n"));
+}
+
+struct cmd_list_element *nds32_cmdlist;
+
+void
+_initialize_nds32_tdep (void)
+{
+ /* Internal used config for testing. */
+ nds32_load_config (&nds32_config);
+
+ add_prefix_cmd ("nds32", no_class, nds32_command,
+ _("Various nds32-specific commands."), &nds32_cmdlist,
+ "nds32 ", 0, &cmdlist);
+
+ add_cmd ("dump", class_files, nds32_dump_command,
+ _("dump stack and GPRs for debugging"), &nds32_cmdlist);
+
+ nds32_init_remote_cmds ();
+
+ /* Initialize gdbarch. */
+ register_gdbarch_init (bfd_arch_nds32, nds32_gdbarch_init);
+
+ /* Following are NDS32 specific commands. */
+
+ nds32_init_reggroups ();
+
+ register_remote_support_xml ("nds32");
+}
diff --git a/gdb/nds32-tdep.h b/gdb/nds32-tdep.h
new file mode 100644
index 0000000..2a71a14
--- /dev/null
+++ b/gdb/nds32-tdep.h
@@ -0,0 +1,127 @@
+/* Common target dependent code for GDB on nds32 systems.
+
+ Copyright (C) 2006-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 "nds32-utils.h"
+
+#ifndef __NDS32_TDEP_H__
+#define __NDS32_TDEP_H__
+
+/* Define numbers of registers we have in NDS32 arch. */
+
+#define NDS32_NUM_PSEUDO_REGS (NDS32_NUM_FPR)
+
+/* NDS32 virtual registers layout for GDB. */
+enum nds32_regnum
+{
+ /* General purpose registers. */
+ NDS32_R0_REGNUM = 0,
+ NDS32_R5_REGNUM = 5,
+ NDS32_TA_REGNUM = 15, /* Temp for assembler. */
+ NDS32_FP_REGNUM = 28, /* Frame register. */
+ NDS32_GP_REGNUM = 29, /* Global register. */
+ NDS32_LP_REGNUM = 30, /* Link pointer. */
+ NDS32_SP_REGNUM = 31, /* Address of stack top. */
+
+ /* Pseudo PC. */
+ NDS32_PC_REGNUM = 32,
+
+ /* D0/D1 User Registers. */
+ NDS32_D0LO_REGNUM = 33,
+ NDS32_D0HI_REGNUM = 34,
+ NDS32_D1LO_REGNUM = 35,
+ NDS32_D1HI_REGNUM = 36,
+
+ /* If target-description is not supported, only assume above
+ registers are supported. */
+ NDS32_NUM_REGS,
+
+ /* These are only used by simulator. */
+ NDS32_SIM_FD0_REGNUM = NDS32_NUM_REGS,
+ NDS32_SIM_IFCLP_REGNUM = NDS32_SIM_FD0_REGNUM + 32,
+ NDS32_SIM_ITB_REGNUM,
+ NDS32_SIM_PSW_REGNUM,
+
+ NDS32_SIM_NUM_REGS,
+};
+
+/* All the possible NDS32 ABIs. They must be consistent with elf/nds32.h. */
+enum nds32_abi
+{
+ NDS32_ABI_V0 = 0,
+ NDS32_ABI_V1,
+ NDS32_ABI_V2,
+ NDS32_ABI_V2FP,
+ NDS32_ABI_AABI,
+ NDS32_ABI_END,
+ NDS32_ABI_BEGIN = NDS32_ABI_V0,
+ /* ABI flag is only 4-bits long. */
+ NDS32_ABI_AUTO = 0xFFFFFFFF
+};
+
+/* ----------------------------------------------
+ 31 28 27 8 7 4 3 0
+ ----------------------------------------------
+ | ARCH | CONFUGURAION FIELD | ABI | VERSION |
+ ---------------------------------------------- */
+struct htab;
+struct gdbarch_tdep
+{
+ /* ABI version */
+ enum nds32_abi nds32_abi;
+ int nds32_fpregs;
+
+ unsigned int eflags;
+
+ /* Detect sigtramp. */
+ int (*sigtramp_p) (struct frame_info *);
+
+ /* Get address of sigcontext for sigtramp. */
+ CORE_ADDR (*sigcontext_addr) (struct frame_info *);
+
+ /* Offset of saved PC in jmp_buf. */
+ /* TODO: int jb_pc_offset; */
+
+ /* Offset of saved PC and SP in `struct sigcontext'. */
+ int sc_pc_offset;
+ int sc_lp_offset;
+ int sc_sp_offset;
+ int sc_fp_offset;
+
+ int *sc_reg_offset;
+ int sc_num_regs;
+
+ struct htab *type_tab;
+};
+
+/* Hidden options. */
+struct nds32_gdb_config
+{
+ /* Use DWARF/CFI for stack frame unwinding.
+ This is much reliable than manual prologue analysis.
+ Default true. */
+ int use_cfi;
+
+ /* ABI for Inferior Call Setup.
+ Default AUTO by reading ABI in ELF header. */
+ int use_abi;
+};
+
+extern struct cmd_list_element *nds32_cmdlist;
+#endif
diff --git a/gdb/nds32-utils.c b/gdb/nds32-utils.c
new file mode 100644
index 0000000..27241e7
--- /dev/null
+++ b/gdb/nds32-utils.c
@@ -0,0 +1,247 @@
+/* Common target dependent code for GDB on nds32 systems.
+
+ Copyright (C) 2006-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 "defs.h"
+#include "top.h" /* for source_script */
+#include "exceptions.h" /* for catch_command_errors */
+#include "ui-file.h" /* struct ui_file_buffer */
+#include "nds32-utils.h"
+#include "gdbtypes.h"
+#include "gdb_assert.h"
+#include "floatformat.h"
+#include "hashtab.h"
+#include <stdio.h>
+#include <string.h>
+
+/* Helpers for allocating types. */
+
+/* Allocate a new type.
+ Use this instead of arch_composite_type () or arch_type () directly,
+ because it must be a 4-byte word, but we may not append all the fields.
+ If `opt' is USE_FLAGS, then a field for flags is appended. */
+
+struct type *
+nds32_init_type (struct gdbarch *gdbarch, char *name, enum type_option opt)
+{
+ struct type *type;
+
+ gdb_assert (opt == USE_FLAGS || opt == NO_FLAGS);
+
+ type = arch_type (gdbarch, TYPE_CODE_STRUCT, 4, name);
+ TYPE_TAG_NAME (type) = name;
+ INIT_CPLUS_SPECIFIC (type);
+
+ if (opt == USE_FLAGS)
+ {
+ int i;
+ struct type *flags_type =
+ arch_flags_type (TYPE_OWNER (type).gdbarch, "nds32_dummy_flags_type",
+ TYPE_LENGTH (type));
+ append_composite_type_field_raw (type, "", flags_type);
+
+ /* Hide all the flags from users,
+ only explicitly appened flags are showen to users.
+ For example,
+ {[ #1 #3 #16 #17 #18 ], INTL = Lv1, POM = Superuser}
+ We don't want users to see this,
+ INTL and POM should be hidden from users. */
+ for (i = 0; i < TYPE_LENGTH (type) * TARGET_CHAR_BIT; i++)
+ append_flags_type_flag (flags_type, i, NULL);
+ }
+
+ return type;
+}
+
+/* Append a flags bit. */
+
+void
+nds32_append_flag (struct type *type, int bitpos, char *name)
+{
+ struct field *f;
+ int nfields;
+
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT);
+
+ nfields = TYPE_NFIELDS (type);
+
+ if (nfields == 0
+ || TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) != TYPE_CODE_FLAGS)
+ {
+ internal_error (__FILE__, __LINE__,
+ _("Pseudo field for flags must be the first one."));
+ }
+
+ /* Append flag in the first field. */
+ append_flags_type_flag (TYPE_FIELD_TYPE (type, 0), bitpos, name);
+}
+
+/* Append a bit-field. */
+
+void
+nds32_append_bitfield (struct type *type, struct type *field_type,
+ int bitpos_from, int bitpos_to, char *name)
+{
+ struct field *f;
+
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT);
+ gdb_assert (bitpos_to >= bitpos_from);
+ gdb_assert (TYPE_NFIELDS (type) != 0 || strcmp (name, "") != 0);
+
+ f = append_composite_type_field_raw (type, xstrdup (name), field_type);
+ SET_FIELD_BITPOS (f[0], bitpos_from);
+ FIELD_BITSIZE (f[0]) = bitpos_to - bitpos_from + 1;
+}
+
+/* Allocate an enumeration type. The only reason to call this function
+ is that we want it to be UNSIGNED instead. This is only useful for
+ enum-type bit-field. */
+
+struct type *
+nds32_init_enum (struct gdbarch *gdbarch, char *name)
+{
+ struct type *type;
+
+ type = arch_type (gdbarch, TYPE_CODE_ENUM, 4, name);
+ TYPE_UNSIGNED (type) = 1;
+ return type;
+}
+
+void
+nds32_append_enum (struct type *type, int enumval, char *name)
+{
+ struct field *f;
+
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_ENUM);
+ f = append_composite_type_field_raw (type, name, NULL);
+ SET_FIELD_ENUMVAL (f[0], enumval);
+}
+
+/* Helpers for type table. */
+
+struct type_entry
+{
+ const char *name;
+ struct type *type;
+};
+
+/* Hash code function. Simply a wrapper for htab_hash_string. */
+
+static hashval_t
+type_hash_string (const PTR p)
+{
+ struct type_entry *e = (struct type_entry *) p;
+
+ return htab_hash_string (e->name);
+}
+
+/* Equal function for hash. Simply a wrapper for strcmp. */
+
+static int
+type_name_eq (const PTR p1, const PTR p2)
+{
+ struct type_entry *e1 = (struct type_entry *) p1;
+ struct type_entry *e2 = (struct type_entry *) p2;
+
+ return strcmp (e1->name, e2->name) == 0;
+}
+
+/* Allocate a hash table for register/type pair. */
+
+htab_t
+nds32_alloc_type_tab (int size)
+{
+ return htab_create_alloc (size, type_hash_string, type_name_eq,
+ NULL /* htab_del */ ,
+ xcalloc, xfree);
+}
+
+/* Look up a register by name. */
+
+struct type *
+nds32_type_lookup (htab_t htab, const char *name)
+{
+ struct type_entry ent;
+ struct type_entry **pe;
+
+ ent.name = name;
+ pe = (struct type_entry **) htab_find_slot (htab, &ent, NO_INSERT);
+ if (pe)
+ return (*pe)->type;
+ else
+ return NULL;
+}
+
+/* Insert a type for a specific register name. */
+
+void
+nds32_type_insert (htab_t htab, const char *name, struct type *type)
+{
+ struct type_entry ent;
+ struct type_entry **pe;
+
+ ent.name = name;
+
+ pe = (struct type_entry **) htab_find_slot (htab, &ent, INSERT);
+
+ if (*pe != NULL)
+ return;
+
+ *pe = xmalloc (sizeof (**pe));
+ (*pe)->name = xstrdup (name);
+ (*pe)->type = type;
+}
+
+/* ui_file_put_method_ftype.
+
+ This is used with mem_file_put to get the content of
+ the internal stream buffer. */
+
+void
+do_ui_file_put_memcpy (void *object, const char *buffer, long length_buffer)
+{
+ struct ui_file_buffer *ui_buf;
+
+ ui_buf = (struct ui_file_buffer *) object;
+ if (ui_buf->buf_size < length_buffer)
+ {
+ if (length_buffer < 256 * 1024)
+ ui_buf->buf_size = length_buffer += 1024;
+ else
+ ui_buf->buf_size = length_buffer * 2;
+ ui_buf->buf = xrealloc (ui_buf->buf, ui_buf->buf_size);
+ }
+
+ memcpy (ui_buf->buf, buffer, length_buffer);
+}
+
+void
+ui_file_buffer_init (struct ui_file_buffer *ub, int size)
+{
+ ub->buf_size = size;
+ ub->buf = xmalloc (size);
+}
+
+void
+free_ui_file_buffer (void *ptr)
+{
+ struct ui_file_buffer *ui_buf = (struct ui_file_buffer *) ptr;
+
+ xfree (ui_buf->buf);
+}
diff --git a/gdb/nds32-utils.h b/gdb/nds32-utils.h
new file mode 100644
index 0000000..b1f9c2c
--- /dev/null
+++ b/gdb/nds32-utils.h
@@ -0,0 +1,59 @@
+/* Common target dependent code for GDB on nds32 systems.
+
+ Copyright (C) 2006-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/>. */
+
+#ifndef NDS32_UTILS_H
+#define NDS32_UTILS_H
+
+void source_nds32script (void);
+
+/* Declarations for making arch-dependent types. */
+enum type_option
+{
+ NO_FLAGS = 0,
+ USE_FLAGS = 1,
+};
+struct field *nds32_append_type_field (struct type *type);
+struct type *nds32_init_type (struct gdbarch *gdbarch, char *name,
+ enum type_option opt);
+void nds32_append_flag (struct type *type, int bitpos, char *name);
+void nds32_append_bitfield (struct type *type, struct type *field_type,
+ int bitpos_from, int bitpos_to, char *name);
+struct type *nds32_init_enum (struct gdbarch *gdbarch, char *name);
+void nds32_append_enum (struct type *type, int bitpos, char *name);
+
+/* Helpers for type table. */
+htab_t nds32_alloc_type_tab (int size);
+struct type *nds32_type_lookup (htab_t htab, const char *name);
+void nds32_type_insert (htab_t htab, const char *name, struct type *type);
+
+/* UI buffer for output redirection. */
+struct ui_file_buffer
+{
+ unsigned char *buf;
+ long buf_size;
+};
+
+void do_ui_file_put_memcpy (void *object, const char *buffer,
+ long length_buffer);
+
+void ui_file_buffer_init (struct ui_file_buffer *ub, int size);
+
+void free_ui_file_buffer (void *ptr);
+#endif
diff --git a/gdb/regformats/nds32-freg0-linux.dat
b/gdb/regformats/nds32-freg0-linux.dat
new file mode 100644
index 0000000..49eafd3
--- /dev/null
+++ b/gdb/regformats/nds32-freg0-linux.dat
@@ -0,0 +1,47 @@
+# DO NOT EDIT: generated from nds32-freg0-linux.xml
+name:nds32_freg0_linux
+xmltarget:nds32-freg0-linux.xml
+expedite:fp,sp,pc
+32:r0
+32:r1
+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:r24
+32:r25
+32:
+32:
+32:fp
+32:gp
+32:lp
+32:sp
+32:pc
+32:d0lo
+32:d0hi
+32:d1lo
+32:d1hi
+32:orig_r0
+32:fucpr
+64:fd0
+64:fd1
+64:fd2
+64:fd3
diff --git a/gdb/regformats/nds32-freg1-linux.dat
b/gdb/regformats/nds32-freg1-linux.dat
new file mode 100644
index 0000000..312912e
--- /dev/null
+++ b/gdb/regformats/nds32-freg1-linux.dat
@@ -0,0 +1,51 @@
+# DO NOT EDIT: generated from nds32-freg1-linux.xml
+name:nds32_freg1_linux
+xmltarget:nds32-freg1-linux.xml
+expedite:fp,sp,pc
+32:r0
+32:r1
+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:r24
+32:r25
+32:
+32:
+32:fp
+32:gp
+32:lp
+32:sp
+32:pc
+32:d0lo
+32:d0hi
+32:d1lo
+32:d1hi
+32:orig_r0
+32:fucpr
+64:fd0
+64:fd1
+64:fd2
+64:fd3
+64:fd4
+64:fd5
+64:fd6
+64:fd7
diff --git a/gdb/regformats/nds32-freg2-linux.dat
b/gdb/regformats/nds32-freg2-linux.dat
new file mode 100644
index 0000000..b281b50
--- /dev/null
+++ b/gdb/regformats/nds32-freg2-linux.dat
@@ -0,0 +1,59 @@
+# DO NOT EDIT: generated from nds32-freg2-linux.xml
+name:nds32_freg2_linux
+xmltarget:nds32-freg2-linux.xml
+expedite:fp,sp,pc
+32:r0
+32:r1
+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:r24
+32:r25
+32:
+32:
+32:fp
+32:gp
+32:lp
+32:sp
+32:pc
+32:d0lo
+32:d0hi
+32:d1lo
+32:d1hi
+32:orig_r0
+32:fucpr
+64:fd0
+64:fd1
+64:fd2
+64:fd3
+64:fd4
+64:fd5
+64:fd6
+64:fd7
+64:fd8
+64:fd9
+64:fd10
+64:fd11
+64:fd12
+64:fd13
+64:fd14
+64:fd15
diff --git a/gdb/regformats/nds32-freg3-linux.dat
b/gdb/regformats/nds32-freg3-linux.dat
new file mode 100644
index 0000000..f0c33f7
--- /dev/null
+++ b/gdb/regformats/nds32-freg3-linux.dat
@@ -0,0 +1,75 @@
+# DO NOT EDIT: generated from nds32-freg3-linux.xml
+name:nds32_freg3_linux
+xmltarget:nds32-freg3-linux.xml
+expedite:fp,sp,pc
+32:r0
+32:r1
+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:r24
+32:r25
+32:
+32:
+32:fp
+32:gp
+32:lp
+32:sp
+32:pc
+32:d0lo
+32:d0hi
+32:d1lo
+32:d1hi
+32:orig_r0
+32:fucpr
+64:fd0
+64:fd1
+64:fd2
+64:fd3
+64:fd4
+64:fd5
+64:fd6
+64:fd7
+64:fd8
+64:fd9
+64:fd10
+64:fd11
+64:fd12
+64:fd13
+64:fd14
+64:fd15
+64:fd16
+64:fd17
+64:fd18
+64:fd19
+64:fd20
+64:fd21
+64:fd22
+64:fd23
+64:fd24
+64:fd25
+64:fd26
+64:fd27
+64:fd28
+64:fd29
+64:fd30
+64:fd31
diff --git a/gdb/regformats/nds32-linux.dat b/gdb/regformats/nds32-linux.dat
new file mode 100644
index 0000000..bd79c4d
--- /dev/null
+++ b/gdb/regformats/nds32-linux.dat
@@ -0,0 +1,43 @@
+# DO NOT EDIT: generated from nds32-linux.xml
+name:nds32_linux
+xmltarget:nds32-linux.xml
+expedite:fp,sp,pc
+32:r0
+32:r1
+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:r24
+32:r25
+32:
+32:
+32:fp
+32:gp
+32:lp
+32:sp
+32:pc
+32:d0lo
+32:d0hi
+32:d1lo
+32:d1hi
+32:orig_r0
+32:fucpr
--
1.7.9.5