+2020-07-28  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * python/py-registers.c: Add 'user-regs.h' include.
+       (register_descriptor_iter_find): New function.
+       (register_descriptor_iterator_object_methods): New static global
+       methods array.
+       (register_descriptor_iterator_object_type): Add pointer to methods
+       array.
+
 2020-07-27  John Baldwin  <jhb@FreeBSD.org>
 
        * fbsd-nat.h: Include <osreldate.h>.  Define USE_SIGTRAP_SIGINFO
 
 The name of this register.
 @end defvar
 
+It is also possible to lookup a register descriptor based on its name
+using the following @code{gdb.RegisterDescriptorIterator} function:
+
+@defun RegisterDescriptorIterator.find (@var{name})
+Takes @var{name} as an argument, which must be a string, and returns a
+@code{gdb.RegisterDescriptor} for the register with that name, or
+@code{None} if there is no register with that name.
+@end defun
+
 Python code can also request from a @code{gdb.Architecture}
 information about the set of register groups available on a given
 architecture
 
 #include "disasm.h"
 #include "reggroups.h"
 #include "python-internal.h"
+#include "user-regs.h"
 #include <unordered_map>
 
 /* Token to access per-gdbarch data related to register descriptors.  */
   while (true);
 }
 
+/* Implement:
+
+   gdb.RegisterDescriptorIterator.find (self, name) -> gdb.RegisterDescriptor
+
+   Look up a descriptor for register with NAME.  If no matching register is
+   found then return None.  */
+
+static PyObject *
+register_descriptor_iter_find (PyObject *self, PyObject *args, PyObject *kw)
+{
+  static const char *keywords[] = { "name", NULL };
+  const char *register_name = NULL;
+
+  register_descriptor_iterator_object *iter_obj
+    = (register_descriptor_iterator_object *) self;
+  struct gdbarch *gdbarch = iter_obj->gdbarch;
+
+  if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s", keywords,
+                                       ®ister_name))
+    return NULL;
+
+  if (register_name != NULL && *register_name != '\0')
+    {
+      int regnum = user_reg_map_name_to_regnum (gdbarch, register_name,
+                                               strlen (register_name));
+      if (regnum >= 0)
+       return gdbpy_get_register_descriptor (gdbarch, regnum).release ();
+    }
+
+  Py_RETURN_NONE;
+}
+
 /* Initializes the new Python classes from this file in the gdb module.  */
 
 int
           (PyObject *) ®ister_descriptor_iterator_object_type));
 }
 
+static PyMethodDef register_descriptor_iterator_object_methods [] = {
+  { "find", (PyCFunction) register_descriptor_iter_find,
+    METH_VARARGS | METH_KEYWORDS,
+    "registers (name) -> gdb.RegisterDescriptor.\n\
+Return a register descriptor for the register NAME, or None if no register\n\
+with that name exists in this iterator." },
+  {NULL}  /* Sentinel */
+};
+
 PyTypeObject register_descriptor_iterator_object_type = {
   PyVarObject_HEAD_INIT (NULL, 0)
   "gdb.RegisterDescriptorIterator",            /*tp_name*/
   0,                             /*tp_weaklistoffset */
   gdbpy_register_descriptor_iter,        /*tp_iter */
   gdbpy_register_descriptor_iter_next,  /*tp_iternext */
-  0                              /*tp_methods */
+  register_descriptor_iterator_object_methods          /*tp_methods */
 };
 
 static gdb_PyGetSetDef gdbpy_register_descriptor_getset[] = {
 
         "    raise gdb.GdbError (\"miss-matched objects\")" \
         "\004" ] \
     "check names and objects match" 1
+
+# Ensure that the '.find' method on the iterator returns the same
+# Python object as we got from the iterator's list of descriptors.
+gdb_py_test_silent_cmd \
+    [multi_line \
+        "python" \
+        "def check_regs (arch, regs):" \
+        "   for r in (regs):" \
+        "     if (arch.registers ().find (r.name) != r):" \
+        "       raise gdb.GdbError (\"object miss-match\")" \
+        "end" ] \
+    "build check_obj function" 0
+gdb_py_test_silent_cmd \
+    "python check_regs (arch, arch.registers (\"general\"))" \
+    "ensure find gets expected descriptors" 1