diff --git a/gdb/testsuite/gdb.base/all-architectures.exp b/gdb/testsuite/gdb.base/all-architectures.exp
new file mode 100644
index 0000000..9748304
--- /dev/null
+++ b/gdb/testsuite/gdb.base/all-architectures.exp
@@ -0,0 +1,315 @@
+# Copyright (C) 2016 Free Software Foundation, Inc.
+
+# 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/>.
+
+# This file is part of the gdb testsuite.
+
+# Test manually setting _all_ combinations of all supported bfd
+# architectures and OS ABIs.  This ensures that gdbarch initialization
+# routines handle unusual combinations gracefully, at least without
+# crashing.
+
+# While at it, because the number of possible combinations is quite
+# large, embed other checks that might be useful to do with all
+# supported archs.
+
+# One such test is ensuring that printing float, double and long
+# double types works in cross/bi-arch scenarios.  Some of GDB's float
+# format conversion routines used to fail to consider that even if
+# host and target floating formats match, their sizes may still
+# differ.  E.g., on x86, long double is 80-bit extended precision on
+# both 32-bit vs 64-bit, but it's stored as 96 bit on 32-bit, and 128
+# bit on 64-bit.  This resulted in GDB accessing memory out of bounds.
+# This test catches the issue when run against gdb linked with
+# libmcheck, or run under Valgrind.
+
+clean_restart
+
+# By default, preparation steps don't output a PASS message.  This is
+# because the testcase has several thousand such steps.
+set want_tests_messages 0
+
+# Call this when an "internal" preparation-like step test passed.
+# Logs the pass in gdb.log, but not in gdb.sum.
+
+proc internal_pass {message} {
+    global want_tests_messages
+
+    if {$want_tests_messages} {
+	pass $message
+    } else {
+	# Skip the sum file, but still log an internal pass in the log
+	# file.
+	global pf_prefix
+
+	verbose -log "IPASS: $pf_prefix $message"
+    }
+}
+
+# The number of times gdb_test_internal was called, and the number of
+# time that resulted in an internal pass.  If these don't match, then
+# some test failed.
+set test_count 0
+set internal_pass_count 0
+
+# Like gdb_test, but calls internal_pass instead of pass, on success.
+
+proc gdb_test_internal {cmd pattern {message ""}} {
+    global test_count internal_pass_count
+    global gdb_prompt
+
+    incr test_count
+
+    if {$message == ""} {
+	set message $cmd
+    }
+
+    gdb_test_multiple $cmd $message {
+	-re "$pattern\r\n$gdb_prompt $" {
+	    internal_pass $message
+	    incr internal_pass_count
+	}
+    }
+}
+
+gdb_test_internal "set max-completions unlimited" \
+    "^set max-completions unlimited"
+
+# Return a list of all the accepted values of "set WHAT".
+
+proc get_set_option_choices {what} {
+    global gdb_prompt
+
+    set values {}
+
+    set test "complete set $what"
+    gdb_test_multiple "complete set $what " "$test" {
+	-re "set $what (\[^\r\n\]+)\r\n" {
+	    lappend values $expect_out(1,string)
+	    exp_continue
+	}
+	-re "$gdb_prompt " {
+	    internal_pass $test
+	}
+    }
+    return $values
+}
+
+set supported_archs [get_set_option_choices "architecture"]
+# There should be at least one more than "auto".
+gdb_assert {[llength $supported_archs] > 1} "at least one architecture"
+
+set supported_osabis [get_set_option_choices "osabi"]
+# There should be at least one more than "auto" and "default".
+gdb_assert {[llength $supported_osabis] > 2} "at least one osabi"
+
+if {[lsearch $supported_archs "mips"] >= 0} {
+    set supported_mipsfpu [get_set_option_choices "mipsfpu"]
+    set supported_mips_abi [get_set_option_choices "mips abi"]
+
+    gdb_assert {[llength $supported_mipsfpu] != 0} "at least one mipsfpu"
+    gdb_assert {[llength $supported_mips_abi] != 0} "at least one mips abi"
+}
+
+if {[lsearch $supported_archs "arm"] >= 0} {
+    set supported_arm_fpu [get_set_option_choices "arm fpu"]
+    set supported_arm_abi [get_set_option_choices "arm abi"]
+
+    gdb_assert {[llength $supported_arm_fpu] != 0} "at least one arm fpu"
+    gdb_assert {[llength $supported_arm_abi] != 0} "at least one arm abi"
+}
+
+# Exercise printing float, double and long double.
+
+proc print_floats {} {
+    gdb_test_internal "ptype 1.0L" "type = long double" "ptype, long double"
+    gdb_test_internal "print 1.0L" " = 1" "print, long double"
+
+    gdb_test_internal "ptype 1.0" "type = double" "ptype, double"
+    gdb_test_internal "print 1.0" " = 1" "print, double"
+
+    gdb_test_internal "ptype 1.0f" "type = float" "ptype, float"
+    gdb_test_internal "print 1.0f" " = 1" "print, float"
+}
+
+# Run tests on the current architecture.
+
+proc do_arch_tests {} {
+    print_floats
+}
+
+# Given we can't change arch, osabi, endianness, etc. atomically, we
+# need to silently ignore the case of the current OS ABI (not the one
+# we'll switch to) not having a handler for the arch.
+set osabi_warning \
+    [multi_line \
+	 "warning: A handler for the OS ABI .* is not built into this configuration" \
+	 "of GDB.  Attempting to continue with the default .* settings." \
+	 "" \
+	 "" \
+	]
+
+set endian_warning "(Little|Big) endian target not supported by GDB\r\n"
+
+# Like gdb_test_no_output, but use internal_pass instead of pass, and
+# ignore "no handler for OS ABI" warnings.
+
+proc gdb_test_no_output_osabi {cmd test} {
+    global osabi_warning
+    global gdb_prompt
+
+    gdb_test_multiple "$cmd" $test {
+	-re "^${cmd}\r\n(${osabi_warning})?$gdb_prompt $" {
+	    internal_pass $test
+	}
+    }
+}
+
+# It'd be nicer/safer to restart GDB on each iteration, but, that
+# increases the testcase's run time several times fold.  At the time
+# of writting, it'd jump from 20s to 4min on x86-64 GNU/Linux with
+# --enable-targets=all.
+
+with_test_prefix "tests" {
+    foreach_with_prefix osabi $supported_osabis {
+
+	gdb_test_no_output_osabi "set osabi $osabi" \
+	    "set osabi"
+
+	foreach_with_prefix arch $supported_archs {
+	    if {$arch == "auto"} {
+		continue
+	    }
+	    set default_endian ""
+	    foreach_with_prefix endian {"auto" "big" "little"} {
+
+		set test "set endian"
+		if {$endian == $default_endian} {
+		    continue
+		} elseif {$endian == "auto"} {
+		    gdb_test_multiple "set endian $endian" $test {
+			-re "^set endian $endian\r\n(${osabi_warning})?The target endianness is set automatically \\(currently .* endian\\)\r\n$gdb_prompt $" {
+			    internal_pass $test
+			}
+		    }
+		} else {
+		    gdb_test_multiple "set endian $endian" $test {
+			-re "^set endian $endian\r\n${endian_warning}.*\r\n$gdb_prompt $" {
+			    internal_pass $test
+			    continue
+			}
+			-re "^set endian $endian\r\n(${osabi_warning})?The target is assumed to be $endian endian\r\n$gdb_prompt $" {
+			    internal_pass $test
+			}
+		    }
+		}
+
+		# Skip setting the same architecture again.
+		if {$endian == "auto"} {
+		    set arch_re [string_to_regexp $arch]
+		    set test "set architecture $arch"
+		    gdb_test_multiple $test $test {
+			-re "^set architecture $arch_re\r\n(${osabi_warning})?The target architecture is assumed to be $arch_re\r\n$gdb_prompt $" {
+			    internal_pass $test
+			}
+			-re "Architecture .* not recognized.*$gdb_prompt $" {
+			    # GDB is missing support for a few
+			    # machines that bfd supports.
+			    if  {$arch == "powerpc:EC603e"
+				 || $arch == "powerpc:e500mc"
+				 || $arch == "powerpc:e500mc64"
+				 || $arch == "powerpc:vle"
+				 || $arch == "powerpc:titan"
+				 || $arch == "powerpc:e5500"
+				 || $arch == "powerpc:e6500"} {
+				if {$want_tests_messages} {
+				    kfail $test "gdb/19797"
+				}
+			    } else {
+				fail "$test (arch not recognized)"
+			    }
+			    continue
+			}
+		    }
+
+		    # Record what is the default endianess.  As an
+		    # optimization, we'll skip testing the manual "set
+		    # endian DEFAULT" case.
+		    set test "show endian"
+		    gdb_test_multiple "show endian" $test {
+			-re "currently little endian.*$gdb_prompt $" {
+			    set default_endian "little"
+			    internal_pass $test
+			}
+			-re "currently big endian.*$gdb_prompt $" {
+			    set default_endian "big"
+			    internal_pass $test
+			}
+		    }
+		}
+
+		# Some architectures have extra settings that affect
+		# the ABI.  Specify the extra testing axes in a
+		# declarative form.
+		#
+		# A list of {COMMAND, VAR, OPTIONS-LIST} elements.
+		set all_axes {}
+
+		if {$arch == "mips"} {
+		    lappend all_axes [list "set mips abi" mips_abi $supported_mips_abi]
+		    lappend all_axes [list "set mipsfpu" mipsfpu $supported_mipsfpu]
+		} elseif {$arch == "arm"} {
+		    lappend all_axes [list "set arm abi" arm_abi $supported_arm_abi]
+		    lappend all_axes [list "set arm fpu" arm_fpu $supported_arm_fpu]
+		}
+
+		# Run testing axis CUR_AXIS.  This is a recursive
+		# procedure that tries all combinations of options of
+		# all the testing axes.
+		proc run_axis {all_axes cur_axis} {
+		    if {$cur_axis == [llength $all_axes]} {
+			do_arch_tests
+			return
+		    }
+
+		    # Unpack the axis.
+		    set axis [lindex $all_axes $cur_axis]
+		    set cmd [lindex $axis 0]
+		    set var [lindex $axis 1]
+		    set options [lindex $axis 2]
+
+		    foreach v $options {
+			with_test_prefix "$var=$v" {
+			    gdb_test_no_output_osabi "$cmd $v" "$cmd"
+			    run_axis $all_axes [expr $cur_axis + 1]
+			}
+		    }
+		}
+
+		run_axis $all_axes 0
+	    }
+	}
+    }
+}
+
+# A test that:
+#
+#  - ensures there's a PASS if all internal tests actually passed
+#
+#  - ensures there's at least one test that is interpreted as a
+#    regression (a matching PASS->FAIL) if some of the internal tests
+#    failed, instead of looking like it could be a new FAIL that could
+#    be ignored.
+#
+gdb_assert {$internal_pass_count == $test_count} "all passed"
