diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 3ce7d69..e0fe442 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1039,6 +1039,7 @@ SFILES = \
 	dfp.c \
 	dictionary.c \
 	disasm.c \
+	disasm-selftests.c \
 	doublest.c \
 	dtrace-probe.c \
 	dummy-frame.c \
@@ -1140,6 +1141,7 @@ SFILES = \
 	rust-exp.y \
 	rust-lang.c \
 	selftest.c \
+	selftest-arch.c \
 	sentinel-frame.c \
 	ser-base.c \
 	ser-event.c \
@@ -1396,6 +1398,7 @@ HFILES_NO_SRCDIR = \
 	rs6000-tdep.h \
 	s390-linux-tdep.h \
 	score-tdep.h \
+	selftest-arch.h \
 	sentinel-frame.h \
 	ser-base.h \
 	ser-event.h \
@@ -1643,6 +1646,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	dfp.o \
 	dictionary.o \
 	disasm.o \
+	disasm-selftests.o \
 	doublest.o \
 	dummy-frame.o \
 	dwarf2-frame.o \
@@ -1744,6 +1748,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	run-time-clock.o \
 	rust-lang.o \
 	selftest.o \
+	selftest-arch.o \
 	sentinel-frame.o \
 	ser-event.o \
 	serial.o \
diff --git a/gdb/disasm-selftests.c b/gdb/disasm-selftests.c
new file mode 100644
index 0000000..46a0a21
--- /dev/null
+++ b/gdb/disasm-selftests.c
@@ -0,0 +1,178 @@
+/* Self tests for disassembler for GDB, the GNU debugger.
+
+   Copyright (C) 2017 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 "defs.h"
+#include "disasm.h"
+
+#if GDB_SELF_TEST
+#include "selftest.h"
+#include "selftest-arch.h"
+
+namespace selftests {
+
+/* Test disassembly of one instruction.  */
+
+static void
+gdb_disassembler_print_one_insn_test (struct gdbarch *gdbarch)
+{
+  size_t len = 0;
+  const gdb_byte *insn = NULL;
+
+  switch (gdbarch_bfd_arch_info (gdbarch)->arch)
+    {
+    case bfd_arch_bfin:
+      /* M3.L = 0xe117 */
+      static const gdb_byte bfin_insn[] = {0x17, 0xe1, 0xff, 0xff};
+
+      insn = bfin_insn;
+      len = sizeof (bfin_insn);
+      break;
+    case bfd_arch_arm:
+      /* mov     r0, #0 */
+      static const gdb_byte arm_insn[] = {0x0, 0x0, 0xa0, 0xe3};
+
+      insn = arm_insn;
+      len = sizeof (arm_insn);
+      break;
+    case bfd_arch_ia64:
+    case bfd_arch_mep:
+    case bfd_arch_mips:
+    case bfd_arch_tic6x:
+    case bfd_arch_xtensa:
+      return;
+    case bfd_arch_s390:
+      /* nopr %r7 */
+      static const gdb_byte s390_insn[] = {0x07, 0x07};
+
+      insn = s390_insn;
+      len = sizeof (s390_insn);
+      break;
+    case bfd_arch_xstormy16:
+      /* nop */
+      static const gdb_byte xstormy16_insn[] = {0x0, 0x0};
+
+      insn = xstormy16_insn;
+      len = sizeof (xstormy16_insn);
+      break;
+    case bfd_arch_arc:
+      {
+	/* PR 21003 */
+	if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_arc_arc601)
+	  return;
+      }
+    case bfd_arch_nios2:
+    case bfd_arch_score:
+      /* nios2 and score need to know the current instruction to select
+	 breakpoint instruction.  Give the breakpoint instruction kind
+	 explicitly.  */
+      insn = gdbarch_sw_breakpoint_from_kind (gdbarch, 4, (int *) &len);
+      break;
+    default:
+      {
+	/* Test disassemble breakpoint instruction.  */
+	CORE_ADDR pc = 0;
+	int kind = gdbarch_breakpoint_kind_from_pc (gdbarch, &pc);
+
+	insn = gdbarch_sw_breakpoint_from_kind (gdbarch, kind,
+						(int *) &len);
+
+	break;
+      }
+    }
+  SELF_CHECK (len > 0);
+
+  /* Test gdb_disassembler for a given gdbarch by reading data from a
+     pre-allocated buffer.  If you want to see the disassembled
+     instruction printed to gdb_stdout, set DISASSEMBLER_TEST_VERBOSE
+     to true.  */
+
+  class gdb_disassembler_test : public gdb_disassembler
+  {
+  public:
+
+    const bool DISASSEMBLER_TEST_VERBOSE = false;
+
+    explicit gdb_disassembler_test (struct gdbarch *gdbarch,
+				    const gdb_byte *insn,
+				    size_t len)
+      : gdb_disassembler (gdbarch,
+			  (DISASSEMBLER_TEST_VERBOSE
+			   ? gdb_stdout : null_stream ()),
+			  gdb_disassembler_test::read_memory),
+	m_insn (insn), m_len (len)
+    {
+    }
+
+    int
+    print_insn (CORE_ADDR memaddr)
+    {
+      if (DISASSEMBLER_TEST_VERBOSE)
+	{
+	  fprintf_unfiltered (stream (), "%s ",
+			      gdbarch_bfd_arch_info (arch ())->arch_name);
+	}
+
+      int len = gdb_disassembler::print_insn (memaddr);
+
+      if (DISASSEMBLER_TEST_VERBOSE)
+	fprintf_unfiltered (stream (), "\n");
+
+      return len;
+    }
+
+  private:
+    /* A buffer contain one instruction.  */
+    const gdb_byte *m_insn;
+
+    /* Length of the buffer.  */
+    size_t m_len;
+
+    static int read_memory (bfd_vma memaddr, gdb_byte *myaddr,
+			    unsigned int len, struct disassemble_info *info)
+    {
+      gdb_disassembler_test *self
+	= static_cast<gdb_disassembler_test *>(info->application_data);
+
+      /* The disassembler in opcodes may read more data than one
+	 instruction.  */
+      for (unsigned int i = 0; i < len; i++)
+	myaddr[i] = self->m_insn[(memaddr + i) % self->m_len];
+
+      return 0;
+    }
+  };
+
+  gdb_disassembler_test di (gdbarch, insn, len);
+
+  SELF_CHECK (di.print_insn (0) == len);
+}
+
+} // namespace selftests
+#endif /* GDB_SELF_TEST */
+
+/* Suppress warning from -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_disasm_test;
+
+void
+_initialize_disasm_test (void)
+{
+#if GDB_SELF_TEST
+  register_self_test (selftests::gdb_disassembler_print_one_insn_test);
+#endif
+}
diff --git a/gdb/selftest-arch.c b/gdb/selftest-arch.c
new file mode 100644
index 0000000..aa716be
--- /dev/null
+++ b/gdb/selftest-arch.c
@@ -0,0 +1,103 @@
+/* GDB self-test for each gdbarch.
+   Copyright (C) 2017 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 "defs.h"
+
+#if GDB_SELF_TEST
+#include "selftest.h"
+#include "selftest-arch.h"
+#include "arch-utils.h"
+
+static std::vector<self_test_function_with_gdbarch *> gdbarch_tests;
+
+void
+register_self_test (self_test_function_with_gdbarch *function)
+{
+  gdbarch_tests.push_back (function);
+}
+
+namespace selftests {
+
+static void
+tests_with_arch (void)
+{
+  int failed = 0;
+
+  for (const auto &f : gdbarch_tests)
+    {
+      const char **arches = gdbarch_printable_names ();
+      int i;
+
+      for (i = 0; arches[i] != NULL; i++)
+	{
+	  if (strcmp ("fr300", arches[i]) == 0)
+	    {
+	      /* PR 20946 */
+	      continue;
+	    }
+	  else if (strcmp ("powerpc:EC603e", arches[i]) == 0
+		   || strcmp ("powerpc:e500mc", arches[i]) == 0
+		   || strcmp ("powerpc:e500mc64", arches[i]) == 0
+		   || strcmp ("powerpc:titan", arches[i]) == 0
+		   || strcmp ("powerpc:vle", arches[i]) == 0
+		   || strcmp ("powerpc:e5500", arches[i]) == 0
+		   || strcmp ("powerpc:e6500", arches[i]) == 0)
+	    {
+	      /* PR 19797 */
+	      continue;
+	    }
+
+	  QUIT;
+
+	  TRY
+	    {
+	      struct gdbarch_info info;
+
+	      gdbarch_info_init (&info);
+	      info.bfd_arch_info = bfd_scan_arch (arches[i]);
+
+	      struct gdbarch *gdbarch = gdbarch_find_by_info (info);
+	      SELF_CHECK (gdbarch != NULL);
+	      f (gdbarch);
+	    }
+	  CATCH (ex, RETURN_MASK_ERROR)
+	    {
+	      ++failed;
+	      exception_fprintf (gdb_stderr, ex,
+				 _("Self test failed: arch %s: "), arches[i]);
+	    }
+	  END_CATCH
+	}
+    }
+
+  SELF_CHECK (failed == 0);
+}
+
+} // namespace selftests
+#endif /* GDB_SELF_TEST */
+
+/* Suppress warning from -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_selftests_with_arch;
+
+void
+_initialize_selftests_with_arch (void)
+{
+#if GDB_SELF_TEST
+  register_self_test (selftests::tests_with_arch);
+#endif
+}
diff --git a/gdb/selftest-arch.h b/gdb/selftest-arch.h
new file mode 100644
index 0000000..d63c2d2
--- /dev/null
+++ b/gdb/selftest-arch.h
@@ -0,0 +1,26 @@
+/* GDB self-test for each gdbarch.
+   Copyright (C) 2017 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 SELFTEST_ARCH_H
+#define SELFTEST_ARCH_H
+
+typedef void self_test_function_with_gdbarch (struct gdbarch *);
+
+extern void register_self_test (self_test_function_with_gdbarch *function);
+
+#endif /* SELFTEST_ARCH_H */
