diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 8bd78a6b84a..4001bcbc07c 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -667,6 +667,7 @@ ALL_TARGET_OBS = \
 	arch/arm-linux.o \
 	arch/i386.o \
 	arch/ppc-linux-common.o \
+	arch/riscv.o \
 	arm-bsd-tdep.o \
 	arm-fbsd-tdep.o \
 	arm-linux-tdep.o \
@@ -1418,6 +1419,7 @@ HFILES_NO_SRCDIR = \
 	arch/i386.h \
 	arch/ppc-linux-common.h \
 	arch/ppc-linux-tdesc.h \
+	arch/riscv.h \
 	cli/cli-cmds.h \
 	cli/cli-decode.h \
 	cli/cli-script.h \
diff --git a/gdb/NEWS b/gdb/NEWS
index ef037dee4a2..9ecbb83d99c 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -38,6 +38,8 @@
   requires the use of a keyword.  Selecting a frame by level is
   unchanged.  The MI comment "-stack-select-frame" is unchanged.
 
+* The RISC-V target now supports target descriptions.
+
 * New targets
 
   NXP S12Z		s12z-*-elf
diff --git a/gdb/arch/riscv.c b/gdb/arch/riscv.c
new file mode 100644
index 00000000000..ca2238d5d70
--- /dev/null
+++ b/gdb/arch/riscv.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 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 "common-defs.h"
+#include "riscv.h"
+#include <stdlib.h>
+
+#include "../features/riscv/32bit-cpu.c"
+#include "../features/riscv/64bit-cpu.c"
+#include "../features/riscv/32bit-fpu.c"
+#include "../features/riscv/64bit-fpu.c"
+
+/* See arch/riscv.h.  */
+
+target_desc *
+riscv_create_target_description (struct riscv_gdbarch_features features)
+{
+  target_desc *tdesc = allocate_target_description ();
+
+#ifndef IN_PROCESS_AGENT
+  std::string arch_name = "riscv";
+
+  if (features.xlen == 4)
+    arch_name.append (":rv32i");
+  else if (features.xlen == 8)
+    arch_name.append (":rv64i");
+  else if (features.xlen == 16)
+    arch_name.append (":rv128i");
+
+  if (features.flen == 4)
+    arch_name.append ("f");
+  else if (features.flen == 8)
+    arch_name.append ("d");
+  else if (features.flen == 16)
+    arch_name.append ("q");
+
+  set_tdesc_architecture (tdesc, arch_name.c_str ());
+#endif
+
+  long regnum = 0;
+
+  /* For now we only support creating 32-bit or 64-bit x-registers.  */
+  if (features.xlen == 4)
+    regnum = create_feature_riscv_32bit_cpu (tdesc, regnum);
+  else if (features.xlen == 8)
+    regnum = create_feature_riscv_64bit_cpu (tdesc, regnum);
+
+  /* For now we only support creating 32-bit or 64-bit f-registers.  */
+  if (features.flen == 4)
+    regnum = create_feature_riscv_32bit_fpu (tdesc, regnum);
+  else if (features.flen == 8)
+    regnum = create_feature_riscv_64bit_fpu (tdesc, regnum);
+
+  return tdesc;
+}
diff --git a/gdb/arch/riscv.h b/gdb/arch/riscv.h
new file mode 100644
index 00000000000..007944019a9
--- /dev/null
+++ b/gdb/arch/riscv.h
@@ -0,0 +1,64 @@
+/* Common target-dependent functionality for RISC-V
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 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 ARCH_RISCV_H
+#define ARCH_RISCV_H
+
+#include "common/tdesc.h"
+
+/* The set of RISC-V architectural features that we track that impact how
+   we configure the actual gdbarch instance.  We hold one of these in the
+   gdbarch_tdep structure, and use it to distinguish between different
+   RISC-V gdbarch instances.
+
+   The information in here ideally comes from the target description,
+   however, if the target doesn't provide a target description then we will
+   create a default target description by first populating one of these
+   based on what we know about the binary being executed, and using that to
+   drive default target description creation.  */
+
+struct riscv_gdbarch_features
+{
+  /* The size of the x-registers in bytes.  This is either 4 (RV32), 8
+     (RV64), or 16 (RV128).  No other value is valid.  Initialise to the
+     invalid 0 value so we can spot if one of these is used
+     uninitialised.  */
+  int xlen = 0;
+
+  /* The size of the f-registers in bytes.  This is either 4 (RV32), 8
+     (RV64), or 16 (RV128).  This can also hold the value 0 to indicate
+     that there are no f-registers.  No other value is valid.  */
+  int flen = 0;
+
+  /* This indicates if hardware floating point abi is in use.  If the FLEN
+     field is 0 then this value _must_ be false.  If the FLEN field is
+     non-zero and this field is false then this indicates the target has
+     floating point registers, but is still using the soft-float abi.  If
+     this field is true then the hardware floating point abi is in use, and
+     values are passed in f-registers matching the size of FLEN.  */
+  bool hw_float_abi = false;
+};
+
+/* Create and return a target description that is compatible with
+   FEATURES.  */
+
+target_desc *riscv_create_target_description
+	(struct riscv_gdbarch_features features);
+
+#endif /* ARCH_RISCV_H */
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index e1f5e31f547..9b646fa1a21 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -81,6 +81,9 @@ ia64*-*-*)
 	cpu_obs="ia64-tdep.o"
 	;;
 
+riscv*-*-*)
+	cpu_obs="riscv-tdep.o arch/riscv.o";;
+
 x86_64-*-*)
 	cpu_obs="${i386_tobjs} ${amd64_tobjs}";;
 
@@ -532,18 +535,18 @@ s390*-*-linux*)
 
 riscv*-*-freebsd*)
 	# Target: FreeBSD/riscv
-	gdb_target_obs="riscv-fbsd-tdep.o riscv-tdep.o"
+	gdb_target_obs="riscv-fbsd-tdep.o"
 	;;
 
 riscv*-*-linux*)
 	# Target: Linux/RISC-V
-	gdb_target_obs="riscv-linux-tdep.o riscv-tdep.o glibc-tdep.o \
+	gdb_target_obs="riscv-linux-tdep.o glibc-tdep.o \
  			linux-tdep.o solib-svr4.o symfile-mem.o linux-record.o"
 	;;
 
 riscv*-*-*)
 	# Target: RISC-V architecture
-	gdb_target_obs="riscv-tdep.o"
+	gdb_target_obs=""
 	;;
 
 rl78-*-elf)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 3c3915b332c..def9c5c3469 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -42944,6 +42944,7 @@
 * Nios II Features::
 * OpenRISC 1000 Features::
 * PowerPC Features::
+* RISC-V Features::
 * S/390 and System z Features::
 * Sparc Features::
 * TIC6x Features::
@@ -43334,6 +43335,41 @@
 The @samp{org.gnu.gdb.power.htm.tar} feature is optional.  It should
 contain the 64-bit checkpointed register @samp{ctar}.
 
+
+@node RISC-V Features
+@subsection RISC-V Features
+@cindex target descriptions, RISC-V Features
+
+The @samp{org.gnu.gdb.riscv.cpu} feature is required for RISC-V
+targets.  It should contain the registers @samp{x0} through
+@samp{x31}, and @samp{pc}.  Either the architectural names (@samp{x0},
+@samp{x1}, etc) can be used, or the ABI names (@samp{zero}, @samp{ra},
+etc).
+
+The @samp{org.gnu.gdb.riscv.fpu} feature is optional.  If present it
+should contain registers @samp{f0} through @samp{f31}, @samp{fflags},
+@samp{frm}, and @samp{fcsr}.  As with the cpu feature either the
+architectural register names, or the ABI names can be used.
+
+The @samp{org.gnu.gdb.riscv.virtual} feature is optional.  If present
+it should contain registers that are not backed by real registers on
+the target but are instead virtual, where the register value is
+derived from other target state.  In many ways these are like GDBs
+pseudo-registers, except implemented by the target.  Currently the
+only register expected in this set is the one byte @samp{priv}
+register that contains the target's privilege level in the least
+significant two bits.
+
+The @samp{org.gnu.gdb.riscv.csr} feature is optional.  If present it
+should contain all of the target's standard CSRs.  Standard CSRs are
+those defined in the RISC-V specification documents.  There is some
+overlap between this feature and the fpu feature; the @samp{fflags},
+@samp{frm}, and @samp{fcsr} registers could be in either feature.  The
+expectation is that these registers will be in the fpu feature if the
+target has floating point hardware, but can be moved into the csr
+feature if the target has the floating point control registers, but no
+other floating point hardware.
+
 @node S/390 and System z Features
 @subsection S/390 and System z Features
 @cindex target descriptions, S/390 features
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index 150fef23f0b..ff2e57c65fd 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -207,6 +207,7 @@ GDB = false
 #Targets which use feature based target descriptions.
 aarch64-feature = 1
 i386-feature = 1
+riscv-feature = 1
 tic6x-feature = 1
 
 all: $(OUTPUTS)
@@ -242,6 +243,12 @@ FEATURE_XMLFILES = aarch64-core.xml \
 	i386/64bit-pkeys.xml \
 	i386/64bit-sse.xml \
 	i386/x32-core.xml \
+	riscv/32bit-cpu.xml \
+	riscv/32bit-csr.xml \
+	riscv/32bit-fpu.xml \
+	riscv/64bit-cpu.xml \
+	riscv/64bit-csr.xml \
+	riscv/64bit-fpu.xml \
 	tic6x-c6xp.xml \
 	tic6x-core.xml \
 	tic6x-gp.xml
@@ -339,6 +346,10 @@ $(outdir)/i386/x32-avx-avx512-linux.dat: i386/x32-core.xml i386/64bit-avx.xml \
 			       i386/64bit-avx512.xml i386/64bit-linux.xml \
 			       i386/64bit-segments.xml
 
+# Regenerate RISC-V CSR feature lists.
+riscv/32bit-csr.xml riscv/64bit-csr.xml: ../../include/opcode/riscv-opc.h
+	./riscv/rebuild-csr-xml.sh ../../include/opcode/riscv-opc.h ./riscv
+
 # 'all' doesn't build the C files, so don't delete them in 'clean'
 # either.
 clean-cfiles:
diff --git a/gdb/features/riscv/32bit-cpu.c b/gdb/features/riscv/32bit-cpu.c
new file mode 100644
index 00000000000..64686db5cdd
--- /dev/null
+++ b/gdb/features/riscv/32bit-cpu.c
@@ -0,0 +1,46 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: 32bit-cpu.xml */
+
+#include "common/tdesc.h"
+
+static int
+create_feature_riscv_32bit_cpu (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.riscv.cpu");
+  tdesc_create_reg (feature, "zero", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "ra", regnum++, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "tp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "t0", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "t1", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "t2", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "s1", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "a0", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "a1", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "a2", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "a3", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "a4", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "a5", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "a6", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "a7", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "s2", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "s3", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "s4", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "s5", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "s6", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "s7", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "s8", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "s9", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "s10", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "s11", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "t3", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "t4", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "t5", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "t6", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr");
+  return regnum;
+}
diff --git a/gdb/features/riscv/32bit-cpu.xml b/gdb/features/riscv/32bit-cpu.xml
new file mode 100644
index 00000000000..c02f86c0b03
--- /dev/null
+++ b/gdb/features/riscv/32bit-cpu.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018 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.riscv.cpu">
+  <reg name="zero" bitsize="32" type="int"/>
+  <reg name="ra" bitsize="32" type="code_ptr"/>
+  <reg name="sp" bitsize="32" type="data_ptr"/>
+  <reg name="gp" bitsize="32" type="data_ptr"/>
+  <reg name="tp" bitsize="32" type="data_ptr"/>
+  <reg name="t0" bitsize="32" type="int"/>
+  <reg name="t1" bitsize="32" type="int"/>
+  <reg name="t2" bitsize="32" type="int"/>
+  <reg name="fp" bitsize="32" type="data_ptr"/>
+  <reg name="s1" bitsize="32" type="int"/>
+  <reg name="a0" bitsize="32" type="int"/>
+  <reg name="a1" bitsize="32" type="int"/>
+  <reg name="a2" bitsize="32" type="int"/>
+  <reg name="a3" bitsize="32" type="int"/>
+  <reg name="a4" bitsize="32" type="int"/>
+  <reg name="a5" bitsize="32" type="int"/>
+  <reg name="a6" bitsize="32" type="int"/>
+  <reg name="a7" bitsize="32" type="int"/>
+  <reg name="s2" bitsize="32" type="int"/>
+  <reg name="s3" bitsize="32" type="int"/>
+  <reg name="s4" bitsize="32" type="int"/>
+  <reg name="s5" bitsize="32" type="int"/>
+  <reg name="s6" bitsize="32" type="int"/>
+  <reg name="s7" bitsize="32" type="int"/>
+  <reg name="s8" bitsize="32" type="int"/>
+  <reg name="s9" bitsize="32" type="int"/>
+  <reg name="s10" bitsize="32" type="int"/>
+  <reg name="s11" bitsize="32" type="int"/>
+  <reg name="t3" bitsize="32" type="int"/>
+  <reg name="t4" bitsize="32" type="int"/>
+  <reg name="t5" bitsize="32" type="int"/>
+  <reg name="t6" bitsize="32" type="int"/>
+  <reg name="pc" bitsize="32" type="code_ptr"/>
+</feature>
diff --git a/gdb/features/riscv/32bit-csr.c b/gdb/features/riscv/32bit-csr.c
new file mode 100644
index 00000000000..711e958ddae
--- /dev/null
+++ b/gdb/features/riscv/32bit-csr.c
@@ -0,0 +1,253 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: 32bit-csr.xml */
+
+#include "common/tdesc.h"
+
+static int
+create_feature_riscv_32bit_csr (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.riscv.csr");
+  tdesc_create_reg (feature, "ustatus", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "uie", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "utvec", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "uscratch", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "uepc", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "ucause", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "utval", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "uip", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "fflags", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "frm", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "fcsr", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "cycle", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "time", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "instret", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter3", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter4", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter5", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter6", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter7", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter8", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter9", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter10", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter11", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter12", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter13", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter14", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter15", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter16", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter17", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter18", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter19", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter20", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter21", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter22", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter23", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter24", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter25", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter26", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter27", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter28", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter29", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter30", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter31", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "cycleh", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "timeh", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "instreth", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter3h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter4h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter5h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter6h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter7h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter8h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter9h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter10h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter11h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter12h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter13h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter14h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter15h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter16h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter17h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter18h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter19h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter20h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter21h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter22h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter23h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter24h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter25h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter26h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter27h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter28h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter29h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter30h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hpmcounter31h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "sstatus", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "sedeleg", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "sideleg", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "sie", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "stvec", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "scounteren", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "sscratch", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "sepc", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "scause", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "stval", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "sip", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "satp", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mvendorid", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "marchid", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mimpid", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhartid", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mstatus", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "misa", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "medeleg", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mideleg", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mie", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mtvec", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mcounteren", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mscratch", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mepc", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mcause", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mtval", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mip", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpcfg0", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpcfg1", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpcfg2", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpcfg3", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr0", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr1", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr2", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr3", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr4", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr5", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr6", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr7", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr8", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr9", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr10", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr11", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr12", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr13", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr14", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pmpaddr15", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mcycle", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "minstret", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter3", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter4", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter5", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter6", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter7", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter8", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter9", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter10", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter11", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter12", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter13", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter14", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter15", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter16", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter17", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter18", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter19", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter20", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter21", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter22", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter23", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter24", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter25", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter26", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter27", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter28", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter29", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter30", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter31", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mcycleh", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "minstreth", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter3h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter4h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter5h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter6h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter7h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter8h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter9h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter10h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter11h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter12h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter13h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter14h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter15h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter16h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter17h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter18h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter19h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter20h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter21h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter22h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter23h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter24h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter25h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter26h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter27h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter28h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter29h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter30h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmcounter31h", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent3", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent4", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent5", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent6", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent7", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent8", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent9", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent10", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent11", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent12", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent13", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent14", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent15", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent16", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent17", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent18", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent19", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent20", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent21", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent22", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent23", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent24", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent25", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent26", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent27", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent28", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent29", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent30", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhpmevent31", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "tselect", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "tdata1", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "tdata2", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "tdata3", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "dcsr", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "dpc", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "dscratch", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hstatus", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hedeleg", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hideleg", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hie", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "htvec", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hscratch", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hepc", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hcause", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hbadaddr", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hip", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mbase", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mbound", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mibase", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mibound", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mdbase", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mdbound", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mucounteren", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mscounteren", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "mhcounteren", regnum++, 1, NULL, 32, "int");
+  return regnum;
+}
diff --git a/gdb/features/riscv/32bit-csr.xml b/gdb/features/riscv/32bit-csr.xml
new file mode 100644
index 00000000000..4aea9e657b9
--- /dev/null
+++ b/gdb/features/riscv/32bit-csr.xml
@@ -0,0 +1,250 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018 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.riscv.csr">
+  <reg name="ustatus" bitsize="32"/>
+  <reg name="uie" bitsize="32"/>
+  <reg name="utvec" bitsize="32"/>
+  <reg name="uscratch" bitsize="32"/>
+  <reg name="uepc" bitsize="32"/>
+  <reg name="ucause" bitsize="32"/>
+  <reg name="utval" bitsize="32"/>
+  <reg name="uip" bitsize="32"/>
+  <reg name="fflags" bitsize="32"/>
+  <reg name="frm" bitsize="32"/>
+  <reg name="fcsr" bitsize="32"/>
+  <reg name="cycle" bitsize="32"/>
+  <reg name="time" bitsize="32"/>
+  <reg name="instret" bitsize="32"/>
+  <reg name="hpmcounter3" bitsize="32"/>
+  <reg name="hpmcounter4" bitsize="32"/>
+  <reg name="hpmcounter5" bitsize="32"/>
+  <reg name="hpmcounter6" bitsize="32"/>
+  <reg name="hpmcounter7" bitsize="32"/>
+  <reg name="hpmcounter8" bitsize="32"/>
+  <reg name="hpmcounter9" bitsize="32"/>
+  <reg name="hpmcounter10" bitsize="32"/>
+  <reg name="hpmcounter11" bitsize="32"/>
+  <reg name="hpmcounter12" bitsize="32"/>
+  <reg name="hpmcounter13" bitsize="32"/>
+  <reg name="hpmcounter14" bitsize="32"/>
+  <reg name="hpmcounter15" bitsize="32"/>
+  <reg name="hpmcounter16" bitsize="32"/>
+  <reg name="hpmcounter17" bitsize="32"/>
+  <reg name="hpmcounter18" bitsize="32"/>
+  <reg name="hpmcounter19" bitsize="32"/>
+  <reg name="hpmcounter20" bitsize="32"/>
+  <reg name="hpmcounter21" bitsize="32"/>
+  <reg name="hpmcounter22" bitsize="32"/>
+  <reg name="hpmcounter23" bitsize="32"/>
+  <reg name="hpmcounter24" bitsize="32"/>
+  <reg name="hpmcounter25" bitsize="32"/>
+  <reg name="hpmcounter26" bitsize="32"/>
+  <reg name="hpmcounter27" bitsize="32"/>
+  <reg name="hpmcounter28" bitsize="32"/>
+  <reg name="hpmcounter29" bitsize="32"/>
+  <reg name="hpmcounter30" bitsize="32"/>
+  <reg name="hpmcounter31" bitsize="32"/>
+  <reg name="cycleh" bitsize="32"/>
+  <reg name="timeh" bitsize="32"/>
+  <reg name="instreth" bitsize="32"/>
+  <reg name="hpmcounter3h" bitsize="32"/>
+  <reg name="hpmcounter4h" bitsize="32"/>
+  <reg name="hpmcounter5h" bitsize="32"/>
+  <reg name="hpmcounter6h" bitsize="32"/>
+  <reg name="hpmcounter7h" bitsize="32"/>
+  <reg name="hpmcounter8h" bitsize="32"/>
+  <reg name="hpmcounter9h" bitsize="32"/>
+  <reg name="hpmcounter10h" bitsize="32"/>
+  <reg name="hpmcounter11h" bitsize="32"/>
+  <reg name="hpmcounter12h" bitsize="32"/>
+  <reg name="hpmcounter13h" bitsize="32"/>
+  <reg name="hpmcounter14h" bitsize="32"/>
+  <reg name="hpmcounter15h" bitsize="32"/>
+  <reg name="hpmcounter16h" bitsize="32"/>
+  <reg name="hpmcounter17h" bitsize="32"/>
+  <reg name="hpmcounter18h" bitsize="32"/>
+  <reg name="hpmcounter19h" bitsize="32"/>
+  <reg name="hpmcounter20h" bitsize="32"/>
+  <reg name="hpmcounter21h" bitsize="32"/>
+  <reg name="hpmcounter22h" bitsize="32"/>
+  <reg name="hpmcounter23h" bitsize="32"/>
+  <reg name="hpmcounter24h" bitsize="32"/>
+  <reg name="hpmcounter25h" bitsize="32"/>
+  <reg name="hpmcounter26h" bitsize="32"/>
+  <reg name="hpmcounter27h" bitsize="32"/>
+  <reg name="hpmcounter28h" bitsize="32"/>
+  <reg name="hpmcounter29h" bitsize="32"/>
+  <reg name="hpmcounter30h" bitsize="32"/>
+  <reg name="hpmcounter31h" bitsize="32"/>
+  <reg name="sstatus" bitsize="32"/>
+  <reg name="sedeleg" bitsize="32"/>
+  <reg name="sideleg" bitsize="32"/>
+  <reg name="sie" bitsize="32"/>
+  <reg name="stvec" bitsize="32"/>
+  <reg name="scounteren" bitsize="32"/>
+  <reg name="sscratch" bitsize="32"/>
+  <reg name="sepc" bitsize="32"/>
+  <reg name="scause" bitsize="32"/>
+  <reg name="stval" bitsize="32"/>
+  <reg name="sip" bitsize="32"/>
+  <reg name="satp" bitsize="32"/>
+  <reg name="mvendorid" bitsize="32"/>
+  <reg name="marchid" bitsize="32"/>
+  <reg name="mimpid" bitsize="32"/>
+  <reg name="mhartid" bitsize="32"/>
+  <reg name="mstatus" bitsize="32"/>
+  <reg name="misa" bitsize="32"/>
+  <reg name="medeleg" bitsize="32"/>
+  <reg name="mideleg" bitsize="32"/>
+  <reg name="mie" bitsize="32"/>
+  <reg name="mtvec" bitsize="32"/>
+  <reg name="mcounteren" bitsize="32"/>
+  <reg name="mscratch" bitsize="32"/>
+  <reg name="mepc" bitsize="32"/>
+  <reg name="mcause" bitsize="32"/>
+  <reg name="mtval" bitsize="32"/>
+  <reg name="mip" bitsize="32"/>
+  <reg name="pmpcfg0" bitsize="32"/>
+  <reg name="pmpcfg1" bitsize="32"/>
+  <reg name="pmpcfg2" bitsize="32"/>
+  <reg name="pmpcfg3" bitsize="32"/>
+  <reg name="pmpaddr0" bitsize="32"/>
+  <reg name="pmpaddr1" bitsize="32"/>
+  <reg name="pmpaddr2" bitsize="32"/>
+  <reg name="pmpaddr3" bitsize="32"/>
+  <reg name="pmpaddr4" bitsize="32"/>
+  <reg name="pmpaddr5" bitsize="32"/>
+  <reg name="pmpaddr6" bitsize="32"/>
+  <reg name="pmpaddr7" bitsize="32"/>
+  <reg name="pmpaddr8" bitsize="32"/>
+  <reg name="pmpaddr9" bitsize="32"/>
+  <reg name="pmpaddr10" bitsize="32"/>
+  <reg name="pmpaddr11" bitsize="32"/>
+  <reg name="pmpaddr12" bitsize="32"/>
+  <reg name="pmpaddr13" bitsize="32"/>
+  <reg name="pmpaddr14" bitsize="32"/>
+  <reg name="pmpaddr15" bitsize="32"/>
+  <reg name="mcycle" bitsize="32"/>
+  <reg name="minstret" bitsize="32"/>
+  <reg name="mhpmcounter3" bitsize="32"/>
+  <reg name="mhpmcounter4" bitsize="32"/>
+  <reg name="mhpmcounter5" bitsize="32"/>
+  <reg name="mhpmcounter6" bitsize="32"/>
+  <reg name="mhpmcounter7" bitsize="32"/>
+  <reg name="mhpmcounter8" bitsize="32"/>
+  <reg name="mhpmcounter9" bitsize="32"/>
+  <reg name="mhpmcounter10" bitsize="32"/>
+  <reg name="mhpmcounter11" bitsize="32"/>
+  <reg name="mhpmcounter12" bitsize="32"/>
+  <reg name="mhpmcounter13" bitsize="32"/>
+  <reg name="mhpmcounter14" bitsize="32"/>
+  <reg name="mhpmcounter15" bitsize="32"/>
+  <reg name="mhpmcounter16" bitsize="32"/>
+  <reg name="mhpmcounter17" bitsize="32"/>
+  <reg name="mhpmcounter18" bitsize="32"/>
+  <reg name="mhpmcounter19" bitsize="32"/>
+  <reg name="mhpmcounter20" bitsize="32"/>
+  <reg name="mhpmcounter21" bitsize="32"/>
+  <reg name="mhpmcounter22" bitsize="32"/>
+  <reg name="mhpmcounter23" bitsize="32"/>
+  <reg name="mhpmcounter24" bitsize="32"/>
+  <reg name="mhpmcounter25" bitsize="32"/>
+  <reg name="mhpmcounter26" bitsize="32"/>
+  <reg name="mhpmcounter27" bitsize="32"/>
+  <reg name="mhpmcounter28" bitsize="32"/>
+  <reg name="mhpmcounter29" bitsize="32"/>
+  <reg name="mhpmcounter30" bitsize="32"/>
+  <reg name="mhpmcounter31" bitsize="32"/>
+  <reg name="mcycleh" bitsize="32"/>
+  <reg name="minstreth" bitsize="32"/>
+  <reg name="mhpmcounter3h" bitsize="32"/>
+  <reg name="mhpmcounter4h" bitsize="32"/>
+  <reg name="mhpmcounter5h" bitsize="32"/>
+  <reg name="mhpmcounter6h" bitsize="32"/>
+  <reg name="mhpmcounter7h" bitsize="32"/>
+  <reg name="mhpmcounter8h" bitsize="32"/>
+  <reg name="mhpmcounter9h" bitsize="32"/>
+  <reg name="mhpmcounter10h" bitsize="32"/>
+  <reg name="mhpmcounter11h" bitsize="32"/>
+  <reg name="mhpmcounter12h" bitsize="32"/>
+  <reg name="mhpmcounter13h" bitsize="32"/>
+  <reg name="mhpmcounter14h" bitsize="32"/>
+  <reg name="mhpmcounter15h" bitsize="32"/>
+  <reg name="mhpmcounter16h" bitsize="32"/>
+  <reg name="mhpmcounter17h" bitsize="32"/>
+  <reg name="mhpmcounter18h" bitsize="32"/>
+  <reg name="mhpmcounter19h" bitsize="32"/>
+  <reg name="mhpmcounter20h" bitsize="32"/>
+  <reg name="mhpmcounter21h" bitsize="32"/>
+  <reg name="mhpmcounter22h" bitsize="32"/>
+  <reg name="mhpmcounter23h" bitsize="32"/>
+  <reg name="mhpmcounter24h" bitsize="32"/>
+  <reg name="mhpmcounter25h" bitsize="32"/>
+  <reg name="mhpmcounter26h" bitsize="32"/>
+  <reg name="mhpmcounter27h" bitsize="32"/>
+  <reg name="mhpmcounter28h" bitsize="32"/>
+  <reg name="mhpmcounter29h" bitsize="32"/>
+  <reg name="mhpmcounter30h" bitsize="32"/>
+  <reg name="mhpmcounter31h" bitsize="32"/>
+  <reg name="mhpmevent3" bitsize="32"/>
+  <reg name="mhpmevent4" bitsize="32"/>
+  <reg name="mhpmevent5" bitsize="32"/>
+  <reg name="mhpmevent6" bitsize="32"/>
+  <reg name="mhpmevent7" bitsize="32"/>
+  <reg name="mhpmevent8" bitsize="32"/>
+  <reg name="mhpmevent9" bitsize="32"/>
+  <reg name="mhpmevent10" bitsize="32"/>
+  <reg name="mhpmevent11" bitsize="32"/>
+  <reg name="mhpmevent12" bitsize="32"/>
+  <reg name="mhpmevent13" bitsize="32"/>
+  <reg name="mhpmevent14" bitsize="32"/>
+  <reg name="mhpmevent15" bitsize="32"/>
+  <reg name="mhpmevent16" bitsize="32"/>
+  <reg name="mhpmevent17" bitsize="32"/>
+  <reg name="mhpmevent18" bitsize="32"/>
+  <reg name="mhpmevent19" bitsize="32"/>
+  <reg name="mhpmevent20" bitsize="32"/>
+  <reg name="mhpmevent21" bitsize="32"/>
+  <reg name="mhpmevent22" bitsize="32"/>
+  <reg name="mhpmevent23" bitsize="32"/>
+  <reg name="mhpmevent24" bitsize="32"/>
+  <reg name="mhpmevent25" bitsize="32"/>
+  <reg name="mhpmevent26" bitsize="32"/>
+  <reg name="mhpmevent27" bitsize="32"/>
+  <reg name="mhpmevent28" bitsize="32"/>
+  <reg name="mhpmevent29" bitsize="32"/>
+  <reg name="mhpmevent30" bitsize="32"/>
+  <reg name="mhpmevent31" bitsize="32"/>
+  <reg name="tselect" bitsize="32"/>
+  <reg name="tdata1" bitsize="32"/>
+  <reg name="tdata2" bitsize="32"/>
+  <reg name="tdata3" bitsize="32"/>
+  <reg name="dcsr" bitsize="32"/>
+  <reg name="dpc" bitsize="32"/>
+  <reg name="dscratch" bitsize="32"/>
+  <reg name="hstatus" bitsize="32"/>
+  <reg name="hedeleg" bitsize="32"/>
+  <reg name="hideleg" bitsize="32"/>
+  <reg name="hie" bitsize="32"/>
+  <reg name="htvec" bitsize="32"/>
+  <reg name="hscratch" bitsize="32"/>
+  <reg name="hepc" bitsize="32"/>
+  <reg name="hcause" bitsize="32"/>
+  <reg name="hbadaddr" bitsize="32"/>
+  <reg name="hip" bitsize="32"/>
+  <reg name="mbase" bitsize="32"/>
+  <reg name="mbound" bitsize="32"/>
+  <reg name="mibase" bitsize="32"/>
+  <reg name="mibound" bitsize="32"/>
+  <reg name="mdbase" bitsize="32"/>
+  <reg name="mdbound" bitsize="32"/>
+  <reg name="mucounteren" bitsize="32"/>
+  <reg name="mscounteren" bitsize="32"/>
+  <reg name="mhcounteren" bitsize="32"/>
+</feature>
diff --git a/gdb/features/riscv/32bit-fpu.c b/gdb/features/riscv/32bit-fpu.c
new file mode 100644
index 00000000000..22e80d640e5
--- /dev/null
+++ b/gdb/features/riscv/32bit-fpu.c
@@ -0,0 +1,48 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: 32bit-fpu.xml */
+
+#include "common/tdesc.h"
+
+static int
+create_feature_riscv_32bit_fpu (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.riscv.fpu");
+  tdesc_create_reg (feature, "ft0", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "ft1", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "ft2", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "ft3", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "ft4", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "ft5", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "ft6", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "ft7", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fs0", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fs1", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fa0", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fa1", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fa2", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fa3", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fa4", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fa5", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fa6", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fa7", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fs2", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fs3", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fs4", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fs5", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fs6", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fs7", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fs8", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fs9", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fs10", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fs11", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "ft8", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "ft9", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "ft10", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "ft11", regnum++, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fflags", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "frm", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "fcsr", regnum++, 1, NULL, 32, "int");
+  return regnum;
+}
diff --git a/gdb/features/riscv/32bit-fpu.xml b/gdb/features/riscv/32bit-fpu.xml
new file mode 100644
index 00000000000..783287d9362
--- /dev/null
+++ b/gdb/features/riscv/32bit-fpu.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018 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.riscv.fpu">
+  <reg name="ft0" bitsize="32" type="ieee_single"/>
+  <reg name="ft1" bitsize="32" type="ieee_single"/>
+  <reg name="ft2" bitsize="32" type="ieee_single"/>
+  <reg name="ft3" bitsize="32" type="ieee_single"/>
+  <reg name="ft4" bitsize="32" type="ieee_single"/>
+  <reg name="ft5" bitsize="32" type="ieee_single"/>
+  <reg name="ft6" bitsize="32" type="ieee_single"/>
+  <reg name="ft7" bitsize="32" type="ieee_single"/>
+  <reg name="fs0" bitsize="32" type="ieee_single"/>
+  <reg name="fs1" bitsize="32" type="ieee_single"/>
+  <reg name="fa0" bitsize="32" type="ieee_single"/>
+  <reg name="fa1" bitsize="32" type="ieee_single"/>
+  <reg name="fa2" bitsize="32" type="ieee_single"/>
+  <reg name="fa3" bitsize="32" type="ieee_single"/>
+  <reg name="fa4" bitsize="32" type="ieee_single"/>
+  <reg name="fa5" bitsize="32" type="ieee_single"/>
+  <reg name="fa6" bitsize="32" type="ieee_single"/>
+  <reg name="fa7" bitsize="32" type="ieee_single"/>
+  <reg name="fs2" bitsize="32" type="ieee_single"/>
+  <reg name="fs3" bitsize="32" type="ieee_single"/>
+  <reg name="fs4" bitsize="32" type="ieee_single"/>
+  <reg name="fs5" bitsize="32" type="ieee_single"/>
+  <reg name="fs6" bitsize="32" type="ieee_single"/>
+  <reg name="fs7" bitsize="32" type="ieee_single"/>
+  <reg name="fs8" bitsize="32" type="ieee_single"/>
+  <reg name="fs9" bitsize="32" type="ieee_single"/>
+  <reg name="fs10" bitsize="32" type="ieee_single"/>
+  <reg name="fs11" bitsize="32" type="ieee_single"/>
+  <reg name="ft8" bitsize="32" type="ieee_single"/>
+  <reg name="ft9" bitsize="32" type="ieee_single"/>
+  <reg name="ft10" bitsize="32" type="ieee_single"/>
+  <reg name="ft11" bitsize="32" type="ieee_single"/>
+
+  <reg name="fflags" bitsize="32" type="int"/>
+  <reg name="frm" bitsize="32" type="int"/>
+  <reg name="fcsr" bitsize="32" type="int"/>
+</feature>
diff --git a/gdb/features/riscv/64bit-cpu.c b/gdb/features/riscv/64bit-cpu.c
new file mode 100644
index 00000000000..910089805ee
--- /dev/null
+++ b/gdb/features/riscv/64bit-cpu.c
@@ -0,0 +1,46 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: 64bit-cpu.xml */
+
+#include "common/tdesc.h"
+
+static int
+create_feature_riscv_64bit_cpu (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.riscv.cpu");
+  tdesc_create_reg (feature, "zero", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "ra", regnum++, 1, NULL, 64, "code_ptr");
+  tdesc_create_reg (feature, "sp", regnum++, 1, NULL, 64, "data_ptr");
+  tdesc_create_reg (feature, "gp", regnum++, 1, NULL, 64, "data_ptr");
+  tdesc_create_reg (feature, "tp", regnum++, 1, NULL, 64, "data_ptr");
+  tdesc_create_reg (feature, "t0", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "t1", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "t2", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "fp", regnum++, 1, NULL, 64, "data_ptr");
+  tdesc_create_reg (feature, "s1", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "a0", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "a1", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "a2", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "a3", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "a4", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "a5", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "a6", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "a7", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "s2", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "s3", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "s4", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "s5", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "s6", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "s7", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "s8", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "s9", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "s10", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "s11", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "t3", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "t4", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "t5", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "t6", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 64, "code_ptr");
+  return regnum;
+}
diff --git a/gdb/features/riscv/64bit-cpu.xml b/gdb/features/riscv/64bit-cpu.xml
new file mode 100644
index 00000000000..f37d7f3ce36
--- /dev/null
+++ b/gdb/features/riscv/64bit-cpu.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018 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.riscv.cpu">
+  <reg name="zero" bitsize="64" type="int"/>
+  <reg name="ra" bitsize="64" type="code_ptr"/>
+  <reg name="sp" bitsize="64" type="data_ptr"/>
+  <reg name="gp" bitsize="64" type="data_ptr"/>
+  <reg name="tp" bitsize="64" type="data_ptr"/>
+  <reg name="t0" bitsize="64" type="int"/>
+  <reg name="t1" bitsize="64" type="int"/>
+  <reg name="t2" bitsize="64" type="int"/>
+  <reg name="fp" bitsize="64" type="data_ptr"/>
+  <reg name="s1" bitsize="64" type="int"/>
+  <reg name="a0" bitsize="64" type="int"/>
+  <reg name="a1" bitsize="64" type="int"/>
+  <reg name="a2" bitsize="64" type="int"/>
+  <reg name="a3" bitsize="64" type="int"/>
+  <reg name="a4" bitsize="64" type="int"/>
+  <reg name="a5" bitsize="64" type="int"/>
+  <reg name="a6" bitsize="64" type="int"/>
+  <reg name="a7" bitsize="64" type="int"/>
+  <reg name="s2" bitsize="64" type="int"/>
+  <reg name="s3" bitsize="64" type="int"/>
+  <reg name="s4" bitsize="64" type="int"/>
+  <reg name="s5" bitsize="64" type="int"/>
+  <reg name="s6" bitsize="64" type="int"/>
+  <reg name="s7" bitsize="64" type="int"/>
+  <reg name="s8" bitsize="64" type="int"/>
+  <reg name="s9" bitsize="64" type="int"/>
+  <reg name="s10" bitsize="64" type="int"/>
+  <reg name="s11" bitsize="64" type="int"/>
+  <reg name="t3" bitsize="64" type="int"/>
+  <reg name="t4" bitsize="64" type="int"/>
+  <reg name="t5" bitsize="64" type="int"/>
+  <reg name="t6" bitsize="64" type="int"/>
+  <reg name="pc" bitsize="64" type="code_ptr"/>
+</feature>
diff --git a/gdb/features/riscv/64bit-csr.c b/gdb/features/riscv/64bit-csr.c
new file mode 100644
index 00000000000..7c777406254
--- /dev/null
+++ b/gdb/features/riscv/64bit-csr.c
@@ -0,0 +1,253 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: 64bit-csr.xml */
+
+#include "common/tdesc.h"
+
+static int
+create_feature_riscv_64bit_csr (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.riscv.csr");
+  tdesc_create_reg (feature, "ustatus", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "uie", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "utvec", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "uscratch", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "uepc", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "ucause", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "utval", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "uip", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "fflags", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "frm", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "fcsr", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "cycle", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "time", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "instret", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter3", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter4", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter5", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter6", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter7", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter8", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter9", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter10", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter11", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter12", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter13", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter14", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter15", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter16", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter17", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter18", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter19", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter20", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter21", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter22", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter23", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter24", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter25", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter26", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter27", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter28", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter29", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter30", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter31", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "cycleh", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "timeh", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "instreth", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter3h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter4h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter5h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter6h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter7h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter8h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter9h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter10h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter11h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter12h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter13h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter14h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter15h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter16h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter17h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter18h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter19h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter20h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter21h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter22h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter23h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter24h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter25h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter26h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter27h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter28h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter29h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter30h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hpmcounter31h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "sstatus", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "sedeleg", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "sideleg", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "sie", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "stvec", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "scounteren", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "sscratch", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "sepc", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "scause", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "stval", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "sip", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "satp", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mvendorid", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "marchid", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mimpid", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhartid", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mstatus", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "misa", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "medeleg", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mideleg", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mie", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mtvec", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mcounteren", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mscratch", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mepc", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mcause", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mtval", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mip", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpcfg0", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpcfg1", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpcfg2", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpcfg3", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr0", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr1", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr2", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr3", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr4", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr5", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr6", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr7", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr8", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr9", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr10", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr11", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr12", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr13", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr14", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pmpaddr15", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mcycle", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "minstret", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter3", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter4", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter5", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter6", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter7", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter8", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter9", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter10", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter11", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter12", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter13", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter14", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter15", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter16", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter17", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter18", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter19", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter20", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter21", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter22", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter23", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter24", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter25", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter26", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter27", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter28", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter29", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter30", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter31", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mcycleh", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "minstreth", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter3h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter4h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter5h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter6h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter7h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter8h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter9h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter10h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter11h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter12h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter13h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter14h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter15h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter16h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter17h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter18h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter19h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter20h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter21h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter22h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter23h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter24h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter25h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter26h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter27h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter28h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter29h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter30h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmcounter31h", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent3", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent4", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent5", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent6", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent7", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent8", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent9", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent10", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent11", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent12", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent13", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent14", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent15", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent16", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent17", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent18", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent19", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent20", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent21", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent22", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent23", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent24", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent25", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent26", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent27", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent28", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent29", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent30", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhpmevent31", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "tselect", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "tdata1", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "tdata2", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "tdata3", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "dcsr", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "dpc", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "dscratch", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hstatus", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hedeleg", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hideleg", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hie", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "htvec", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hscratch", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hepc", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hcause", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hbadaddr", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hip", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mbase", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mbound", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mibase", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mibound", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mdbase", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mdbound", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mucounteren", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mscounteren", regnum++, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "mhcounteren", regnum++, 1, NULL, 64, "int");
+  return regnum;
+}
diff --git a/gdb/features/riscv/64bit-csr.xml b/gdb/features/riscv/64bit-csr.xml
new file mode 100644
index 00000000000..a3de83443a5
--- /dev/null
+++ b/gdb/features/riscv/64bit-csr.xml
@@ -0,0 +1,250 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018 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.riscv.csr">
+  <reg name="ustatus" bitsize="64"/>
+  <reg name="uie" bitsize="64"/>
+  <reg name="utvec" bitsize="64"/>
+  <reg name="uscratch" bitsize="64"/>
+  <reg name="uepc" bitsize="64"/>
+  <reg name="ucause" bitsize="64"/>
+  <reg name="utval" bitsize="64"/>
+  <reg name="uip" bitsize="64"/>
+  <reg name="fflags" bitsize="64"/>
+  <reg name="frm" bitsize="64"/>
+  <reg name="fcsr" bitsize="64"/>
+  <reg name="cycle" bitsize="64"/>
+  <reg name="time" bitsize="64"/>
+  <reg name="instret" bitsize="64"/>
+  <reg name="hpmcounter3" bitsize="64"/>
+  <reg name="hpmcounter4" bitsize="64"/>
+  <reg name="hpmcounter5" bitsize="64"/>
+  <reg name="hpmcounter6" bitsize="64"/>
+  <reg name="hpmcounter7" bitsize="64"/>
+  <reg name="hpmcounter8" bitsize="64"/>
+  <reg name="hpmcounter9" bitsize="64"/>
+  <reg name="hpmcounter10" bitsize="64"/>
+  <reg name="hpmcounter11" bitsize="64"/>
+  <reg name="hpmcounter12" bitsize="64"/>
+  <reg name="hpmcounter13" bitsize="64"/>
+  <reg name="hpmcounter14" bitsize="64"/>
+  <reg name="hpmcounter15" bitsize="64"/>
+  <reg name="hpmcounter16" bitsize="64"/>
+  <reg name="hpmcounter17" bitsize="64"/>
+  <reg name="hpmcounter18" bitsize="64"/>
+  <reg name="hpmcounter19" bitsize="64"/>
+  <reg name="hpmcounter20" bitsize="64"/>
+  <reg name="hpmcounter21" bitsize="64"/>
+  <reg name="hpmcounter22" bitsize="64"/>
+  <reg name="hpmcounter23" bitsize="64"/>
+  <reg name="hpmcounter24" bitsize="64"/>
+  <reg name="hpmcounter25" bitsize="64"/>
+  <reg name="hpmcounter26" bitsize="64"/>
+  <reg name="hpmcounter27" bitsize="64"/>
+  <reg name="hpmcounter28" bitsize="64"/>
+  <reg name="hpmcounter29" bitsize="64"/>
+  <reg name="hpmcounter30" bitsize="64"/>
+  <reg name="hpmcounter31" bitsize="64"/>
+  <reg name="cycleh" bitsize="64"/>
+  <reg name="timeh" bitsize="64"/>
+  <reg name="instreth" bitsize="64"/>
+  <reg name="hpmcounter3h" bitsize="64"/>
+  <reg name="hpmcounter4h" bitsize="64"/>
+  <reg name="hpmcounter5h" bitsize="64"/>
+  <reg name="hpmcounter6h" bitsize="64"/>
+  <reg name="hpmcounter7h" bitsize="64"/>
+  <reg name="hpmcounter8h" bitsize="64"/>
+  <reg name="hpmcounter9h" bitsize="64"/>
+  <reg name="hpmcounter10h" bitsize="64"/>
+  <reg name="hpmcounter11h" bitsize="64"/>
+  <reg name="hpmcounter12h" bitsize="64"/>
+  <reg name="hpmcounter13h" bitsize="64"/>
+  <reg name="hpmcounter14h" bitsize="64"/>
+  <reg name="hpmcounter15h" bitsize="64"/>
+  <reg name="hpmcounter16h" bitsize="64"/>
+  <reg name="hpmcounter17h" bitsize="64"/>
+  <reg name="hpmcounter18h" bitsize="64"/>
+  <reg name="hpmcounter19h" bitsize="64"/>
+  <reg name="hpmcounter20h" bitsize="64"/>
+  <reg name="hpmcounter21h" bitsize="64"/>
+  <reg name="hpmcounter22h" bitsize="64"/>
+  <reg name="hpmcounter23h" bitsize="64"/>
+  <reg name="hpmcounter24h" bitsize="64"/>
+  <reg name="hpmcounter25h" bitsize="64"/>
+  <reg name="hpmcounter26h" bitsize="64"/>
+  <reg name="hpmcounter27h" bitsize="64"/>
+  <reg name="hpmcounter28h" bitsize="64"/>
+  <reg name="hpmcounter29h" bitsize="64"/>
+  <reg name="hpmcounter30h" bitsize="64"/>
+  <reg name="hpmcounter31h" bitsize="64"/>
+  <reg name="sstatus" bitsize="64"/>
+  <reg name="sedeleg" bitsize="64"/>
+  <reg name="sideleg" bitsize="64"/>
+  <reg name="sie" bitsize="64"/>
+  <reg name="stvec" bitsize="64"/>
+  <reg name="scounteren" bitsize="64"/>
+  <reg name="sscratch" bitsize="64"/>
+  <reg name="sepc" bitsize="64"/>
+  <reg name="scause" bitsize="64"/>
+  <reg name="stval" bitsize="64"/>
+  <reg name="sip" bitsize="64"/>
+  <reg name="satp" bitsize="64"/>
+  <reg name="mvendorid" bitsize="64"/>
+  <reg name="marchid" bitsize="64"/>
+  <reg name="mimpid" bitsize="64"/>
+  <reg name="mhartid" bitsize="64"/>
+  <reg name="mstatus" bitsize="64"/>
+  <reg name="misa" bitsize="64"/>
+  <reg name="medeleg" bitsize="64"/>
+  <reg name="mideleg" bitsize="64"/>
+  <reg name="mie" bitsize="64"/>
+  <reg name="mtvec" bitsize="64"/>
+  <reg name="mcounteren" bitsize="64"/>
+  <reg name="mscratch" bitsize="64"/>
+  <reg name="mepc" bitsize="64"/>
+  <reg name="mcause" bitsize="64"/>
+  <reg name="mtval" bitsize="64"/>
+  <reg name="mip" bitsize="64"/>
+  <reg name="pmpcfg0" bitsize="64"/>
+  <reg name="pmpcfg1" bitsize="64"/>
+  <reg name="pmpcfg2" bitsize="64"/>
+  <reg name="pmpcfg3" bitsize="64"/>
+  <reg name="pmpaddr0" bitsize="64"/>
+  <reg name="pmpaddr1" bitsize="64"/>
+  <reg name="pmpaddr2" bitsize="64"/>
+  <reg name="pmpaddr3" bitsize="64"/>
+  <reg name="pmpaddr4" bitsize="64"/>
+  <reg name="pmpaddr5" bitsize="64"/>
+  <reg name="pmpaddr6" bitsize="64"/>
+  <reg name="pmpaddr7" bitsize="64"/>
+  <reg name="pmpaddr8" bitsize="64"/>
+  <reg name="pmpaddr9" bitsize="64"/>
+  <reg name="pmpaddr10" bitsize="64"/>
+  <reg name="pmpaddr11" bitsize="64"/>
+  <reg name="pmpaddr12" bitsize="64"/>
+  <reg name="pmpaddr13" bitsize="64"/>
+  <reg name="pmpaddr14" bitsize="64"/>
+  <reg name="pmpaddr15" bitsize="64"/>
+  <reg name="mcycle" bitsize="64"/>
+  <reg name="minstret" bitsize="64"/>
+  <reg name="mhpmcounter3" bitsize="64"/>
+  <reg name="mhpmcounter4" bitsize="64"/>
+  <reg name="mhpmcounter5" bitsize="64"/>
+  <reg name="mhpmcounter6" bitsize="64"/>
+  <reg name="mhpmcounter7" bitsize="64"/>
+  <reg name="mhpmcounter8" bitsize="64"/>
+  <reg name="mhpmcounter9" bitsize="64"/>
+  <reg name="mhpmcounter10" bitsize="64"/>
+  <reg name="mhpmcounter11" bitsize="64"/>
+  <reg name="mhpmcounter12" bitsize="64"/>
+  <reg name="mhpmcounter13" bitsize="64"/>
+  <reg name="mhpmcounter14" bitsize="64"/>
+  <reg name="mhpmcounter15" bitsize="64"/>
+  <reg name="mhpmcounter16" bitsize="64"/>
+  <reg name="mhpmcounter17" bitsize="64"/>
+  <reg name="mhpmcounter18" bitsize="64"/>
+  <reg name="mhpmcounter19" bitsize="64"/>
+  <reg name="mhpmcounter20" bitsize="64"/>
+  <reg name="mhpmcounter21" bitsize="64"/>
+  <reg name="mhpmcounter22" bitsize="64"/>
+  <reg name="mhpmcounter23" bitsize="64"/>
+  <reg name="mhpmcounter24" bitsize="64"/>
+  <reg name="mhpmcounter25" bitsize="64"/>
+  <reg name="mhpmcounter26" bitsize="64"/>
+  <reg name="mhpmcounter27" bitsize="64"/>
+  <reg name="mhpmcounter28" bitsize="64"/>
+  <reg name="mhpmcounter29" bitsize="64"/>
+  <reg name="mhpmcounter30" bitsize="64"/>
+  <reg name="mhpmcounter31" bitsize="64"/>
+  <reg name="mcycleh" bitsize="64"/>
+  <reg name="minstreth" bitsize="64"/>
+  <reg name="mhpmcounter3h" bitsize="64"/>
+  <reg name="mhpmcounter4h" bitsize="64"/>
+  <reg name="mhpmcounter5h" bitsize="64"/>
+  <reg name="mhpmcounter6h" bitsize="64"/>
+  <reg name="mhpmcounter7h" bitsize="64"/>
+  <reg name="mhpmcounter8h" bitsize="64"/>
+  <reg name="mhpmcounter9h" bitsize="64"/>
+  <reg name="mhpmcounter10h" bitsize="64"/>
+  <reg name="mhpmcounter11h" bitsize="64"/>
+  <reg name="mhpmcounter12h" bitsize="64"/>
+  <reg name="mhpmcounter13h" bitsize="64"/>
+  <reg name="mhpmcounter14h" bitsize="64"/>
+  <reg name="mhpmcounter15h" bitsize="64"/>
+  <reg name="mhpmcounter16h" bitsize="64"/>
+  <reg name="mhpmcounter17h" bitsize="64"/>
+  <reg name="mhpmcounter18h" bitsize="64"/>
+  <reg name="mhpmcounter19h" bitsize="64"/>
+  <reg name="mhpmcounter20h" bitsize="64"/>
+  <reg name="mhpmcounter21h" bitsize="64"/>
+  <reg name="mhpmcounter22h" bitsize="64"/>
+  <reg name="mhpmcounter23h" bitsize="64"/>
+  <reg name="mhpmcounter24h" bitsize="64"/>
+  <reg name="mhpmcounter25h" bitsize="64"/>
+  <reg name="mhpmcounter26h" bitsize="64"/>
+  <reg name="mhpmcounter27h" bitsize="64"/>
+  <reg name="mhpmcounter28h" bitsize="64"/>
+  <reg name="mhpmcounter29h" bitsize="64"/>
+  <reg name="mhpmcounter30h" bitsize="64"/>
+  <reg name="mhpmcounter31h" bitsize="64"/>
+  <reg name="mhpmevent3" bitsize="64"/>
+  <reg name="mhpmevent4" bitsize="64"/>
+  <reg name="mhpmevent5" bitsize="64"/>
+  <reg name="mhpmevent6" bitsize="64"/>
+  <reg name="mhpmevent7" bitsize="64"/>
+  <reg name="mhpmevent8" bitsize="64"/>
+  <reg name="mhpmevent9" bitsize="64"/>
+  <reg name="mhpmevent10" bitsize="64"/>
+  <reg name="mhpmevent11" bitsize="64"/>
+  <reg name="mhpmevent12" bitsize="64"/>
+  <reg name="mhpmevent13" bitsize="64"/>
+  <reg name="mhpmevent14" bitsize="64"/>
+  <reg name="mhpmevent15" bitsize="64"/>
+  <reg name="mhpmevent16" bitsize="64"/>
+  <reg name="mhpmevent17" bitsize="64"/>
+  <reg name="mhpmevent18" bitsize="64"/>
+  <reg name="mhpmevent19" bitsize="64"/>
+  <reg name="mhpmevent20" bitsize="64"/>
+  <reg name="mhpmevent21" bitsize="64"/>
+  <reg name="mhpmevent22" bitsize="64"/>
+  <reg name="mhpmevent23" bitsize="64"/>
+  <reg name="mhpmevent24" bitsize="64"/>
+  <reg name="mhpmevent25" bitsize="64"/>
+  <reg name="mhpmevent26" bitsize="64"/>
+  <reg name="mhpmevent27" bitsize="64"/>
+  <reg name="mhpmevent28" bitsize="64"/>
+  <reg name="mhpmevent29" bitsize="64"/>
+  <reg name="mhpmevent30" bitsize="64"/>
+  <reg name="mhpmevent31" bitsize="64"/>
+  <reg name="tselect" bitsize="64"/>
+  <reg name="tdata1" bitsize="64"/>
+  <reg name="tdata2" bitsize="64"/>
+  <reg name="tdata3" bitsize="64"/>
+  <reg name="dcsr" bitsize="64"/>
+  <reg name="dpc" bitsize="64"/>
+  <reg name="dscratch" bitsize="64"/>
+  <reg name="hstatus" bitsize="64"/>
+  <reg name="hedeleg" bitsize="64"/>
+  <reg name="hideleg" bitsize="64"/>
+  <reg name="hie" bitsize="64"/>
+  <reg name="htvec" bitsize="64"/>
+  <reg name="hscratch" bitsize="64"/>
+  <reg name="hepc" bitsize="64"/>
+  <reg name="hcause" bitsize="64"/>
+  <reg name="hbadaddr" bitsize="64"/>
+  <reg name="hip" bitsize="64"/>
+  <reg name="mbase" bitsize="64"/>
+  <reg name="mbound" bitsize="64"/>
+  <reg name="mibase" bitsize="64"/>
+  <reg name="mibound" bitsize="64"/>
+  <reg name="mdbase" bitsize="64"/>
+  <reg name="mdbound" bitsize="64"/>
+  <reg name="mucounteren" bitsize="64"/>
+  <reg name="mscounteren" bitsize="64"/>
+  <reg name="mhcounteren" bitsize="64"/>
+</feature>
diff --git a/gdb/features/riscv/64bit-fpu.c b/gdb/features/riscv/64bit-fpu.c
new file mode 100644
index 00000000000..8cbd7484ab3
--- /dev/null
+++ b/gdb/features/riscv/64bit-fpu.c
@@ -0,0 +1,56 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: 64bit-fpu.xml */
+
+#include "common/tdesc.h"
+
+static int
+create_feature_riscv_64bit_fpu (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.riscv.fpu");
+  tdesc_type_with_fields *type_with_fields;
+  type_with_fields = tdesc_create_union (feature, "riscv_double");
+  tdesc_type *field_type;
+  field_type = tdesc_named_type (feature, "ieee_single");
+  tdesc_add_field (type_with_fields, "float", field_type);
+  field_type = tdesc_named_type (feature, "ieee_double");
+  tdesc_add_field (type_with_fields, "double", field_type);
+
+  tdesc_create_reg (feature, "ft0", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "ft1", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "ft2", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "ft3", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "ft4", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "ft5", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "ft6", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "ft7", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fs0", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fs1", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fa0", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fa1", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fa2", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fa3", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fa4", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fa5", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fa6", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fa7", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fs2", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fs3", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fs4", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fs5", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fs6", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fs7", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fs8", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fs9", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fs10", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fs11", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "ft8", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "ft9", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "ft10", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "ft11", regnum++, 1, NULL, 64, "riscv_double");
+  tdesc_create_reg (feature, "fflags", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "frm", regnum++, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "fcsr", regnum++, 1, NULL, 32, "int");
+  return regnum;
+}
diff --git a/gdb/features/riscv/64bit-fpu.xml b/gdb/features/riscv/64bit-fpu.xml
new file mode 100644
index 00000000000..fb24b72bcaf
--- /dev/null
+++ b/gdb/features/riscv/64bit-fpu.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018 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.riscv.fpu">
+
+  <union id="riscv_double">
+    <field name="float" type="ieee_single"/>
+    <field name="double" type="ieee_double"/>
+  </union>
+
+  <reg name="ft0" bitsize="64" type="riscv_double"/>
+  <reg name="ft1" bitsize="64" type="riscv_double"/>
+  <reg name="ft2" bitsize="64" type="riscv_double"/>
+  <reg name="ft3" bitsize="64" type="riscv_double"/>
+  <reg name="ft4" bitsize="64" type="riscv_double"/>
+  <reg name="ft5" bitsize="64" type="riscv_double"/>
+  <reg name="ft6" bitsize="64" type="riscv_double"/>
+  <reg name="ft7" bitsize="64" type="riscv_double"/>
+  <reg name="fs0" bitsize="64" type="riscv_double"/>
+  <reg name="fs1" bitsize="64" type="riscv_double"/>
+  <reg name="fa0" bitsize="64" type="riscv_double"/>
+  <reg name="fa1" bitsize="64" type="riscv_double"/>
+  <reg name="fa2" bitsize="64" type="riscv_double"/>
+  <reg name="fa3" bitsize="64" type="riscv_double"/>
+  <reg name="fa4" bitsize="64" type="riscv_double"/>
+  <reg name="fa5" bitsize="64" type="riscv_double"/>
+  <reg name="fa6" bitsize="64" type="riscv_double"/>
+  <reg name="fa7" bitsize="64" type="riscv_double"/>
+  <reg name="fs2" bitsize="64" type="riscv_double"/>
+  <reg name="fs3" bitsize="64" type="riscv_double"/>
+  <reg name="fs4" bitsize="64" type="riscv_double"/>
+  <reg name="fs5" bitsize="64" type="riscv_double"/>
+  <reg name="fs6" bitsize="64" type="riscv_double"/>
+  <reg name="fs7" bitsize="64" type="riscv_double"/>
+  <reg name="fs8" bitsize="64" type="riscv_double"/>
+  <reg name="fs9" bitsize="64" type="riscv_double"/>
+  <reg name="fs10" bitsize="64" type="riscv_double"/>
+  <reg name="fs11" bitsize="64" type="riscv_double"/>
+  <reg name="ft8" bitsize="64" type="riscv_double"/>
+  <reg name="ft9" bitsize="64" type="riscv_double"/>
+  <reg name="ft10" bitsize="64" type="riscv_double"/>
+  <reg name="ft11" bitsize="64" type="riscv_double"/>
+
+  <reg name="fflags" bitsize="32" type="int"/>
+  <reg name="frm" bitsize="32" type="int"/>
+  <reg name="fcsr" bitsize="32" type="int"/>
+</feature>
diff --git a/gdb/features/riscv/rebuild-csr-xml.sh b/gdb/features/riscv/rebuild-csr-xml.sh
new file mode 100755
index 00000000000..6971b8dbb2a
--- /dev/null
+++ b/gdb/features/riscv/rebuild-csr-xml.sh
@@ -0,0 +1,29 @@
+#! /bin/bash
+
+RISCV_OPC_FILE=$1
+RISCV_FEATURE_DIR=$2
+
+function gen_csr_xml ()
+{
+    bitsize=$1
+
+    cat <<EOF
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018 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.riscv.csr">
+EOF
+
+    grep "^DECLARE_CSR(" ${RISCV_OPC_FILE} \
+        | sed -e "s!DECLARE_CSR(\(.*\), .*!  <reg name=\"\1\" bitsize=\"$bitsize\"/>!"
+
+    echo "</feature>"
+}
+
+gen_csr_xml 32 > ${RISCV_FEATURE_DIR}/32bit-csr.xml
+gen_csr_xml 64 > ${RISCV_FEATURE_DIR}/64bit-csr.xml
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 408ab0af24b..5965a594440 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -55,6 +55,7 @@
 #include "cli/cli-decode.h"
 #include "observable.h"
 #include "prologue-value.h"
+#include "arch/riscv.h"
 
 /* The stack must be 16-byte aligned.  */
 #define SP_ALIGNMENT 16
@@ -62,9 +63,6 @@
 /* The biggest alignment that the target supports.  */
 #define BIGGEST_ALIGNMENT 16
 
-/* Forward declarations.  */
-static bool riscv_has_feature (struct gdbarch *gdbarch, char feature);
-
 /* Define a series of is_XXX_insn functions to check if the value INSN
    is an instance of instruction XXX.  */
 #define DECLARE_INSN(INSN_NAME, INSN_MATCH, INSN_MASK) \
@@ -98,110 +96,170 @@ struct riscv_unwind_cache
   CORE_ADDR frame_base;
 };
 
-/* The preferred register names for all the general purpose and floating
-   point registers.  These are what GDB will use when referencing a
-   register.  */
+/* RISC-V specific register group for CSRs.  */
 
-static const char * const riscv_gdb_reg_names[RISCV_LAST_FP_REGNUM + 1] =
-{
- "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "s1",
- "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4",
- "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6",
- "pc",
- "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", "fs0", "fs1",
- "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7", "fs2", "fs3",
- "fs4", "fs5", "fs6", "fs7", "fs8", "fs9", "fs10", "fs11", "ft8", "ft9",
- "ft10", "ft11",
-};
+static reggroup *csr_reggroup = NULL;
 
-/* Map alternative register names onto their GDB register number.  */
+/* A set of registers that we expect to find in a tdesc_feature.  These
+   are use in RISCV_GDBARCH_INIT when processing the target description.  */
 
-struct riscv_register_alias
+struct riscv_register_feature
 {
-  /* The register alias.  Usually more descriptive than the
-     architectural name of the register.  */
+  /* Information for a single register.  */
+  struct register_info
+  {
+    /* The GDB register number for this register.  */
+    int regnum;
+
+    /* List of names for this register.  The first name in this list is the
+       preferred name, the name GDB should use when describing this
+       register.  */
+    std::vector <const char *> names;
+
+    /* When true this register is required in this feature set.  */
+    bool required_p;
+  };
+
+  /* The name for this feature.  This is the name used to find this feature
+     within the target description.  */
   const char *name;
 
-  /* The GDB register number.  */
-  int regnum;
+  /* List of all the registers that we expect that we might find in this
+     register set.  */
+  std::vector <struct register_info> registers;
+};
+
+/* The general x-registers feature set.  */
+
+static const struct riscv_register_feature riscv_xreg_feature =
+{
+ "org.gnu.gdb.riscv.cpu",
+ {
+   { RISCV_ZERO_REGNUM + 0, { "zero", "x0" }, true },
+   { RISCV_ZERO_REGNUM + 1, { "ra", "x1" }, true },
+   { RISCV_ZERO_REGNUM + 2, { "sp", "x2" }, true },
+   { RISCV_ZERO_REGNUM + 3, { "gp", "x3" }, true },
+   { RISCV_ZERO_REGNUM + 4, { "tp", "x4" }, true },
+   { RISCV_ZERO_REGNUM + 5, { "t0", "x5" }, true },
+   { RISCV_ZERO_REGNUM + 6, { "t1", "x6" }, true },
+   { RISCV_ZERO_REGNUM + 7, { "t2", "x7" }, true },
+   { RISCV_ZERO_REGNUM + 8, { "fp", "x8", "s0" }, true },
+   { RISCV_ZERO_REGNUM + 9, { "s1", "x9" }, true },
+   { RISCV_ZERO_REGNUM + 10, { "a0", "x10" }, true },
+   { RISCV_ZERO_REGNUM + 11, { "a1", "x11" }, true },
+   { RISCV_ZERO_REGNUM + 12, { "a2", "x12" }, true },
+   { RISCV_ZERO_REGNUM + 13, { "a3", "x13" }, true },
+   { RISCV_ZERO_REGNUM + 14, { "a4", "x14" }, true },
+   { RISCV_ZERO_REGNUM + 15, { "a5", "x15" }, true },
+   { RISCV_ZERO_REGNUM + 16, { "a6", "x16" }, true },
+   { RISCV_ZERO_REGNUM + 17, { "a7", "x17" }, true },
+   { RISCV_ZERO_REGNUM + 18, { "s2", "x18" }, true },
+   { RISCV_ZERO_REGNUM + 19, { "s3", "x19" }, true },
+   { RISCV_ZERO_REGNUM + 20, { "s4", "x20" }, true },
+   { RISCV_ZERO_REGNUM + 21, { "s5", "x21" }, true },
+   { RISCV_ZERO_REGNUM + 22, { "s6", "x22" }, true },
+   { RISCV_ZERO_REGNUM + 23, { "s7", "x23" }, true },
+   { RISCV_ZERO_REGNUM + 24, { "s8", "x24" }, true },
+   { RISCV_ZERO_REGNUM + 25, { "s9", "x25" }, true },
+   { RISCV_ZERO_REGNUM + 26, { "s10", "x26" }, true },
+   { RISCV_ZERO_REGNUM + 27, { "s11", "x27" }, true },
+   { RISCV_ZERO_REGNUM + 28, { "t3", "x28" }, true },
+   { RISCV_ZERO_REGNUM + 29, { "t4", "x29" }, true },
+   { RISCV_ZERO_REGNUM + 30, { "t5", "x30" }, true },
+   { RISCV_ZERO_REGNUM + 31, { "t6", "x31" }, true },
+   { RISCV_ZERO_REGNUM + 32, { "pc" }, true }
+ }
+};
+
+/* The f-registers feature set.  */
+
+static const struct riscv_register_feature riscv_freg_feature =
+{
+ "org.gnu.gdb.riscv.fpu",
+ {
+   { RISCV_FIRST_FP_REGNUM + 0, { "ft0", "f0" }, true },
+   { RISCV_FIRST_FP_REGNUM + 1, { "ft1", "f1" }, true },
+   { RISCV_FIRST_FP_REGNUM + 2, { "ft2", "f2" }, true },
+   { RISCV_FIRST_FP_REGNUM + 3, { "ft3", "f3" }, true },
+   { RISCV_FIRST_FP_REGNUM + 4, { "ft4", "f4" }, true },
+   { RISCV_FIRST_FP_REGNUM + 5, { "ft5", "f5" }, true },
+   { RISCV_FIRST_FP_REGNUM + 6, { "ft6", "f6" }, true },
+   { RISCV_FIRST_FP_REGNUM + 7, { "ft7", "f7" }, true },
+   { RISCV_FIRST_FP_REGNUM + 8, { "fs0", "f8", "s0" }, true },
+   { RISCV_FIRST_FP_REGNUM + 9, { "fs1", "f9" }, true },
+   { RISCV_FIRST_FP_REGNUM + 10, { "fa0", "f10" }, true },
+   { RISCV_FIRST_FP_REGNUM + 11, { "fa1", "f11" }, true },
+   { RISCV_FIRST_FP_REGNUM + 12, { "fa2", "f12" }, true },
+   { RISCV_FIRST_FP_REGNUM + 13, { "fa3", "f13" }, true },
+   { RISCV_FIRST_FP_REGNUM + 14, { "fa4", "f14" }, true },
+   { RISCV_FIRST_FP_REGNUM + 15, { "fa5", "f15" }, true },
+   { RISCV_FIRST_FP_REGNUM + 16, { "fa6", "f16" }, true },
+   { RISCV_FIRST_FP_REGNUM + 17, { "fa7", "f17" }, true },
+   { RISCV_FIRST_FP_REGNUM + 18, { "fs2", "f18" }, true },
+   { RISCV_FIRST_FP_REGNUM + 19, { "fs3", "f19" }, true },
+   { RISCV_FIRST_FP_REGNUM + 20, { "fs4", "f20" }, true },
+   { RISCV_FIRST_FP_REGNUM + 21, { "fs5", "f21" }, true },
+   { RISCV_FIRST_FP_REGNUM + 22, { "fs6", "f22" }, true },
+   { RISCV_FIRST_FP_REGNUM + 23, { "fs7", "f23" }, true },
+   { RISCV_FIRST_FP_REGNUM + 24, { "fs8", "f24" }, true },
+   { RISCV_FIRST_FP_REGNUM + 25, { "fs9", "f25" }, true },
+   { RISCV_FIRST_FP_REGNUM + 26, { "fs10", "f26" }, true },
+   { RISCV_FIRST_FP_REGNUM + 27, { "fs11", "f27" }, true },
+   { RISCV_FIRST_FP_REGNUM + 28, { "ft8", "f28" }, true },
+   { RISCV_FIRST_FP_REGNUM + 29, { "ft9", "f29" }, true },
+   { RISCV_FIRST_FP_REGNUM + 30, { "ft10", "f30" }, true },
+   { RISCV_FIRST_FP_REGNUM + 31, { "ft11", "f31" }, true },
+
+   { RISCV_CSR_FFLAGS_REGNUM, { "fflags" }, true },
+   { RISCV_CSR_FRM_REGNUM, { "frm" }, true },
+   { RISCV_CSR_FCSR_REGNUM, { "fcsr" }, true },
+
+ }
+};
+
+/* Set of virtual registers.  These are not physical registers on the
+   hardware, but might be available from the target.  These are not pseudo
+   registers, reading these really does result in a register read from the
+   target, it is just that there might not be a physical register backing
+   the result.  */
+
+static const struct riscv_register_feature riscv_virtual_feature =
+{
+ "org.gnu.gdb.riscv.virtual",
+ {
+   { RISCV_PRIV_REGNUM, { "priv" }, false }
+ }
 };
 
-/* Table of register aliases.  */
-
-static const struct riscv_register_alias riscv_register_aliases[] =
-{
- /* Aliases for general purpose registers.  These are the architectural
-    names, as GDB uses the more user friendly names by default.  */
- { "x0", (RISCV_ZERO_REGNUM + 0) },
- { "x1", (RISCV_ZERO_REGNUM + 1) },
- { "x2", (RISCV_ZERO_REGNUM + 2) },
- { "x3", (RISCV_ZERO_REGNUM + 3) },
- { "x4", (RISCV_ZERO_REGNUM + 4) },
- { "x5", (RISCV_ZERO_REGNUM + 5) },
- { "x6", (RISCV_ZERO_REGNUM + 6) },
- { "x7", (RISCV_ZERO_REGNUM + 7) },
- { "x8", (RISCV_ZERO_REGNUM + 8) },
- { "s0", (RISCV_ZERO_REGNUM + 8) },	/* fp, s0, and x8 are all aliases.  */
- { "x9", (RISCV_ZERO_REGNUM + 9) },
- { "x10", (RISCV_ZERO_REGNUM + 10) },
- { "x11", (RISCV_ZERO_REGNUM + 11) },
- { "x12", (RISCV_ZERO_REGNUM + 12) },
- { "x13", (RISCV_ZERO_REGNUM + 13) },
- { "x14", (RISCV_ZERO_REGNUM + 14) },
- { "x15", (RISCV_ZERO_REGNUM + 15) },
- { "x16", (RISCV_ZERO_REGNUM + 16) },
- { "x17", (RISCV_ZERO_REGNUM + 17) },
- { "x18", (RISCV_ZERO_REGNUM + 18) },
- { "x19", (RISCV_ZERO_REGNUM + 19) },
- { "x20", (RISCV_ZERO_REGNUM + 20) },
- { "x21", (RISCV_ZERO_REGNUM + 21) },
- { "x22", (RISCV_ZERO_REGNUM + 22) },
- { "x23", (RISCV_ZERO_REGNUM + 23) },
- { "x24", (RISCV_ZERO_REGNUM + 24) },
- { "x25", (RISCV_ZERO_REGNUM + 25) },
- { "x26", (RISCV_ZERO_REGNUM + 26) },
- { "x27", (RISCV_ZERO_REGNUM + 27) },
- { "x28", (RISCV_ZERO_REGNUM + 28) },
- { "x29", (RISCV_ZERO_REGNUM + 29) },
- { "x30", (RISCV_ZERO_REGNUM + 30) },
- { "x31", (RISCV_ZERO_REGNUM + 31) },
-
- /* Aliases for the floating-point registers.  These are the architectural
-    names as GDB uses the more user friendly names by default.  */
- { "f0", (RISCV_FIRST_FP_REGNUM + 0) },
- { "f1", (RISCV_FIRST_FP_REGNUM + 1) },
- { "f2", (RISCV_FIRST_FP_REGNUM + 2) },
- { "f3", (RISCV_FIRST_FP_REGNUM + 3) },
- { "f4", (RISCV_FIRST_FP_REGNUM + 4) },
- { "f5", (RISCV_FIRST_FP_REGNUM + 5) },
- { "f6", (RISCV_FIRST_FP_REGNUM + 6) },
- { "f7", (RISCV_FIRST_FP_REGNUM + 7) },
- { "f8", (RISCV_FIRST_FP_REGNUM + 8) },
- { "f9", (RISCV_FIRST_FP_REGNUM + 9) },
- { "f10", (RISCV_FIRST_FP_REGNUM + 10) },
- { "f11", (RISCV_FIRST_FP_REGNUM + 11) },
- { "f12", (RISCV_FIRST_FP_REGNUM + 12) },
- { "f13", (RISCV_FIRST_FP_REGNUM + 13) },
- { "f14", (RISCV_FIRST_FP_REGNUM + 14) },
- { "f15", (RISCV_FIRST_FP_REGNUM + 15) },
- { "f16", (RISCV_FIRST_FP_REGNUM + 16) },
- { "f17", (RISCV_FIRST_FP_REGNUM + 17) },
- { "f18", (RISCV_FIRST_FP_REGNUM + 18) },
- { "f19", (RISCV_FIRST_FP_REGNUM + 19) },
- { "f20", (RISCV_FIRST_FP_REGNUM + 20) },
- { "f21", (RISCV_FIRST_FP_REGNUM + 21) },
- { "f22", (RISCV_FIRST_FP_REGNUM + 22) },
- { "f23", (RISCV_FIRST_FP_REGNUM + 23) },
- { "f24", (RISCV_FIRST_FP_REGNUM + 24) },
- { "f25", (RISCV_FIRST_FP_REGNUM + 25) },
- { "f26", (RISCV_FIRST_FP_REGNUM + 26) },
- { "f27", (RISCV_FIRST_FP_REGNUM + 27) },
- { "f28", (RISCV_FIRST_FP_REGNUM + 28) },
- { "f29", (RISCV_FIRST_FP_REGNUM + 29) },
- { "f30", (RISCV_FIRST_FP_REGNUM + 30) },
- { "f31", (RISCV_FIRST_FP_REGNUM + 31) },
+/* Feature set for CSRs.  This set is NOT constant as the register names
+   list for each register is not complete.  The aliases are computed
+   during RISCV_CREATE_CSR_ALIASES.  */
+
+static struct riscv_register_feature riscv_csr_feature =
+{
+ "org.gnu.gdb.riscv.csr",
+ {
+#define DECLARE_CSR(NAME,VALUE) \
+  { RISCV_ ## VALUE ## _REGNUM, { # NAME }, false },
+#include "opcode/riscv-opc.h"
+#undef DECLARE_CSR
+ }
 };
 
+/* Complete RISCV_CSR_FEATURE, building the CSR alias names and adding them
+   to the name list for each register.  */
+
+static void
+riscv_create_csr_aliases ()
+{
+  for (auto &reg : riscv_csr_feature.registers)
+    {
+      int csr_num = reg.regnum - RISCV_FIRST_CSR_REGNUM;
+      const char *alias = xstrprintf ("csr%d", csr_num);
+      reg.names.push_back (alias);
+    }
+}
+
 /* Controls whether we place compressed breakpoints or not.  When in auto
    mode GDB tries to determine if the target supports compressed
    breakpoints, and uses them if it does.  */
@@ -293,82 +351,17 @@ static unsigned int riscv_debug_infcall = 0;
 
 static unsigned int riscv_debug_unwinder = 0;
 
-/* Read the MISA register from the target.  There are a couple of locations
-   that the register might be found, these are all tried.  If the MISA
-   register can't be found at all then the default value of 0 is returned,
-   this is inline with the RISC-V specification.  */
-
-static uint32_t
-riscv_read_misa_reg ()
-{
-  uint32_t value = 0;
-
-  if (target_has_registers)
-    {
-      /* Old cores might have MISA located at a different offset.  */
-      static int misa_regs[] =
-	{ RISCV_CSR_MISA_REGNUM, RISCV_CSR_LEGACY_MISA_REGNUM };
-
-      struct frame_info *frame = get_current_frame ();
-
-      for (int i = 0; i < ARRAY_SIZE (misa_regs); ++i)
-	{
-	  bool success = false;
-
-	  TRY
-	    {
-	      value = get_frame_register_unsigned (frame, misa_regs[i]);
-	      success = true;
-	    }
-	  CATCH (ex, RETURN_MASK_ERROR)
-	    {
-	      /* Ignore errors, it is acceptable for a target to not
-		 provide a MISA register, in which case the default value
-		 of 0 should be used.  */
-	    }
-	  END_CATCH
-
-	  if (success)
-	    break;
-	}
-    }
-
-  return value;
-}
+/* When this is set to non-zero debugging information about gdbarch
+   initialisation will be printed.  */
 
-/* Return true if FEATURE is available for the architecture GDBARCH.  The
-   FEATURE should be one of the single character feature codes described in
-   the RiscV ISA manual, these are between 'A' and 'Z'.  */
-
-static bool
-riscv_has_feature (struct gdbarch *gdbarch, char feature)
-{
-  gdb_assert (feature >= 'A' && feature <= 'Z');
-
-  uint32_t misa = riscv_read_misa_reg ();
-  if (misa == 0)
-    misa = gdbarch_tdep (gdbarch)->core_features;
-
-  return (misa & (1 << (feature - 'A'))) != 0;
-}
+static unsigned int riscv_debug_gdbarch = 0;
 
 /* See riscv-tdep.h.  */
 
 int
 riscv_isa_xlen (struct gdbarch *gdbarch)
 {
-  switch (gdbarch_tdep (gdbarch)->abi.fields.base_len)
-    {
-    default:
-      warning (_("unknown xlen size, assuming 4 bytes"));
-      /* Fall through.  */
-    case 1:
-      return 4;
-    case 2:
-      return 8;
-    case 3:
-      return 16;
-    }
+  return gdbarch_tdep (gdbarch)->features.xlen;
 }
 
 /* See riscv-tdep.h.  */
@@ -376,14 +369,7 @@ riscv_isa_xlen (struct gdbarch *gdbarch)
 int
 riscv_isa_flen (struct gdbarch *gdbarch)
 {
-  if (riscv_has_feature (gdbarch, 'Q'))
-    return 16;
-  else if (riscv_has_feature (gdbarch, 'D'))
-    return 8;
-  else if (riscv_has_feature (gdbarch, 'F'))
-    return 4;
-
-  return 0;
+  return gdbarch_tdep (gdbarch)->features.flen;
 }
 
 /* Return true if the target for GDBARCH has floating point hardware.  */
@@ -399,7 +385,7 @@ riscv_has_fp_regs (struct gdbarch *gdbarch)
 static bool
 riscv_has_fp_abi (struct gdbarch *gdbarch)
 {
-  return (gdbarch_tdep (gdbarch)->abi.fields.float_abi != 0);
+  return gdbarch_tdep (gdbarch)->features.hw_float_abi;
 }
 
 /* Return true if REGNO is a floating pointer register.  */
@@ -485,16 +471,36 @@ value_of_riscv_user_reg (struct frame_info *frame, const void *baton)
   return value_of_register (*reg_p, frame);
 }
 
-/* Implement the register_name gdbarch method.  */
+/* Implement the register_name gdbarch method.  This is used instead of
+   the function supplied by calling TDESC_USE_REGISTERS so that we can
+   ensure the preferred names are offered.  */
 
 static const char *
 riscv_register_name (struct gdbarch *gdbarch, int regnum)
 {
-  /* Prefer to use the alias. */
-  if (regnum >= RISCV_ZERO_REGNUM && regnum <= RISCV_LAST_FP_REGNUM)
+  /* Lookup the name through the target description.  If we get back NULL
+     then this is an unknown register.  If we do get a name back then we
+     look up the registers preferred name below.  */
+  const char *name = tdesc_register_name (gdbarch, regnum);
+  if (name == NULL || name[0] == '\0')
+    return NULL;
+
+  if (regnum >= RISCV_ZERO_REGNUM && regnum < RISCV_FIRST_FP_REGNUM)
+    {
+      gdb_assert (regnum < riscv_xreg_feature.registers.size ());
+      return riscv_xreg_feature.registers[regnum].names[0];
+    }
+
+  if (regnum >= RISCV_FIRST_FP_REGNUM && regnum <= RISCV_LAST_FP_REGNUM)
     {
-      gdb_assert (regnum < ARRAY_SIZE (riscv_gdb_reg_names));
-      return riscv_gdb_reg_names[regnum];
+      if (riscv_has_fp_regs (gdbarch))
+        {
+          regnum -= RISCV_FIRST_FP_REGNUM;
+          gdb_assert (regnum < riscv_freg_feature.registers.size ());
+          return riscv_freg_feature.registers[regnum].names[0];
+        }
+      else
+        return NULL;
     }
 
   /* Check that there's no gap between the set of registers handled above,
@@ -509,14 +515,6 @@ riscv_register_name (struct gdbarch *gdbarch, int regnum)
       switch (regnum)
 	{
 	  #include "opcode/riscv-opc.h"
-	default:
-          {
-            static char buf[20];
-
-            xsnprintf (buf, sizeof (buf), "csr%d",
-                       regnum - RISCV_FIRST_CSR_REGNUM);
-            return buf;
-          }
 	}
 #undef DECLARE_CSR
     }
@@ -524,7 +522,10 @@ riscv_register_name (struct gdbarch *gdbarch, int regnum)
   if (regnum == RISCV_PRIV_REGNUM)
     return "priv";
 
-  return NULL;
+  /* It is possible that that the target provides some registers that GDB
+     is unaware of, in that case just return the NAME from the target
+     description.  */
+  return name;
 }
 
 /* Construct a type for 64-bit FP registers.  */
@@ -561,115 +562,59 @@ riscv_fpreg_d_type (struct gdbarch *gdbarch)
   return tdep->riscv_fpreg_d_type;
 }
 
-/* Construct a type for 128-bit FP registers.  */
+/* Implement the register_type gdbarch method.  This is installed as an
+   for the override setup by TDESC_USE_REGISTERS, for most registers we
+   delegate the type choice to the target description, but for a few
+   registers we try to improve the types if the target description has
+   taken a simplistic approach.  */
 
 static struct type *
-riscv_fpreg_q_type (struct gdbarch *gdbarch)
+riscv_register_type (struct gdbarch *gdbarch, int regnum)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct type *type = tdesc_register_type (gdbarch, regnum);
+  int xlen = riscv_isa_xlen (gdbarch);
 
-  if (tdep->riscv_fpreg_q_type == nullptr)
+  /* We want to perform some specific type "fixes" in cases where we feel
+     that we really can do better than the target description.  For all
+     other cases we just return what the target description says.  */
+  if (riscv_is_fp_regno_p (regnum))
     {
-      const struct builtin_type *bt = builtin_type (gdbarch);
-
-      /* The type we're building is this: */
-#if 0
-      union __gdb_builtin_type_fpreg_d
-      {
-	float f;
-	double d;
-	long double ld;
-      };
-#endif
-
-      struct type *t;
-
-      t = arch_composite_type (gdbarch,
-			       "__gdb_builtin_type_fpreg_q", TYPE_CODE_UNION);
-      append_composite_type_field (t, "float", bt->builtin_float);
-      append_composite_type_field (t, "double", bt->builtin_double);
-      append_composite_type_field (t, "long double", bt->builtin_long_double);
-      TYPE_VECTOR (t) = 1;
-      TYPE_NAME (t) = "builtin_type_fpreg_q";
-      tdep->riscv_fpreg_q_type = t;
+      /* This spots the case for RV64 where the double is defined as
+         either 'ieee_double' or 'float' (which is the generic name that
+         converts to 'double' on 64-bit).  In these cases its better to
+         present the registers using a union type.  */
+      int flen = riscv_isa_flen (gdbarch);
+      if (flen == 8
+          && TYPE_CODE (type) == TYPE_CODE_FLT
+          && TYPE_LENGTH (type) == flen
+          && (strcmp (TYPE_NAME (type), "builtin_type_ieee_double") == 0
+              || strcmp (TYPE_NAME (type), "double") == 0))
+        type = riscv_fpreg_d_type (gdbarch);
     }
 
-  return tdep->riscv_fpreg_q_type;
-}
-
-/* Implement the register_type gdbarch method.  */
-
-static struct type *
-riscv_register_type (struct gdbarch *gdbarch, int regnum)
-{
-  int regsize;
-
-  if (regnum < RISCV_FIRST_FP_REGNUM)
+  if ((regnum == gdbarch_pc_regnum (gdbarch)
+       || regnum == RISCV_RA_REGNUM
+       || regnum == RISCV_FP_REGNUM
+       || regnum == RISCV_SP_REGNUM
+       || regnum == RISCV_GP_REGNUM
+       || regnum == RISCV_TP_REGNUM)
+      && TYPE_CODE (type) == TYPE_CODE_INT
+      && TYPE_LENGTH (type) == xlen)
     {
+      /* This spots the case where some interesting registers are defined
+         as simple integers of the expected size, we force these registers
+         to be pointers as we believe that is more useful.  */
       if (regnum == gdbarch_pc_regnum (gdbarch)
-	  || regnum == RISCV_RA_REGNUM)
-	return builtin_type (gdbarch)->builtin_func_ptr;
-
-      if (regnum == RISCV_FP_REGNUM
-	  || regnum == RISCV_SP_REGNUM
-	  || regnum == RISCV_GP_REGNUM
-	  || regnum == RISCV_TP_REGNUM)
-	return builtin_type (gdbarch)->builtin_data_ptr;
-
-      /* Remaining GPRs vary in size based on the current ISA.  */
-      regsize = riscv_isa_xlen (gdbarch);
-      switch (regsize)
-	{
-	case 4:
-	  return builtin_type (gdbarch)->builtin_uint32;
-	case 8:
-	  return builtin_type (gdbarch)->builtin_uint64;
-	case 16:
-	  return builtin_type (gdbarch)->builtin_uint128;
-	default:
-	  internal_error (__FILE__, __LINE__,
-			  _("unknown isa regsize %i"), regsize);
-	}
+          || regnum == RISCV_RA_REGNUM)
+        type = builtin_type (gdbarch)->builtin_func_ptr;
+      else if (regnum == RISCV_FP_REGNUM
+               || regnum == RISCV_SP_REGNUM
+               || regnum == RISCV_GP_REGNUM
+               || regnum == RISCV_TP_REGNUM)
+	type = builtin_type (gdbarch)->builtin_data_ptr;
     }
-  else if (regnum <= RISCV_LAST_FP_REGNUM)
-    {
-      regsize = riscv_isa_xlen (gdbarch);
-      switch (regsize)
-	{
-	case 4:
-	  return builtin_type (gdbarch)->builtin_float;
-	case 8:
-	  return riscv_fpreg_d_type (gdbarch);
-	case 16:
-	  return riscv_fpreg_q_type (gdbarch);
-	default:
-	  internal_error (__FILE__, __LINE__,
-			  _("unknown isa regsize %i"), regsize);
-	}
-    }
-  else if (regnum == RISCV_PRIV_REGNUM)
-    return builtin_type (gdbarch)->builtin_int8;
-  else
-    {
-      if (regnum == RISCV_CSR_FFLAGS_REGNUM
-	  || regnum == RISCV_CSR_FRM_REGNUM
-	  || regnum == RISCV_CSR_FCSR_REGNUM)
-	return builtin_type (gdbarch)->builtin_int32;
 
-      regsize = riscv_isa_xlen (gdbarch);
-      switch (regsize)
-	{
-	case 4:
-	  return builtin_type (gdbarch)->builtin_int32;
-	case 8:
-	  return builtin_type (gdbarch)->builtin_int64;
-	case 16:
-	  return builtin_type (gdbarch)->builtin_int128;
-	default:
-	  internal_error (__FILE__, __LINE__,
-			  _("unknown isa regsize %i"), regsize);
-	}
-    }
+  return type;
 }
 
 /* Helper for riscv_print_registers_info, prints info for a single register
@@ -682,14 +627,28 @@ riscv_print_one_register_info (struct gdbarch *gdbarch,
 			       int regnum)
 {
   const char *name = gdbarch_register_name (gdbarch, regnum);
-  struct value *val = value_of_register (regnum, frame);
-  struct type *regtype = value_type (val);
+  struct value *val;
+  struct type *regtype;
   int print_raw_format;
   enum tab_stops { value_column_1 = 15 };
 
   fputs_filtered (name, file);
   print_spaces_filtered (value_column_1 - strlen (name), file);
 
+  TRY
+    {
+      val = value_of_register (regnum, frame);
+      regtype = value_type (val);
+    }
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      /* Handle failure to read a register without interrupting the entire
+         'info registers' flow.  */
+      fprintf_filtered (file, "%s\n", ex.message);
+      return;
+    }
+  END_CATCH
+
   print_raw_format = (value_entirely_available (val)
 		      && !value_optimized_out (val));
 
@@ -904,6 +863,15 @@ riscv_register_reggroup_p (struct gdbarch  *gdbarch, int regnum,
       || gdbarch_register_name (gdbarch, regnum)[0] == '\0')
     return 0;
 
+  if (regnum > RISCV_LAST_REGNUM)
+    {
+      int ret = tdesc_register_in_reggroup_p (gdbarch, regnum, reggroup);
+      if (ret != -1)
+        return ret;
+
+      return default_register_reggroup_p (gdbarch, regnum, reggroup);
+    }
+
   if (reggroup == all_reggroup)
     {
       if (regnum < RISCV_FIRST_CSR_REGNUM || regnum == RISCV_PRIV_REGNUM)
@@ -926,7 +894,7 @@ riscv_register_reggroup_p (struct gdbarch  *gdbarch, int regnum,
       else
 	return regnum < RISCV_FIRST_FP_REGNUM;
     }
-  else if (reggroup == system_reggroup)
+  else if (reggroup == system_reggroup || reggroup == csr_reggroup)
     {
       if (regnum == RISCV_PRIV_REGNUM)
 	return 1;
@@ -954,7 +922,6 @@ riscv_print_registers_info (struct gdbarch *gdbarch,
   if (regnum != -1)
     {
       /* Print one specified register.  */
-      gdb_assert (regnum <= RISCV_LAST_REGNUM);
       if (gdbarch_register_name (gdbarch, regnum) == NULL
 	  || *(gdbarch_register_name (gdbarch, regnum)) == '\0')
         error (_("Not a valid register for the current processor type"));
@@ -981,7 +948,7 @@ riscv_print_registers_info (struct gdbarch *gdbarch,
 	    continue;
 
 	  /* Is the register in the group we're interested in?  */
-	  if (!riscv_register_reggroup_p (gdbarch, regnum, reggroup))
+	  if (!gdbarch_register_reggroup_p (gdbarch, regnum, reggroup))
 	    continue;
 
 	  riscv_print_one_register_info (gdbarch, file, frame, regnum);
@@ -2822,36 +2789,26 @@ static const struct frame_unwind riscv_frame_unwind =
   /*.prev_arch     =*/ NULL,
 };
 
-/* Initialize the current architecture based on INFO.  If possible,
-   re-use an architecture from ARCHES, which is a list of
-   architectures already created during this debugging session.
-
-   Called e.g. at program startup, when reading a core file, and when
-   reading a binary file.  */
+/* Find a suitable default target description.  Use the contents of INFO,
+   specifically the bfd object being executed, to guide the selection of a
+   suitable default target description.  */
 
-static struct gdbarch *
-riscv_gdbarch_init (struct gdbarch_info info,
-		    struct gdbarch_list *arches)
+static struct target_desc *
+riscv_find_default_target_description (const struct gdbarch_info info)
 {
-  struct gdbarch *gdbarch;
-  struct gdbarch_tdep *tdep;
-  struct gdbarch_tdep tmp_tdep;
-  int i;
-
-  /* Ideally, we'd like to get as much information from the target for
-     things like register size, and whether the target has floating point
-     hardware.  However, there are some things that the target can't tell
-     us, like, what ABI is being used.
+  struct riscv_gdbarch_features features;
 
-     So, for now, we take as much information as possible from the ELF,
-     including things like register size, and FP hardware support, along
-     with information about the ABI.
-
-     Information about this target is built up in TMP_TDEP, and then we
-     look for an existing gdbarch in ARCHES that matches TMP_TDEP.  If no
-     match is found we'll create a new gdbarch and copy TMP_TDEP over.  */
-  memset (&tmp_tdep, 0, sizeof (tmp_tdep));
+  /* Setup some arbitrary defaults.  */
+  features.xlen = 8;
+  features.flen = 0;
+  features.hw_float_abi = false;
 
+  /* Now try to improve on the defaults by looking at the binary we are
+     going to execute.  We assume the user knows what they are doing and
+     that the target will match the binary.  Remember, this code path is
+     only used at all if the target hasn't given us a description, so this
+     is really a last ditched effort to do something sane before giving
+     up.  */
   if (info.abfd != NULL
       && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
     {
@@ -2859,26 +2816,22 @@ riscv_gdbarch_init (struct gdbarch_info info,
       int e_flags = elf_elfheader (info.abfd)->e_flags;
 
       if (eclass == ELFCLASS32)
-	tmp_tdep.abi.fields.base_len = 1;
+	features.xlen = 4;
       else if (eclass == ELFCLASS64)
-	tmp_tdep.abi.fields.base_len = 2;
+	features.xlen = 8;
       else
-        internal_error (__FILE__, __LINE__,
+	internal_error (__FILE__, __LINE__,
 			_("unknown ELF header class %d"), eclass);
 
-      if (e_flags & EF_RISCV_RVC)
-	tmp_tdep.core_features |= (1 << ('C' - 'A'));
-
       if (e_flags & EF_RISCV_FLOAT_ABI_DOUBLE)
 	{
-	  tmp_tdep.abi.fields.float_abi = 2;
-	  tmp_tdep.core_features |= (1 << ('D' - 'A'));
-	  tmp_tdep.core_features |= (1 << ('F' - 'A'));
+	  features.flen = 8;
+	  features.hw_float_abi = true;
 	}
       else if (e_flags & EF_RISCV_FLOAT_ABI_SINGLE)
 	{
-	  tmp_tdep.abi.fields.float_abi = 1;
-	  tmp_tdep.core_features |= (1 << ('F' - 'A'));
+	  features.flen = 4;
+	  features.hw_float_abi = true;
 	}
     }
   else
@@ -2886,25 +2839,210 @@ riscv_gdbarch_init (struct gdbarch_info info,
       const struct bfd_arch_info *binfo = info.bfd_arch_info;
 
       if (binfo->bits_per_word == 32)
-	tmp_tdep.abi.fields.base_len = 1;
+	features.xlen = 4;
       else if (binfo->bits_per_word == 64)
-	tmp_tdep.abi.fields.base_len = 2;
+	features.xlen = 8;
       else
-        internal_error (__FILE__, __LINE__, _("unknown bits_per_word %d"),
+	internal_error (__FILE__, __LINE__, _("unknown bits_per_word %d"),
 			binfo->bits_per_word);
     }
 
+  /* Now build a target description based on the feature set.  */
+  return riscv_create_target_description (features);
+}
+
+/* All of the registers in REG_SET are checked for in FEATURE, TDESC_DATA
+   is updated with the register numbers for each register as listed in
+   REG_SET.  If any register marked as required in REG_SET is not found in
+   FEATURE then this function returns false, otherwise, it returns true.  */
+
+static bool
+riscv_check_tdesc_feature (struct tdesc_arch_data *tdesc_data,
+                           const struct tdesc_feature *feature,
+                           const struct riscv_register_feature *reg_set)
+{
+  for (const auto &reg : reg_set->registers)
+    {
+      bool found = false;
+
+      for (const char *name : reg.names)
+	{
+	  found =
+	    tdesc_numbered_register (feature, tdesc_data, reg.regnum, name);
+
+	  if (found)
+	    break;
+	}
+
+      if (!found && reg.required_p)
+	return false;
+    }
+
+  return true;
+}
+
+/* Add all the expected register sets into GDBARCH.  */
+
+static void
+riscv_add_reggroups (struct gdbarch *gdbarch)
+{
+  /* Add predefined register groups.  */
+  reggroup_add (gdbarch, all_reggroup);
+  reggroup_add (gdbarch, save_reggroup);
+  reggroup_add (gdbarch, restore_reggroup);
+  reggroup_add (gdbarch, system_reggroup);
+  reggroup_add (gdbarch, vector_reggroup);
+  reggroup_add (gdbarch, general_reggroup);
+  reggroup_add (gdbarch, float_reggroup);
+
+  /* Add RISC-V specific register groups.  */
+  reggroup_add (gdbarch, csr_reggroup);
+}
+
+/* Create register aliases for all the alternative names that exist for
+   registers in REG_SET.  */
+
+static void
+riscv_setup_register_aliases (struct gdbarch *gdbarch,
+                              const struct riscv_register_feature *reg_set)
+{
+  for (auto &reg : reg_set->registers)
+    {
+      /* The first item in the names list is the preferred name for the
+         register, this is what RISCV_REGISTER_NAME returns, and so we
+         don't need to create an alias with that name here.  */
+      for (int i = 1; i < reg.names.size (); ++i)
+        user_reg_add (gdbarch, reg.names[i], value_of_riscv_user_reg,
+                      &reg.regnum);
+    }
+}
+
+/* Initialize the current architecture based on INFO.  If possible,
+   re-use an architecture from ARCHES, which is a list of
+   architectures already created during this debugging session.
+
+   Called e.g. at program startup, when reading a core file, and when
+   reading a binary file.  */
+
+static struct gdbarch *
+riscv_gdbarch_init (struct gdbarch_info info,
+		    struct gdbarch_list *arches)
+{
+  struct gdbarch *gdbarch;
+  struct gdbarch_tdep *tdep;
+  struct riscv_gdbarch_features features;
+  const struct target_desc *tdesc = info.target_desc;
+
+  /* Ensure we always have a target description.  */
+  if (!tdesc_has_registers (tdesc))
+    tdesc = riscv_find_default_target_description (info);
+  gdb_assert (tdesc);
+
+  if (riscv_debug_gdbarch)
+    fprintf_unfiltered (gdb_stdlog, "Have got a target description\n");
+
+  const struct tdesc_feature *feature_cpu
+    = tdesc_find_feature (tdesc, riscv_xreg_feature.name);
+  const struct tdesc_feature *feature_fpu
+    = tdesc_find_feature (tdesc, riscv_freg_feature.name);
+  const struct tdesc_feature *feature_virtual
+    = tdesc_find_feature (tdesc, riscv_virtual_feature.name);
+  const struct tdesc_feature *feature_csr
+    = tdesc_find_feature (tdesc, riscv_csr_feature.name);
+
+  if (feature_cpu == NULL)
+    return NULL;
+
+  struct tdesc_arch_data *tdesc_data = tdesc_data_alloc ();
+
+  bool valid_p = riscv_check_tdesc_feature (tdesc_data,
+                                            feature_cpu,
+                                            &riscv_xreg_feature);
+  if (valid_p)
+    {
+      /* Check that all of the core cpu registers have the same bitsize.  */
+      int xlen_bitsize = tdesc_register_bitsize (feature_cpu, "pc");
+
+      for (auto &tdesc_reg : feature_cpu->registers)
+        valid_p &= (tdesc_reg->bitsize == xlen_bitsize);
+
+      if (riscv_debug_gdbarch)
+        fprintf_filtered
+          (gdb_stdlog,
+           "From target-description, xlen = %d\n", xlen_bitsize);
+
+      features.xlen = (xlen_bitsize / 8);
+    }
+
+  if (feature_fpu != NULL)
+    {
+      valid_p &= riscv_check_tdesc_feature (tdesc_data, feature_fpu,
+                                            &riscv_freg_feature);
+
+      int bitsize = tdesc_register_bitsize (feature_fpu, "ft0");
+      features.flen = (bitsize / 8);
+      features.hw_float_abi = true;
+
+      if (riscv_debug_gdbarch)
+        fprintf_filtered
+          (gdb_stdlog,
+           "From target-description, flen = %d\n", bitsize);
+    }
+  else
+    {
+      features.flen = 0;
+      features.hw_float_abi = false;
+
+      if (riscv_debug_gdbarch)
+        fprintf_filtered
+          (gdb_stdlog,
+           "No FPU in target-description, assume soft-float ABI\n");
+    }
+
+  if (feature_virtual)
+    riscv_check_tdesc_feature (tdesc_data, feature_virtual,
+                               &riscv_virtual_feature);
+
+  if (feature_csr)
+    riscv_check_tdesc_feature (tdesc_data, feature_csr,
+                               &riscv_csr_feature);
+
+  if (!valid_p)
+    {
+      if (riscv_debug_gdbarch)
+        fprintf_unfiltered (gdb_stdlog, "Target description is not valid\n");
+      tdesc_data_cleanup (tdesc_data);
+      return NULL;
+    }
+
   /* Find a candidate among the list of pre-declared architectures.  */
   for (arches = gdbarch_list_lookup_by_info (arches, &info);
        arches != NULL;
        arches = gdbarch_list_lookup_by_info (arches->next, &info))
-    if (gdbarch_tdep (arches->gdbarch)->abi.value == tmp_tdep.abi.value)
+    {
+      /* Check that the feature set of the ARCHES matches the feature set
+         we are looking for.  If it doesn't then we can't reuse this
+         gdbarch.  */
+      struct gdbarch_tdep *other_tdep = gdbarch_tdep (arches->gdbarch);
+
+      if (other_tdep->features.hw_float_abi != features.hw_float_abi
+          || other_tdep->features.xlen != features.xlen
+          || other_tdep->features.flen != features.flen)
+        continue;
+
+      break;
+    }
+
+  if (arches != NULL)
+    {
+      tdesc_data_cleanup (tdesc_data);
       return arches->gdbarch;
+    }
 
   /* None found, so create a new architecture from the information provided.  */
-  tdep = (struct gdbarch_tdep *) xmalloc (sizeof *tdep);
+  tdep = new (struct gdbarch_tdep);
   gdbarch = gdbarch_alloc (&info, tdep);
-  memcpy (tdep, &tmp_tdep, sizeof (tmp_tdep));
+  tdep->features = features;
 
   /* Target data types.  */
   set_gdbarch_short_bit (gdbarch, 16);
@@ -2924,19 +3062,6 @@ riscv_gdbarch_init (struct gdbarch_info info,
   set_gdbarch_sw_breakpoint_from_kind (gdbarch, riscv_sw_breakpoint_from_kind);
   set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
 
-  /* Register architecture.  */
-  set_gdbarch_num_regs (gdbarch, RISCV_LAST_REGNUM + 1);
-  set_gdbarch_sp_regnum (gdbarch, RISCV_SP_REGNUM);
-  set_gdbarch_pc_regnum (gdbarch, RISCV_PC_REGNUM);
-  set_gdbarch_ps_regnum (gdbarch, RISCV_FP_REGNUM);
-  set_gdbarch_deprecated_fp_regnum (gdbarch, RISCV_FP_REGNUM);
-
-  /* Functions to supply register information.  */
-  set_gdbarch_register_name (gdbarch, riscv_register_name);
-  set_gdbarch_register_type (gdbarch, riscv_register_type);
-  set_gdbarch_print_registers_info (gdbarch, riscv_print_registers_info);
-  set_gdbarch_register_reggroup_p (gdbarch, riscv_register_reggroup_p);
-
   /* Functions to analyze frames.  */
   set_gdbarch_skip_prologue (gdbarch, riscv_skip_prologue);
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
@@ -2957,9 +3082,49 @@ riscv_gdbarch_init (struct gdbarch_info info,
   dwarf2_append_unwinders (gdbarch);
   frame_unwind_append_unwinder (gdbarch, &riscv_frame_unwind);
 
-  for (i = 0; i < ARRAY_SIZE (riscv_register_aliases); ++i)
-    user_reg_add (gdbarch, riscv_register_aliases[i].name,
-		  value_of_riscv_user_reg, &riscv_register_aliases[i].regnum);
+  /* Register architecture.  */
+  riscv_add_reggroups (gdbarch);
+
+  /* We reserve all possible register numbers for the known registers.
+     This means the target description mechanism will add any target
+     specific registers after this number.  This helps make debugging GDB
+     just a little easier.  */
+  set_gdbarch_num_regs (gdbarch, RISCV_LAST_REGNUM + 1);
+
+  /* We don't have to provide the count of 0 here (its the default) but
+     include this line to make it explicit that, right now, we don't have
+     any pseudo registers on RISC-V.  */
+  set_gdbarch_num_pseudo_regs (gdbarch, 0);
+
+  /* Some specific register numbers GDB likes to know about.  */
+  set_gdbarch_sp_regnum (gdbarch, RISCV_SP_REGNUM);
+  set_gdbarch_pc_regnum (gdbarch, RISCV_PC_REGNUM);
+
+  set_gdbarch_print_registers_info (gdbarch, riscv_print_registers_info);
+
+  /* Finalise the target description registers.  */
+  tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+
+  /* Override the register type callback setup by the target description
+     mechanism.  This allows us to provide special type for floating point
+     registers.  */
+  set_gdbarch_register_type (gdbarch, riscv_register_type);
+
+  /* Override the register name callback setup by the target description
+     mechanism.  This allows us to force our preferred names for the
+     registers, no matter what the target description called them.  */
+  set_gdbarch_register_name (gdbarch, riscv_register_name);
+
+  /* Override the register group callback setup by the target description
+     mechanism.  This allows us to force registers into the groups we
+     want, ignoring what the target tells us.  */
+  set_gdbarch_register_reggroup_p (gdbarch, riscv_register_reggroup_p);
+
+  /* Create register aliases for alternative register names.  */
+  riscv_setup_register_aliases (gdbarch, &riscv_xreg_feature);
+  if (riscv_has_fp_regs (gdbarch))
+    riscv_setup_register_aliases (gdbarch, &riscv_freg_feature);
+  riscv_setup_register_aliases (gdbarch, &riscv_csr_feature);
 
   /* Hook in OS ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
@@ -3106,9 +3271,20 @@ riscv_software_single_step (struct regcache *regcache)
   return {next_pc};
 }
 
+/* Create RISC-V specific reggroups.  */
+
+static void
+riscv_init_reggroups ()
+{
+  csr_reggroup = reggroup_new ("csr", USER_REGGROUP);
+}
+
 void
 _initialize_riscv_tdep (void)
 {
+  riscv_create_csr_aliases ();
+  riscv_init_reggroups ();
+
   gdbarch_register (bfd_arch_riscv, riscv_gdbarch_init, NULL);
 
   /* Add root prefix command for all "set debug riscv" and "show debug
@@ -3153,6 +3329,16 @@ of the stack unwinding mechanism."),
 			     show_riscv_debug_variable,
 			     &setdebugriscvcmdlist, &showdebugriscvcmdlist);
 
+  add_setshow_zuinteger_cmd ("gdbarch", class_maintenance,
+			     &riscv_debug_gdbarch,  _("\
+Set riscv gdbarch initialisation debugging."), _("\
+Show riscv gdbarch initialisation debugging."), _("\
+When non-zero, print debugging information for the riscv gdbarch\n\
+initialisation process."),
+			     NULL,
+			     show_riscv_debug_variable,
+			     &setdebugriscvcmdlist, &showdebugriscvcmdlist);
+
   /* Add root prefix command for all "set riscv" and "show riscv" commands.  */
   add_prefix_cmd ("riscv", no_class, set_riscv_command,
 		  _("RISC-V specific commands."),
diff --git a/gdb/riscv-tdep.h b/gdb/riscv-tdep.h
index 2cb51b16c53..59ad37df6ce 100644
--- a/gdb/riscv-tdep.h
+++ b/gdb/riscv-tdep.h
@@ -21,6 +21,8 @@
 #ifndef RISCV_TDEP_H
 #define RISCV_TDEP_H
 
+#include "arch/riscv.h"
+
 /* RiscV register numbers.  */
 enum
 {
@@ -57,31 +59,12 @@ enum
 /* RISC-V specific per-architecture information.  */
 struct gdbarch_tdep
 {
-  union
-  {
-    /* Provide access to the whole ABI in one value.  */
-    unsigned value;
-
-    struct
-    {
-      /* Encode the base machine length following the same rules as in the
-	 MISA register.  */
-      unsigned base_len : 2;
-
-      /* Encode which floating point ABI is in use following the same rules
-	 as the ELF e_flags field.  */
-      unsigned float_abi : 2;
-    } fields;
-  } abi;
-
-  /* Only the least significant 26 bits are (possibly) valid, and indicate
-     features that are supported on the target.  These could be cached from
-     the target, or read from the executable when available.  */
-  unsigned core_features;
+  /* Features about the target that impact how the gdbarch is configured.
+     Two gdbarch instances are compatible only if this field matches.  */
+  struct riscv_gdbarch_features features;
 
   /* ISA-specific data types.  */
-  struct type *riscv_fpreg_d_type;
-  struct type *riscv_fpreg_q_type;
+  struct type *riscv_fpreg_d_type = nullptr;
 };
 
 
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index bdd29c0f2b5..20604bb4b96 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -1716,6 +1716,7 @@ maint_print_c_tdesc_cmd (const char *args, int from_tty)
   if (startswith (filename_after_features.c_str (), "i386/32bit-")
       || startswith (filename_after_features.c_str (), "i386/64bit-")
       || startswith (filename_after_features.c_str (), "i386/x32-core.xml")
+      || startswith (filename_after_features.c_str (), "riscv/")
       || startswith (filename_after_features.c_str (), "tic6x-")
       || startswith (filename_after_features.c_str (), "aarch64"))
     {
