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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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, &regs);
+  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 *) &regs[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, &regs);
+  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 *) &regs[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, &regs);
+  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 *) &regs[nds32_ptreg_map[regno]]);
+
+  ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
+  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, &regs);
+  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 *) &regs[nds32_ptreg_map[regno]]);
+    }
+
+  ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
+
+  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


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