diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 13fac9256f..2624975146 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,10 @@
+2018-09-24  John Baldwin  <jhb@FreeBSD.org>
+
+	* trad-frame.c (trad_frame_set_regmap, trad_frame_set_reg_regmap):
+	New.
+	* trad-frame.h (trad_frame_set_regmap, trad_frame_set_reg_regmap):
+	New.
+
 2018-09-24  Tom Tromey  <tom@tromey.com>
 
 	* common/pathstuff.c (get_standard_cache_dir): Make
diff --git a/gdb/trad-frame.c b/gdb/trad-frame.c
index fd9f24084d..e09a333499 100644
--- a/gdb/trad-frame.c
+++ b/gdb/trad-frame.c
@@ -22,6 +22,7 @@
 #include "trad-frame.h"
 #include "regcache.h"
 #include "frame-unwind.h"
+#include "target.h"
 #include "value.h"
 
 struct trad_frame_cache
@@ -125,6 +126,64 @@ trad_frame_set_addr (struct trad_frame_saved_reg this_saved_regs[],
   this_saved_regs[regnum].addr = addr;
 }
 
+void
+trad_frame_set_regmap (struct trad_frame_saved_reg this_saved_regs[],
+		       struct gdbarch *gdbarch, const void *regmap,
+		       CORE_ADDR addr, size_t size)
+{
+  const struct regcache_map_entry *map;
+  int offs = 0, count;
+
+  for (map = (const struct regcache_map_entry *) regmap;
+       (count = map->count) != 0;
+       map++)
+    {
+      int regno = map->regno;
+      int slot_size = map->size;
+
+      if (slot_size == 0 && regno != REGCACHE_MAP_SKIP)
+	slot_size = register_size (gdbarch, regno);
+
+      if (offs + slot_size > size)
+	break;
+
+      if (regno == REGCACHE_MAP_SKIP)
+	offs += count * slot_size;
+      else
+	for (; count--; regno++, offs += slot_size)
+	  {
+	    /* Mimic the semantics of regcache::transfer_regset if a
+	       register slot's size does not match the size of a
+	       register.
+
+	       If a register slot is larger than a register, assume
+	       the register's value is stored in the first N bytes of
+	       the slot and ignore the remaining bytes.
+
+	       If the register slot is smaller than the register,
+	       assume that the slot contains the low N bytes of the
+	       register's value.  Since trad_frame assumes that
+	       registers stored by address are sized according to the
+	       register, read the low N bytes and zero-extend them to
+	       generate a register value.  */
+	    if (slot_size >= register_size (gdbarch, regno))
+	      trad_frame_set_addr (this_saved_regs, regno, addr + offs);
+	    else
+	      {
+		enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+		gdb_byte buf[slot_size];
+
+		if (target_read_memory (addr + offs, buf, sizeof buf) == 0)
+		  {
+		    LONGEST val
+		      = extract_unsigned_integer (buf, sizeof buf, byte_order);
+		    trad_frame_set_value (this_saved_regs, regno, val);
+		  }
+	      }
+	  }
+    }
+}
+
 void
 trad_frame_set_reg_value (struct trad_frame_cache *this_trad_cache,
 			  int regnum, LONGEST val)
@@ -148,6 +207,16 @@ trad_frame_set_reg_addr (struct trad_frame_cache *this_trad_cache,
   trad_frame_set_addr (this_trad_cache->prev_regs, regnum, addr);
 }
 
+void
+trad_frame_set_reg_regmap (struct trad_frame_cache *this_trad_cache,
+			   const void *regmap, CORE_ADDR addr, size_t size)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_trad_cache->this_frame);
+
+  trad_frame_set_regmap (this_trad_cache->prev_regs, gdbarch, regmap, addr,
+			 size);
+}
+
 void
 trad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs[],
 			int regnum)
diff --git a/gdb/trad-frame.h b/gdb/trad-frame.h
index a11a2c29c9..1fc1859996 100644
--- a/gdb/trad-frame.h
+++ b/gdb/trad-frame.h
@@ -45,6 +45,9 @@ void trad_frame_set_reg_realreg (struct trad_frame_cache *this_trad_cache,
 				 int regnum, int realreg);
 void trad_frame_set_reg_addr (struct trad_frame_cache *this_trad_cache,
 			      int regnum, CORE_ADDR addr);
+void trad_frame_set_reg_regmap (struct trad_frame_cache *this_trad_cache,
+				const void *regmap, CORE_ADDR addr,
+				size_t size);
 void trad_frame_set_reg_value (struct trad_frame_cache *this_cache,
 			       int regnum, LONGEST val);
 
@@ -96,6 +99,11 @@ void trad_frame_set_realreg (struct trad_frame_saved_reg this_saved_regs[],
 void trad_frame_set_addr (struct trad_frame_saved_reg this_trad_cache[],
 			  int regnum, CORE_ADDR addr);
 
+/* Encode registers in REGMAP are at address ADDR in the trad-frame.  */
+void trad_frame_set_regmap (struct trad_frame_saved_reg this_saved_regs[],
+			    struct gdbarch *gdbarch, const void *regmap,
+			    CORE_ADDR addr, size_t size);
+
 /* Mark REGNUM as unknown.  */
 void trad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs[],
 			     int regnum);
