diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 057c14f..983a243 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2016-01-24  Marcin KoÅ›cielnicki  <koriakin@0x04.net>
+
+	* gdbarch.c: Regenerate.
+	* gdbarch.h: Regenerate.
+	* gdbarch.sh: Add write_guessed_tracepoint_pc hook.
+	* tracefile.c (tracefile_fetch_registers): When PC is a pseudo,
+	ask gdbarch to handle guessed PC via the new hook.
+
 2016-01-22  John Baldwin  <jhb@FreeBSD.org>
 
 	* fbsd-nat.c (fbsd_pid_to_str): Adjust string format.
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 4143744..21942b0 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -181,6 +181,7 @@ struct gdbarch
   int char_signed;
   gdbarch_read_pc_ftype *read_pc;
   gdbarch_write_pc_ftype *write_pc;
+  gdbarch_write_guessed_tracepoint_pc_ftype *write_guessed_tracepoint_pc;
   gdbarch_virtual_frame_pointer_ftype *virtual_frame_pointer;
   gdbarch_pseudo_register_read_ftype *pseudo_register_read;
   gdbarch_pseudo_register_read_value_ftype *pseudo_register_read_value;
@@ -523,6 +524,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
     gdbarch->char_signed = 1;
   /* Skip verify of read_pc, has predicate.  */
   /* Skip verify of write_pc, has predicate.  */
+  /* Skip verify of write_guessed_tracepoint_pc, has predicate.  */
   /* Skip verify of virtual_frame_pointer, invalid_p == 0 */
   /* Skip verify of pseudo_register_read, has predicate.  */
   /* Skip verify of pseudo_register_read_value, has predicate.  */
@@ -1402,6 +1404,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: vtable_function_descriptors = %s\n",
                       plongest (gdbarch->vtable_function_descriptors));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_write_guessed_tracepoint_pc_p() = %d\n",
+                      gdbarch_write_guessed_tracepoint_pc_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: write_guessed_tracepoint_pc = <%s>\n",
+                      host_address_to_string (gdbarch->write_guessed_tracepoint_pc));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_write_pc_p() = %d\n",
                       gdbarch_write_pc_p (gdbarch));
   fprintf_unfiltered (file,
@@ -1821,6 +1829,30 @@ set_gdbarch_write_pc (struct gdbarch *gdbarch,
   gdbarch->write_pc = write_pc;
 }
 
+int
+gdbarch_write_guessed_tracepoint_pc_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->write_guessed_tracepoint_pc != NULL;
+}
+
+void
+gdbarch_write_guessed_tracepoint_pc (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR val)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->write_guessed_tracepoint_pc != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_write_guessed_tracepoint_pc called\n");
+  gdbarch->write_guessed_tracepoint_pc (regcache, val);
+}
+
+void
+set_gdbarch_write_guessed_tracepoint_pc (struct gdbarch *gdbarch,
+                                         gdbarch_write_guessed_tracepoint_pc_ftype write_guessed_tracepoint_pc)
+{
+  gdbarch->write_guessed_tracepoint_pc = write_guessed_tracepoint_pc;
+}
+
 void
 gdbarch_virtual_frame_pointer (struct gdbarch *gdbarch, CORE_ADDR pc, int *frame_regnum, LONGEST *frame_offset)
 {
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 3fadcd1..9e24d15 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -239,6 +239,12 @@ typedef void (gdbarch_write_pc_ftype) (struct regcache *regcache, CORE_ADDR val)
 extern void gdbarch_write_pc (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR val);
 extern void set_gdbarch_write_pc (struct gdbarch *gdbarch, gdbarch_write_pc_ftype *write_pc);
 
+extern int gdbarch_write_guessed_tracepoint_pc_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_write_guessed_tracepoint_pc_ftype) (struct regcache *regcache, CORE_ADDR val);
+extern void gdbarch_write_guessed_tracepoint_pc (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR val);
+extern void set_gdbarch_write_guessed_tracepoint_pc (struct gdbarch *gdbarch, gdbarch_write_guessed_tracepoint_pc_ftype *write_guessed_tracepoint_pc);
+
 /* Function for getting target's idea of a frame pointer.  FIXME: GDB's
    whole scheme for dealing with "frames" and "frame pointers" needs a
    serious shakedown. */
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 4ac6b90..b67ea72 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -417,6 +417,7 @@ v:int:char_signed:::1:-1:1
 #
 F:CORE_ADDR:read_pc:struct regcache *regcache:regcache
 F:void:write_pc:struct regcache *regcache, CORE_ADDR val:regcache, val
+F:void:write_guessed_tracepoint_pc:struct regcache *regcache, CORE_ADDR val:regcache, val
 # Function for getting target's idea of a frame pointer.  FIXME: GDB's
 # whole scheme for dealing with "frames" and "frame pointers" needs a
 # serious shakedown.
diff --git a/gdb/tracefile.c b/gdb/tracefile.c
index fef4ed9..7c2649d 100644
--- a/gdb/tracefile.c
+++ b/gdb/tracefile.c
@@ -396,16 +396,18 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
      as the address of the tracepoint.  */
   pc_regno = gdbarch_pc_regnum (gdbarch);
 
-  /* XXX This guessing code below only works if the PC register isn't
-     a pseudo-register.  The value of a pseudo-register isn't stored
-     in the (non-readonly) regcache -- instead it's recomputed
-     (probably from some other cached raw register) whenever the
-     register is read.  This guesswork should probably move to some
-     higher layer.  */
-  if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
+  if (pc_regno < 0)
     return;
 
-  if (regno == -1 || regno == pc_regno)
+  /* We try to guess PC if:
+
+     1) We want all registers, or
+     2) PC is a real register, and we want exactly it, or
+     3) PC is a pseudo register (we don't know which real register it
+        corresponds to, so let's try to play safe).  */
+
+  if (regno == -1 || regno == pc_regno ||
+      pc_regno >= gdbarch_num_regs (gdbarch))
     {
       struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
       gdb_byte *regs;
@@ -429,11 +431,23 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
 	      return;
 	    }
 
-	  regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
-	  store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
-				  gdbarch_byte_order (gdbarch),
-				  tp->base.loc->address);
-	  regcache_raw_supply (regcache, pc_regno, regs);
+	  if (pc_regno >= gdbarch_num_regs (gdbarch))
+	    {
+	      /* PC is a pseudo, let gdbarch deal with that.  If it doesn't
+	         know how, just bail.  */
+	      if (gdbarch_write_guessed_tracepoint_pc_p (gdbarch))
+	        gdbarch_write_guessed_tracepoint_pc (gdbarch, regcache,
+						     tp->base.loc->address);
+	    }
+	  else
+	    {
+	      /* PC is a real register.  */
+	      regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
+	      store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
+				      gdbarch_byte_order (gdbarch),
+				      tp->base.loc->address);
+	      regcache_raw_supply (regcache, pc_regno, regs);
+	    }
 	}
     }
 }
