diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index 2432bae..edbb1b3 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -1600,6 +1600,33 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch,
     }
 }
 
+/* Similar to amd64_supply_fpregset, but use XSAVE extended state.  */
+
+static void
+amd64_linux_supply_xstateregset (const struct regset *regset,
+				 struct regcache *regcache, int regnum,
+				 const void *xstateregs, size_t len)
+{
+  amd64_supply_xsave (regcache, regnum, xstateregs);
+}
+
+/* Similar to amd64_collect_fpregset, but use XSAVE extended state.  */
+
+static void
+amd64_linux_collect_xstateregset (const struct regset *regset,
+				  const struct regcache *regcache,
+				  int regnum, void *xstateregs, size_t len)
+{
+  amd64_collect_xsave (regcache, regnum, xstateregs, 1);
+}
+
+static const struct regset amd64_linux_xstateregset =
+  {
+    NULL,
+    amd64_linux_supply_xstateregset,
+    amd64_linux_collect_xstateregset
+  };
+
 /* Iterate over core file register note sections.  */
 
 static void
@@ -1608,9 +1635,12 @@ amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					  void *cb_data,
 					  const struct regcache *regcache)
 {
-  cb (".reg", 27 * 8, "general-purpose", cb_data);
-  cb (".reg2", 512, "floating-point", cb_data);
-  cb (".reg-xstate", X86_XSTATE_MAX_SIZE, "XSAVE extended state", cb_data);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  cb (".reg", 27 * 8, &i386_gregset, NULL, cb_data);
+  cb (".reg2", 512, &amd64_fpregset, NULL, cb_data);
+  cb (".reg-xstate",  regcache ? X86_XSTATE_MAX_SIZE : 0,
+      &amd64_linux_xstateregset, "XSAVE extended state", cb_data);
 }
 
 static void
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index abd9c48..7c8575a 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -2868,53 +2868,10 @@ amd64_collect_fpregset (const struct regset *regset,
   amd64_collect_fxsave (regcache, regnum, fpregs);
 }
 
-/* Similar to amd64_supply_fpregset, but use XSAVE extended state.  */
-
-static void
-amd64_supply_xstateregset (const struct regset *regset,
-			   struct regcache *regcache, int regnum,
-			   const void *xstateregs, size_t len)
-{
-  amd64_supply_xsave (regcache, regnum, xstateregs);
-}
-
-/* Similar to amd64_collect_fpregset, but use XSAVE extended state.  */
-
-static void
-amd64_collect_xstateregset (const struct regset *regset,
-			    const struct regcache *regcache,
-			    int regnum, void *xstateregs, size_t len)
-{
-  amd64_collect_xsave (regcache, regnum, xstateregs, 1);
-}
-
-static const struct regset amd64_fpregset =
+const struct regset amd64_fpregset =
   {
     NULL, amd64_supply_fpregset, amd64_collect_fpregset
   };
-
-static const struct regset amd64_xstateregset =
-  {
-    NULL, amd64_supply_xstateregset, amd64_collect_xstateregset
-  };
-
-/* Return the appropriate register set for the core section identified
-   by SECT_NAME and SECT_SIZE.  */
-
-static const struct regset *
-amd64_regset_from_core_section (struct gdbarch *gdbarch,
-				const char *sect_name, size_t sect_size)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
-  if (strcmp (sect_name, ".reg2") == 0 && sect_size == tdep->sizeof_fpregset)
-    return &amd64_fpregset;
-
-  if (strcmp (sect_name, ".reg-xstate") == 0)
-    return &amd64_xstateregset;
-
-  return i386_regset_from_core_section (gdbarch, sect_name, sect_size);
-}
 
 
 /* Figure out where the longjmp will land.  Slurp the jmp_buf out of
@@ -2973,6 +2930,7 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* AMD64 generally uses `fxsave' instead of `fsave' for saving its
      floating-point registers.  */
   tdep->sizeof_fpregset = I387_SIZEOF_FXSAVE;
+  tdep->fpregset = &amd64_fpregset;
 
   if (! tdesc_has_registers (tdesc))
     tdesc = tdesc_amd64;
@@ -3086,11 +3044,6 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   frame_unwind_append_unwinder (gdbarch, &amd64_frame_unwind);
   frame_base_set_default (gdbarch, &amd64_frame_base);
 
-  /* If we have a register mapping, enable the generic core file support.  */
-  if (tdep->gregset_reg_offset)
-    set_gdbarch_regset_from_core_section (gdbarch,
-					  amd64_regset_from_core_section);
-
   set_gdbarch_get_longjmp_target (gdbarch, amd64_get_longjmp_target);
 
   set_gdbarch_relocate_instruction (gdbarch, amd64_relocate_instruction);
diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h
index f1b039e..641eef3 100644
--- a/gdb/amd64-tdep.h
+++ b/gdb/amd64-tdep.h
@@ -119,6 +119,8 @@ extern void amd64_collect_fxsave (const struct regcache *regcache, int regnum,
 extern void amd64_collect_xsave (const struct regcache *regcache,
 				 int regnum, void *xsave, int gcore);
 
+/* Floating-point register set. */
+extern const struct regset amd64_fpregset;
 
 /* Variables exported from amd64-linux-tdep.c.  */
 extern int amd64_linux_gregset_reg_offset[];
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 22decd5..e3587f3 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -731,28 +731,6 @@ static const struct regset arm_linux_vfpregset =
     NULL, arm_linux_supply_vfp, arm_linux_collect_vfp
   };
 
-/* Return the appropriate register set for the core section identified
-   by SECT_NAME and SECT_SIZE.  */
-
-static const struct regset *
-arm_linux_regset_from_core_section (struct gdbarch *gdbarch,
-				    const char *sect_name, size_t sect_size)
-{
-  if (strcmp (sect_name, ".reg") == 0
-      && sect_size == ARM_LINUX_SIZEOF_GREGSET)
-    return &arm_linux_gregset;
-
-  if (strcmp (sect_name, ".reg2") == 0
-      && sect_size == ARM_LINUX_SIZEOF_NWFPE)
-    return &arm_linux_fpregset;
-
-  if (strcmp (sect_name, ".reg-arm-vfp") == 0
-      && sect_size == ARM_LINUX_SIZEOF_VFP)
-    return &arm_linux_vfpregset;
-
-  return NULL;
-}
-
 /* Iterate over core file register note sections.  */
 
 static void
@@ -763,13 +741,14 @@ arm_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", ARM_LINUX_SIZEOF_GREGSET, "general-purpose", cb_data);
+  cb (".reg", ARM_LINUX_SIZEOF_GREGSET, &arm_linux_gregset, NULL, cb_data);
 
   if (tdep->have_vfp_registers)
-    cb (".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, "VFP floating-point",
-	cb_data);
+    cb (".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, &arm_linux_vfpregset,
+	"VFP floating-point", cb_data);
   else if (tdep->have_fpa_registers)
-    cb (".reg2", ARM_LINUX_SIZEOF_NWFPE, "FPA floating-point", cb_data);
+    cb (".reg2", ARM_LINUX_SIZEOF_NWFPE, &arm_linux_fpregset,
+	"FPA floating-point", cb_data);
 }
 
 /* Determine target description from core file.  */
@@ -1457,8 +1436,6 @@ arm_linux_init_abi (struct gdbarch_info info,
 				&arm_kernel_linux_restart_syscall_tramp_frame);
 
   /* Core file support.  */
-  set_gdbarch_regset_from_core_section (gdbarch,
-					arm_linux_regset_from_core_section);
   set_gdbarch_iterate_over_regset_sections
     (gdbarch, arm_linux_iterate_over_regset_sections);
   set_gdbarch_core_read_description (gdbarch, arm_linux_core_read_description);
diff --git a/gdb/corelow.c b/gdb/corelow.c
index 7e64e1d..42af7f4 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -134,7 +134,9 @@ sniff_core_bfd (bfd *abfd)
 
   /* Don't sniff if we have support for register sets in
      CORE_GDBARCH.  */
-  if (core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch))
+  if (core_gdbarch
+      && (gdbarch_iterate_over_regset_sections_p (core_gdbarch)
+	  || gdbarch_regset_from_core_section_p (core_gdbarch)))
     return NULL;
 
   for (cf = core_file_fns; cf != NULL; cf = cf->next)
@@ -489,7 +491,9 @@ core_detach (struct target_ops *ops, const char *args, int from_tty)
 
 static void
 get_core_register_section (struct regcache *regcache,
+			   const struct regset *regset,
 			   const char *name,
+			   int min_size,
 			   int which,
 			   const char *human_name,
 			   int required)
@@ -517,6 +521,12 @@ get_core_register_section (struct regcache *regcache,
     }
 
   size = bfd_section_size (core_bfd, section);
+  if (size < min_size)
+    {
+      warning (_("Section `%s' in core file too small."), section_name);
+      return;
+    }
+
   contents = alloca (size);
   if (! bfd_get_section_contents (core_bfd, section, contents,
 				  (file_ptr) 0, size))
@@ -526,10 +536,9 @@ get_core_register_section (struct regcache *regcache,
       return;
     }
 
-  if (core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch))
+  if (regset == NULL
+      && core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch))
     {
-      const struct regset *regset;
-
       regset = gdbarch_regset_from_core_section (core_gdbarch,
 						 name, size);
       if (regset == NULL)
@@ -539,7 +548,10 @@ get_core_register_section (struct regcache *regcache,
 		     human_name);
 	  return;
 	}
+    }
 
+  if (regset != NULL)
+    {
       regset->supply_regset (regset, regcache, -1, contents, size);
       return;
     }
@@ -555,16 +567,28 @@ get_core_register_section (struct regcache *regcache,
 
 static void
 get_core_registers_cb (const char *sect_name, int size,
+		       const struct regset *regset,
 		       const char *human_name, void *cb_data)
 {
   struct regcache *regcache = (struct regcache *) cb_data;
+  int required = 0;
 
   if (strcmp (sect_name, ".reg") == 0)
-    get_core_register_section (regcache, sect_name, 0, human_name, 1);
+    {
+      required = 1;
+      if (human_name == NULL)
+	human_name = "general-purpose";
+    }
   else if (strcmp (sect_name, ".reg2") == 0)
-    get_core_register_section (regcache, sect_name, 2, human_name, 0);
-  else
-    get_core_register_section (regcache, sect_name, 3, human_name, 0);
+    {
+      if (human_name == NULL)
+	human_name = "floating-point";
+    }
+
+  /* The 'which' parameter is only used when no regset is provided.
+     Thus we just set it to -1. */
+  get_core_register_section (regcache, regset, sect_name,
+			     size, -1, human_name, required);
 }
 
 /* Get the registers out of a core file.  This is the machine-
@@ -581,7 +605,9 @@ get_core_registers (struct target_ops *ops,
   int i;
   struct gdbarch *gdbarch;
 
-  if (!(core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch))
+  if (!(core_gdbarch
+	&& (gdbarch_iterate_over_regset_sections_p (core_gdbarch)
+	    || gdbarch_regset_from_core_section_p (core_gdbarch)))
       && (core_vec == NULL || core_vec->core_read_registers == NULL))
     {
       fprintf_filtered (gdb_stderr,
@@ -596,10 +622,10 @@ get_core_registers (struct target_ops *ops,
 					  (void *) regcache, NULL);
   else
     {
-      get_core_register_section (regcache,
-				 ".reg", 0, "general-purpose", 1);
-      get_core_register_section (regcache,
-				 ".reg2", 2, "floating-point", 0);
+      get_core_register_section (regcache, NULL,
+				 ".reg", 0, 0, "general-purpose", 1);
+      get_core_register_section (regcache, NULL,
+				 ".reg2", 0, 2, "floating-point", 0);
     }
 
   /* Mark all registers not found in the core as unavailable.  */
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index bbda3da..90a63ca 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -82,7 +82,8 @@ typedef int (iterate_over_objfiles_in_search_order_cb_ftype)
   (struct objfile *objfile, void *cb_data);
 
 typedef void (iterate_over_regset_sections_cb)
-  (const char *sect_name, int size, const char *human_name, void *cb_data);
+  (const char *sect_name, int size, const struct regset *regset,
+   const char *human_name, void *cb_data);
 
 
 /* The following are pre-initialized by GDBARCH.  */
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 80d3eec..293854f 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -1176,7 +1176,8 @@ typedef int (iterate_over_objfiles_in_search_order_cb_ftype)
   (struct objfile *objfile, void *cb_data);
 
 typedef void (iterate_over_regset_sections_cb)
-  (const char *sect_name, int size, const char *human_name, void *cb_data);
+  (const char *sect_name, int size, const struct regset *regset,
+   const char *human_name, void *cb_data);
 EOF
 
 # function typedef's
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index 4ee6874..7feb21d 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -648,6 +648,35 @@ i386_linux_core_read_description (struct gdbarch *gdbarch,
     return tdesc_i386_mmx_linux;
 }
 
+/* Similar to i386_supply_fpregset, but use XSAVE extended state.  */
+
+static void
+i386_linux_supply_xstateregset (const struct regset *regset,
+				struct regcache *regcache, int regnum,
+				const void *xstateregs, size_t len)
+{
+  i387_supply_xsave (regcache, regnum, xstateregs);
+}
+
+/* Similar to i386_collect_fpregset, but use XSAVE extended state.  */
+
+static void
+i386_linux_collect_xstateregset (const struct regset *regset,
+				 const struct regcache *regcache,
+				 int regnum, void *xstateregs, size_t len)
+{
+  i387_collect_xsave (regcache, regnum, xstateregs, 1);
+}
+
+/* Register set definitions.  */
+
+static const struct regset i386_linux_xstateregset =
+  {
+    NULL,
+    i386_linux_supply_xstateregset,
+    i386_linux_collect_xstateregset
+  };
+
 /* Iterate over core file register note sections.  */
 
 static void
@@ -658,14 +687,17 @@ i386_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", 68, "general-purpose", cb_data);
+  cb (".reg", 68, &i386_gregset, NULL, cb_data);
 
   if (tdep->xcr0 & X86_XSTATE_AVX)
-    cb (".reg-xstate", X86_XSTATE_MAX_SIZE, "XSAVE extended state", cb_data);
+    /* Use max size for writing, accept any size when reading.  */
+    cb (".reg-xstate", regcache ? X86_XSTATE_MAX_SIZE : 0,
+	&i386_linux_xstateregset, "XSAVE extended state", cb_data);
   else if (tdep->xcr0 & X86_XSTATE_SSE)
-    cb (".reg-xfp", 512, "extended floating-point", cb_data);
+    cb (".reg-xfp", 512, &i386_fpregset, "extended floating-point",
+	cb_data);
   else
-    cb (".reg2", 108, "floating-point", cb_data);
+    cb (".reg2", 108, &i386_fpregset, NULL, cb_data);
 }
 
 /* Linux kernel shows PC value after the 'int $0x80' instruction even if
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 1e68505..8f8cc99 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -3806,26 +3806,6 @@ i386_collect_fpregset (const struct regset *regset,
   i387_collect_fsave (regcache, regnum, fpregs);
 }
 
-/* Similar to i386_supply_fpregset, but use XSAVE extended state.  */
-
-static void
-i386_supply_xstateregset (const struct regset *regset,
-			  struct regcache *regcache, int regnum,
-			  const void *xstateregs, size_t len)
-{
-  i387_supply_xsave (regcache, regnum, xstateregs);
-}
-
-/* Similar to i386_collect_fpregset , but use XSAVE extended state.  */
-
-static void
-i386_collect_xstateregset (const struct regset *regset,
-			   const struct regcache *regcache,
-			   int regnum, void *xstateregs, size_t len)
-{
-  i387_collect_xsave (regcache, regnum, xstateregs, 1);
-}
-
 /* Register set definitions.  */
 
 const struct regset i386_gregset =
@@ -3833,16 +3813,11 @@ const struct regset i386_gregset =
     NULL, i386_supply_gregset, i386_collect_gregset
   };
 
-static const struct regset i386_fpregset =
+const struct regset i386_fpregset =
   {
     NULL, i386_supply_fpregset, i386_collect_fpregset
   };
 
-static const struct regset i386_xstateregset =
-  {
-    NULL, i386_supply_xstateregset, i386_collect_xstateregset
-  };
-
 /* Return the appropriate register set for the core section identified
    by SECT_NAME and SECT_SIZE.  */
 
@@ -3853,15 +3828,10 @@ i386_regset_from_core_section (struct gdbarch *gdbarch,
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (strcmp (sect_name, ".reg") == 0 && sect_size == tdep->sizeof_gregset)
-      return &i386_gregset;
-
-  if ((strcmp (sect_name, ".reg2") == 0 && sect_size == tdep->sizeof_fpregset)
-      || (strcmp (sect_name, ".reg-xfp") == 0
-	  && sect_size == I387_SIZEOF_FXSAVE))
-    return &i386_fpregset;
+    return &i386_gregset;
 
-  if (strcmp (sect_name, ".reg-xstate") == 0)
-    return &i386_xstateregset;
+  if (strcmp (sect_name, ".reg2") == 0 && sect_size == tdep->sizeof_fpregset)
+    return tdep->fpregset;
 
   return NULL;
 }
@@ -8291,6 +8261,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* Floating-point registers.  */
   tdep->sizeof_fpregset = I387_SIZEOF_FSAVE;
+  tdep->fpregset = &i386_fpregset;
 
   /* The default settings include the FPU registers, the MMX registers
      and the SSE registers.  This can be overridden for a specific ABI
@@ -8595,7 +8566,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* If we have a register mapping, enable the generic core file
      support, unless it has already been enabled.  */
   if (tdep->gregset_reg_offset
-      && !gdbarch_regset_from_core_section_p (gdbarch))
+      && !gdbarch_regset_from_core_section_p (gdbarch)
+      && !gdbarch_iterate_over_regset_sections_p (gdbarch))
     set_gdbarch_regset_from_core_section (gdbarch,
 					  i386_regset_from_core_section);
 
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index e0950a3..db8f4f7 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -237,6 +237,9 @@ struct gdbarch_tdep
   int (*i386_sysenter_record) (struct regcache *regcache);
   /* Parse syscall args.  */
   int (*i386_syscall_record) (struct regcache *regcache);
+
+  /* Regsets. */
+  const struct regset *fpregset;
 };
 
 /* Floating-point registers.  */
@@ -387,6 +390,9 @@ extern void i386_supply_gregset (const struct regset *regset,
 /* General-purpose register set. */
 extern const struct regset i386_gregset;
 
+/* Floating-point register set. */
+extern const struct regset i386_fpregset;
+
 /* Return the appropriate register set for the core section identified
    by SECT_NAME and SECT_SIZE.  */
 extern const struct regset *
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 3d8b1fc..fcba93b 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -1105,16 +1105,15 @@ struct linux_collect_regset_section_cb_data
 
 static void
 linux_collect_regset_section_cb (const char *sect_name, int size,
+				 const struct regset *regset,
 				 const char *human_name, void *cb_data)
 {
-  const struct regset *regset;
   char *buf;
   struct linux_collect_regset_section_cb_data *data = cb_data;
 
   if (data->abort_iteration)
     return;
 
-  regset = gdbarch_regset_from_core_section (data->gdbarch, sect_name, size);
   gdb_assert (regset && regset->collect_regset);
 
   buf = xmalloc (size);
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 7ab3255..4d7d051 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -489,27 +489,6 @@ ppc_linux_fpregset (void)
   return &ppc32_linux_fpregset;
 }
 
-static const struct regset *
-ppc_linux_regset_from_core_section (struct gdbarch *core_arch,
-				    const char *sect_name, size_t sect_size)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (core_arch);
-  if (strcmp (sect_name, ".reg") == 0)
-    {
-      if (tdep->wordsize == 4)
-	return &ppc32_linux_gregset;
-      else
-	return &ppc64_linux_gregset;
-    }
-  if (strcmp (sect_name, ".reg2") == 0)
-    return &ppc32_linux_fpregset;
-  if (strcmp (sect_name, ".reg-ppc-vmx") == 0)
-    return &ppc32_linux_vrregset;
-  if (strcmp (sect_name, ".reg-ppc-vsx") == 0)
-    return &ppc32_linux_vsxregset;
-  return NULL;
-}
-
 /* Iterate over supported core file register note sections. */
 
 static void
@@ -522,14 +501,18 @@ ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
   int have_altivec = tdep->ppc_vr0_regnum != -1;
   int have_vsx = tdep->ppc_vsr0_upper_regnum != -1;
 
-  cb (".reg", 48 * tdep->wordsize, "general-purpose", cb_data);
-  cb (".reg2", 264, "floating-point", cb_data);
+  if (tdep->wordsize == 4)
+    cb (".reg", 48 * 4, &ppc32_linux_gregset, NULL, cb_data);
+  else
+    cb (".reg", 48 * 8, &ppc64_linux_gregset, NULL, cb_data);
+
+  cb (".reg2", 264, &ppc32_linux_fpregset, NULL, cb_data);
 
   if (have_altivec)
-    cb (".reg-ppc-vmx", 544, "ppc Altivec", cb_data);
+    cb (".reg-ppc-vmx", 544, &ppc32_linux_vrregset, "ppc Altivec", cb_data);
 
   if (have_vsx)
-    cb (".reg-ppc-vsx", 256, "POWER7 VSX", cb_data);
+    cb (".reg-ppc-vsx", 256, &ppc32_linux_vsxregset, "POWER7 VSX", cb_data);
 }
 
 static void
@@ -1385,8 +1368,6 @@ ppc_linux_init_abi (struct gdbarch_info info,
     set_gdbarch_elfcore_write_linux_prpsinfo (gdbarch,
 					      elfcore_write_ppc_linux_prpsinfo32);
 
-  set_gdbarch_regset_from_core_section (gdbarch,
-					ppc_linux_regset_from_core_section);
   set_gdbarch_core_read_description (gdbarch, ppc_linux_core_read_description);
   set_gdbarch_iterate_over_regset_sections (gdbarch,
 					    ppc_linux_iterate_over_regset_sections);
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index 840431d..abd2e40 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -82,13 +82,6 @@ struct gdbarch_tdep
   int pc_regnum;
   int cc_regnum;
 
-  /* Core file register sets.  */
-  const struct regset *gregset;
-  int sizeof_gregset;
-
-  const struct regset *fpregset;
-  int sizeof_fpregset;
-
   int have_linux_v1;
   int have_linux_v2;
   int have_tdb;
@@ -536,36 +529,6 @@ const struct regset s390_tdb_regset = {
   regcache_collect_regset
 };
 
-/* Return the appropriate register set for the core section identified
-   by SECT_NAME and SECT_SIZE.  */
-static const struct regset *
-s390_regset_from_core_section (struct gdbarch *gdbarch,
-			       const char *sect_name, size_t sect_size)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
-  if (strcmp (sect_name, ".reg") == 0 && sect_size >= tdep->sizeof_gregset)
-    return tdep->gregset;
-
-  if (strcmp (sect_name, ".reg2") == 0 && sect_size >= tdep->sizeof_fpregset)
-    return tdep->fpregset;
-
-  if (strcmp (sect_name, ".reg-s390-high-gprs") == 0 && sect_size >= 16*4)
-    return &s390_upper_regset;
-
-  if (strcmp (sect_name, ".reg-s390-last-break") == 0 && sect_size >= 8)
-    return (gdbarch_ptr_bit (gdbarch) == 32
-	    ?  &s390_last_break_regset : &s390x_last_break_regset);
-
-  if (strcmp (sect_name, ".reg-s390-system-call") == 0 && sect_size >= 4)
-    return &s390_system_call_regset;
-
-  if (strcmp (sect_name, ".reg-s390-tdb") == 0 && sect_size >= 256)
-    return &s390_tdb_regset;
-
-  return NULL;
-}
-
 /* Iterate over supported core file register note sections. */
 
 static void
@@ -575,18 +538,25 @@ s390_iterate_over_regset_sections (struct gdbarch *gdbarch,
 				   const struct regcache *regcache)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  const int gregset_size = (tdep->abi == ABI_LINUX_S390 ?
+			    s390_sizeof_gregset : s390x_sizeof_gregset);
 
-  cb (".reg", tdep->sizeof_gregset, "general-purpose", cb_data);
-  cb (".reg2", s390_sizeof_fpregset, "floating-point", cb_data);
+  cb (".reg", gregset_size, &s390_gregset, NULL, cb_data);
+  cb (".reg2", s390_sizeof_fpregset, &s390_fpregset, NULL, cb_data);
 
   if (tdep->abi == ABI_LINUX_S390 && tdep->gpr_full_regnum != -1)
-    cb (".reg-s390-high-gprs", 16 * 4, "s390 GPR upper halves", cb_data);
+    cb (".reg-s390-high-gprs", 16 * 4, &s390_upper_regset,
+	"s390 GPR upper halves", cb_data);
 
   if (tdep->have_linux_v1)
-    cb (".reg-s390-last-break", 8, "s930 last-break address", cb_data);
+    cb (".reg-s390-last-break", 8,
+	(gdbarch_ptr_bit (gdbarch) == 32
+	 ? &s390_last_break_regset : &s390x_last_break_regset),
+	"s930 last-break address", cb_data);
 
   if (tdep->have_linux_v2)
-    cb (".reg-s390-system-call", 4, "s390 system-call", cb_data);
+    cb (".reg-s390-system-call", 4, &s390_system_call_regset,
+	"s390 system-call", cb_data);
 
   /* If regcache is set, we are in "write" (gcore) mode.  In this
      case, don't iterate over the TDB unless its registers are
@@ -595,7 +565,8 @@ s390_iterate_over_regset_sections (struct gdbarch *gdbarch,
       && (regcache == NULL
 	  || REG_VALID == regcache_register_status (regcache,
 						    S390_TDB_DWORD0_REGNUM)))
-    cb (".reg-s390-tdb", s390_sizeof_tdbregset, "s390 TDB", cb_data);
+    cb (".reg-s390-tdb", s390_sizeof_tdbregset, &s390_tdb_regset,
+	"s390 TDB", cb_data);
 }
 
 static const struct target_desc *
@@ -3067,8 +3038,6 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_stab_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum);
   set_gdbarch_dwarf2_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum);
   set_gdbarch_value_from_register (gdbarch, s390_value_from_register);
-  set_gdbarch_regset_from_core_section (gdbarch,
-					s390_regset_from_core_section);
   set_gdbarch_core_read_description (gdbarch, s390_core_read_description);
   set_gdbarch_iterate_over_regset_sections (gdbarch,
 					    s390_iterate_over_regset_sections);
@@ -3134,11 +3103,6 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   switch (tdep->abi)
     {
     case ABI_LINUX_S390:
-      tdep->gregset = &s390_gregset;
-      tdep->sizeof_gregset = s390_sizeof_gregset;
-      tdep->fpregset = &s390_fpregset;
-      tdep->sizeof_fpregset = s390_sizeof_fpregset;
-
       set_gdbarch_addr_bits_remove (gdbarch, s390_addr_bits_remove);
       set_solib_svr4_fetch_link_map_offsets
 	(gdbarch, svr4_ilp32_fetch_link_map_offsets);
@@ -3147,11 +3111,6 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       break;
 
     case ABI_LINUX_ZSERIES:
-      tdep->gregset = &s390_gregset;
-      tdep->sizeof_gregset = s390x_sizeof_gregset;
-      tdep->fpregset = &s390_fpregset;
-      tdep->sizeof_fpregset = s390_sizeof_fpregset;
-
       set_gdbarch_long_bit (gdbarch, 64);
       set_gdbarch_long_long_bit (gdbarch, 64);
       set_gdbarch_ptr_bit (gdbarch, 64);
