diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index fb4d42c7baa..789f7dce224 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -432,6 +432,8 @@ SUBDIR_PYTHON_SRCS = \
 	python/py-threadevent.c \
 	python/py-tui.c \
 	python/py-type.c \
+	python/py-type-init.c \
+	python/py-float-format.c \
 	python/py-unwind.c \
 	python/py-utils.c \
 	python/py-value.c \
diff --git a/gdb/python/py-float-format.c b/gdb/python/py-float-format.c
new file mode 100644
index 00000000000..e517e410899
--- /dev/null
+++ b/gdb/python/py-float-format.c
@@ -0,0 +1,297 @@
+/* Accessibility of float format controls from inside the Python API
+
+   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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/>.  */
+
+#include "defs.h"
+#include "python-internal.h"
+#include "floatformat.h"
+
+/* Structure backing the float format Python interface. */
+
+struct float_format_object
+{
+  PyObject_HEAD
+  struct floatformat format;
+
+  struct floatformat *float_format ()
+  {
+    return &this->format;
+  }
+};
+
+/* Initializes the float format type and registers it with the Python interpreter. */
+
+int
+gdbpy_initialize_float_format (void)
+{
+  if (PyType_Ready (&float_format_object_type) < 0)
+    return -1;
+
+  if (gdb_pymodule_addobject (gdb_module, "FloatFormat",
+    (PyObject *) &float_format_object_type) < 0)
+    return -1;
+
+  return 0;
+}
+
+#define INSTANCE_FIELD_GETTER(getter_name, field_name, field_type, field_conv) \
+  static PyObject *                                                            \
+  getter_name (PyObject *self, void *closure)                                  \
+  {                                                                            \
+    float_format_object *ff = (float_format_object*) self;                     \
+    field_type value = ff->float_format ()->field_name;                        \
+    return field_conv (value);                                                 \
+  }
+
+#define INSTANCE_FIELD_SETTER(getter_name, field_name, field_type, field_conv) \
+  static int                                                                   \
+  getter_name (PyObject *self, PyObject* value, void *closure)                 \
+  {                                                                            \
+    field_type native_value;                                                   \
+    if (!field_conv (value, &native_value))                                    \
+      return -1;                                                               \
+    float_format_object *ff = (float_format_object*) self;                     \
+    ff->float_format ()->field_name = native_value;                            \
+    return 0;                                                                  \
+  }
+
+/* Converts from the intbit enum to a Python boolean. */
+
+static PyObject *
+intbit_to_py (enum floatformat_intbit intbit)
+{
+  gdb_assert (intbit == floatformat_intbit_yes || intbit == floatformat_intbit_no);
+  if (intbit == floatformat_intbit_no)
+    Py_RETURN_FALSE;
+  else
+    Py_RETURN_TRUE;
+}
+
+/* Converts from a Python boolean to the intbit enum. */
+
+static bool
+py_to_intbit (PyObject *object, enum floatformat_intbit *intbit)
+{
+  if (!PyObject_IsInstance (object, (PyObject*) &PyBool_Type))
+  {
+    PyErr_SetString (PyExc_TypeError, "intbit must be True or False");
+    return false;
+  }
+
+  *intbit = PyObject_IsTrue (object) ? floatformat_intbit_yes : floatformat_intbit_no;
+  return true;
+}
+
+/* Converts from a Python integer to a unsigned integer. */
+
+static bool
+py_to_unsigned_int (PyObject *object, unsigned int *val)
+{
+  if (!PyObject_IsInstance (object, (PyObject*) &PyLong_Type))
+  {
+    PyErr_SetString (PyExc_TypeError, "value must be an integer");
+    return false;
+  }
+
+  long native_val = PyLong_AsLong (object);
+  if (native_val > (long) UINT_MAX)
+  {
+    PyErr_SetString (PyExc_ValueError, "value is too large");
+    return false;
+  }
+  if (native_val < 0)
+  {
+    PyErr_SetString (PyExc_ValueError, "value must not be smaller than zero");
+    return false;
+  }
+
+  *val = (unsigned int) native_val;
+  return true;
+}
+
+/* Converts from a Python integer to a signed integer. */
+
+static bool
+py_to_int(PyObject *object, int *val)
+{
+  if(!PyObject_IsInstance(object, (PyObject*)&PyLong_Type))
+  {
+    PyErr_SetString(PyExc_TypeError, u8"value must be an integer");
+    return false;
+  }
+
+  long native_val = PyLong_AsLong(object);
+  if(native_val > (long)INT_MAX)
+  {
+    PyErr_SetString(PyExc_ValueError, u8"value is too large");
+    return false;
+  }
+
+  *val = (int)native_val;
+  return true;
+}
+
+INSTANCE_FIELD_GETTER (ffpy_get_totalsize, totalsize, unsigned int, PyLong_FromLong)
+INSTANCE_FIELD_GETTER (ffpy_get_sign_start, sign_start, unsigned int, PyLong_FromLong)
+INSTANCE_FIELD_GETTER (ffpy_get_exp_start, exp_start, unsigned int, PyLong_FromLong)
+INSTANCE_FIELD_GETTER (ffpy_get_exp_len, exp_len, unsigned int, PyLong_FromLong)
+INSTANCE_FIELD_GETTER (ffpy_get_exp_bias, exp_bias, int, PyLong_FromLong)
+INSTANCE_FIELD_GETTER (ffpy_get_exp_nan, exp_nan, unsigned int, PyLong_FromLong)
+INSTANCE_FIELD_GETTER (ffpy_get_man_start, man_start, unsigned int, PyLong_FromLong)
+INSTANCE_FIELD_GETTER (ffpy_get_man_len, man_len, unsigned int, PyLong_FromLong)
+INSTANCE_FIELD_GETTER (ffpy_get_intbit, intbit, enum floatformat_intbit, intbit_to_py)
+INSTANCE_FIELD_GETTER (ffpy_get_name, name, const char *, PyUnicode_FromString)
+
+INSTANCE_FIELD_SETTER (ffpy_set_totalsize, totalsize, unsigned int, py_to_unsigned_int)
+INSTANCE_FIELD_SETTER (ffpy_set_sign_start, sign_start, unsigned int, py_to_unsigned_int)
+INSTANCE_FIELD_SETTER (ffpy_set_exp_start, exp_start, unsigned int, py_to_unsigned_int)
+INSTANCE_FIELD_SETTER (ffpy_set_exp_len, exp_len, unsigned int, py_to_unsigned_int)
+INSTANCE_FIELD_SETTER (ffpy_set_exp_bias, exp_bias, int, py_to_int)
+INSTANCE_FIELD_SETTER (ffpy_set_exp_nan, exp_nan, unsigned int, py_to_unsigned_int)
+INSTANCE_FIELD_SETTER (ffpy_set_man_start, man_start, unsigned int, py_to_unsigned_int)
+INSTANCE_FIELD_SETTER (ffpy_set_man_len, man_len, unsigned int, py_to_unsigned_int)
+INSTANCE_FIELD_SETTER (ffpy_set_intbit, intbit, enum floatformat_intbit, py_to_intbit)
+
+/* Makes sure float formats created from Python always test as valid. */
+
+static int
+ffpy_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED,
+                   const void *from ATTRIBUTE_UNUSED)
+{
+  return 1;
+}
+
+/* Initializes new float format objects. */
+
+static int
+ffpy_init (PyObject *self,
+           PyObject *args ATTRIBUTE_UNUSED,
+           PyObject *kwds ATTRIBUTE_UNUSED)
+{
+  auto ff = (float_format_object*) self;
+  ff->format = floatformat ();
+  ff->float_format ()->name = "";
+  ff->float_format ()->is_valid = ffpy_always_valid;
+  return 0;
+}
+
+/* Retrieves a pointer to the underlying float format structure. */
+
+struct floatformat *
+float_format_object_as_float_format (PyObject *self)
+{
+  if (!PyObject_IsInstance (self, (PyObject*) &float_format_object_type))
+    return nullptr;
+  return ((float_format_object*) self)->float_format ();
+}
+
+static gdb_PyGetSetDef float_format_object_getset[] =
+{
+  { "totalsize", ffpy_get_totalsize, ffpy_set_totalsize,
+    "The total size of the floating point number, in bits.", nullptr },
+  { "sign_start", ffpy_get_sign_start, ffpy_set_sign_start,
+    "The bit offset of the sign bit.", nullptr },
+  { "exp_start", ffpy_get_exp_start, ffpy_set_exp_start,
+    "The bit offset of the start of the exponent.", nullptr },
+  { "exp_len", ffpy_get_exp_len, ffpy_set_exp_len,
+    "The size of the exponent, in bits.", nullptr },
+  { "exp_bias", ffpy_get_exp_bias, ffpy_set_exp_bias,
+    "Bias added to a \"true\" exponent to form the biased exponent.", nullptr },
+  { "exp_nan", ffpy_get_exp_nan, ffpy_set_exp_nan,
+    "Exponent value which indicates NaN.", nullptr },
+  { "man_start", ffpy_get_man_start, ffpy_set_man_start,
+    "The bit offset of the start of the mantissa.", nullptr },
+  { "man_len", ffpy_get_man_len, ffpy_set_man_len,
+    "The size of the mantissa, in bits.", nullptr },
+  { "intbit", ffpy_get_intbit, ffpy_set_intbit,
+    "Is the integer bit explicit or implicit?", nullptr },
+  { "name", ffpy_get_name, nullptr,
+    "Internal name for debugging.", nullptr },
+  { nullptr }
+};
+
+static PyMethodDef float_format_object_methods[] =
+{
+  { NULL }
+};
+
+static PyNumberMethods float_format_object_as_number = {
+  nullptr,             /* nb_add */
+  nullptr,             /* nb_subtract */
+  nullptr,             /* nb_multiply */
+  nullptr,             /* nb_remainder */
+  nullptr,             /* nb_divmod */
+  nullptr,             /* nb_power */
+  nullptr,             /* nb_negative */
+  nullptr,             /* nb_positive */
+  nullptr,             /* nb_absolute */
+  nullptr,             /* nb_nonzero */
+  nullptr,             /* nb_invert */
+  nullptr,             /* nb_lshift */
+  nullptr,             /* nb_rshift */
+  nullptr,             /* nb_and */
+  nullptr,             /* nb_xor */
+  nullptr,             /* nb_or */
+  nullptr,             /* nb_int */
+  nullptr,             /* reserved */
+  nullptr,             /* nb_float */
+};
+
+PyTypeObject float_format_object_type =
+{
+  PyVarObject_HEAD_INIT (NULL, 0)
+  "gdb.FloatFormat",              /*tp_name*/
+  sizeof (float_format_object),   /*tp_basicsize*/
+  0,                              /*tp_itemsize*/
+  nullptr,                        /*tp_dealloc*/
+  0,                              /*tp_print*/
+  nullptr,                        /*tp_getattr*/
+  nullptr,                        /*tp_setattr*/
+  nullptr,                        /*tp_compare*/
+  nullptr,                        /*tp_repr*/
+  &float_format_object_as_number, /*tp_as_number*/
+  nullptr,                        /*tp_as_sequence*/
+  nullptr,                        /*tp_as_mapping*/
+  nullptr,                        /*tp_hash */
+  nullptr,                        /*tp_call*/
+  nullptr,                        /*tp_str*/
+  nullptr,                        /*tp_getattro*/
+  nullptr,                        /*tp_setattro*/
+  nullptr,                        /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,             /*tp_flags*/
+  "GDB float format object",      /* tp_doc */
+  nullptr,                        /* tp_traverse */
+  nullptr,                        /* tp_clear */
+  nullptr,                        /* tp_richcompare */
+  0,                              /* tp_weaklistoffset */
+  nullptr,                        /* tp_iter */
+  nullptr,                        /* tp_iternext */
+  float_format_object_methods,    /* tp_methods */
+  nullptr,                        /* tp_members */
+  float_format_object_getset,     /* tp_getset */
+  nullptr,                        /* tp_base */
+  nullptr,                        /* tp_dict */
+  nullptr,                        /* tp_descr_get */
+  nullptr,                        /* tp_descr_set */
+  0,                              /* tp_dictoffset */
+  ffpy_init,                      /* tp_init */
+  nullptr,                        /* tp_alloc */
+  PyType_GenericNew,              /* tp_new */
+};
+
+
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index c278925531b..28a7c9a7873 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -704,6 +704,18 @@ objfile_to_objfile_object (struct objfile *objfile)
   return gdbpy_ref<>::new_reference (result);
 }
 
+struct objfile *
+objfile_object_to_objfile (PyObject *self)
+{
+  if (!PyObject_TypeCheck (self, &objfile_object_type))
+    return nullptr;
+
+  auto objfile_object = (struct objfile_object*) self;
+  OBJFPY_REQUIRE_VALID (objfile_object);
+
+  return objfile_object->objfile;
+}
+
 int
 gdbpy_initialize_objfile (void)
 {
diff --git a/gdb/python/py-type-init.c b/gdb/python/py-type-init.c
new file mode 100644
index 00000000000..f3b6813c3ad
--- /dev/null
+++ b/gdb/python/py-type-init.c
@@ -0,0 +1,388 @@
+/* Functionality for creating new types accessible from python.
+
+   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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/>.  */
+
+#include "defs.h"
+#include "python-internal.h"
+#include "gdbtypes.h"
+#include "floatformat.h"
+#include "objfiles.h"
+#include "gdbsupport/gdb_obstack.h"
+
+
+/* Copies a null-terminated string into an objfile's obstack. */
+
+static const char *
+copy_string (struct objfile *objfile, const char *py_str)
+{
+  unsigned int len = strlen (py_str);
+  return obstack_strndup (&objfile->per_bfd->storage_obstack,
+                          py_str, len);
+}
+
+/* Creates a new type and returns a new gdb.Type associated with it. */
+
+PyObject *
+gdbpy_init_type (PyObject *self, PyObject *args)
+{
+  PyObject *objfile_object;
+  enum type_code code;
+  int bit_length;
+  const char *py_name;
+
+  if(!PyArg_ParseTuple (args, "Oiis", &objfile_object, &code, &bit_length, &py_name))
+    return nullptr;
+
+  struct objfile* objfile = objfile_object_to_objfile (objfile_object);
+  if (objfile == nullptr)
+    return nullptr;
+
+  const char *name = copy_string (objfile, py_name);
+  struct type *type;
+  try
+  {
+    type = init_type (objfile, code, bit_length, name);
+    gdb_assert (type != nullptr);
+  }
+  catch (gdb_exception_error& ex)
+  {
+    GDB_PY_HANDLE_EXCEPTION (ex);
+  }
+
+  return type_to_type_object (type);
+}
+
+/* Creates a new integer type and returns a new gdb.Type associated with it. */
+
+PyObject *
+gdbpy_init_integer_type (PyObject *self, PyObject *args)
+{
+  PyObject *objfile_object;
+  int bit_size;
+  int unsigned_p;
+  const char *py_name;
+
+  if (!PyArg_ParseTuple (args, "Oips", &objfile_object, &bit_size, &unsigned_p, &py_name))
+    return nullptr;
+
+  struct objfile *objfile = objfile_object_to_objfile (objfile_object);
+  if (objfile == nullptr)
+    return nullptr;
+
+  const char *name = copy_string (objfile, py_name);
+  struct type *type;
+  try
+  {
+    type = init_integer_type (objfile, bit_size, unsigned_p, name);
+    gdb_assert (type != nullptr);
+  }
+  catch (gdb_exception_error& ex)
+  {
+    GDB_PY_HANDLE_EXCEPTION (ex);
+  }
+
+  return type_to_type_object(type);
+}
+
+/* Creates a new character type and returns a new gdb.Type associated with it. */
+
+PyObject *
+gdbpy_init_character_type (PyObject *self, PyObject *args)
+{
+
+  PyObject *objfile_object;
+  int bit_size;
+  int unsigned_p;
+  const char *py_name;
+
+  if (!PyArg_ParseTuple (args, "Oips", &objfile_object, &bit_size, &unsigned_p, &py_name))
+    return nullptr;
+
+  struct objfile *objfile = objfile_object_to_objfile (objfile_object);
+  if (objfile == nullptr)
+    return nullptr;
+
+  const char *name = copy_string (objfile, py_name);
+  struct type *type;
+  try
+  {
+    type = init_character_type (objfile, bit_size, unsigned_p, name);
+    gdb_assert (type != nullptr);
+  }
+  catch (gdb_exception_error& ex)
+  {
+    GDB_PY_HANDLE_EXCEPTION (ex);
+  }
+
+  return type_to_type_object (type);
+}
+
+/* Creates a new boolean type and returns a new gdb.Type associated with it. */
+
+PyObject *
+gdbpy_init_boolean_type (PyObject *self, PyObject *args)
+{
+
+  PyObject *objfile_object;
+  int bit_size;
+  int unsigned_p;
+  const char *py_name;
+
+  if (!PyArg_ParseTuple (args, "Oips", &objfile_object, &bit_size, &unsigned_p, &py_name))
+    return nullptr;
+
+  struct objfile *objfile = objfile_object_to_objfile (objfile_object);
+  if (objfile == nullptr)
+    return nullptr;
+
+  const char *name = copy_string (objfile, py_name);
+  struct type *type;
+  try
+  {
+    type = init_boolean_type (objfile, bit_size, unsigned_p, name);
+    gdb_assert (type != nullptr);
+  }
+  catch (gdb_exception_error& ex)
+  {
+    GDB_PY_HANDLE_EXCEPTION (ex);
+  }
+
+  return type_to_type_object (type);
+}
+
+/* Creates a new float type and returns a new gdb.Type associated with it. */
+
+PyObject *
+gdbpy_init_float_type (PyObject *self, PyObject *args)
+{
+  PyObject *objfile_object, *float_format_object;
+  const char *py_name;
+
+  if (!PyArg_ParseTuple (args, "OOs", &objfile_object, &float_format_object, &py_name))
+    return nullptr;
+
+  struct objfile *objfile = objfile_object_to_objfile (objfile_object);
+  if (objfile == nullptr)
+    return nullptr;
+
+  struct floatformat *local_ff = float_format_object_as_float_format (float_format_object);
+  if (local_ff == nullptr)
+    return nullptr;
+
+  /* Persist a copy of the format in the objfile's obstack. This guarantees that
+   * the format won't outlive the type being created from it and that changes
+   * made to the object used to create this type will not affect it after
+   * creation. */
+  auto ff = OBSTACK_CALLOC
+    (&objfile->objfile_obstack,
+     1,
+     struct floatformat);
+  memcpy (ff, local_ff, sizeof (struct floatformat));
+
+  /* We only support creating float types in the architecture's endianness, so
+   * make sure init_float_type sees the float format structure we need it to. */
+  enum bfd_endian endianness = gdbarch_byte_order (objfile->arch());
+  gdb_assert (endianness < BFD_ENDIAN_UNKNOWN);
+
+  const struct floatformat *per_endian[2] = { nullptr, nullptr };
+  per_endian[endianness] = ff;
+
+  const char *name = copy_string (objfile, py_name);
+  struct type *type;
+  try
+  {
+    type = init_float_type (objfile, -1, name, per_endian, endianness);
+    gdb_assert (type != nullptr);
+  }
+  catch (gdb_exception_error& ex)
+  {
+    GDB_PY_HANDLE_EXCEPTION (ex);
+  }
+
+  return type_to_type_object (type);
+}
+
+/* Creates a new decimal float type and returns a new gdb.Type associated with it. */
+
+PyObject *
+gdbpy_init_decfloat_type (PyObject *self, PyObject *args)
+{
+  PyObject *objfile_object;
+  int bit_length;
+  const char *py_name;
+
+  if (!PyArg_ParseTuple (args, "Ois", &objfile_object, &bit_length, &py_name))
+    return nullptr;
+
+  struct objfile *objfile = objfile_object_to_objfile (objfile_object);
+  if (objfile == nullptr)
+    return nullptr;
+
+  const char *name = copy_string (objfile, py_name);
+  struct type *type;
+  try
+  {
+    type = init_decfloat_type (objfile, bit_length, name);
+    gdb_assert (type != nullptr);
+  }
+  catch (gdb_exception_error& ex)
+  {
+    GDB_PY_HANDLE_EXCEPTION (ex);
+  }
+
+  return type_to_type_object (type);
+}
+
+/* Returns whether a given type can be used to create a complex type. */
+
+PyObject *
+gdbpy_can_create_complex_type (PyObject *self, PyObject *args)
+{
+
+  PyObject *type_object;
+
+  if (!PyArg_ParseTuple (args, "O", &type_object))
+    return nullptr;
+
+  struct type *type = type_object_to_type (type_object);
+  if (type == nullptr)
+    return nullptr;
+
+  bool can_create_complex;
+  try
+  {
+    can_create_complex = can_create_complex_type (type);
+  }
+  catch (gdb_exception_error& ex)
+  {
+    GDB_PY_HANDLE_EXCEPTION (ex);
+  }
+
+  if (can_create_complex)
+    Py_RETURN_TRUE;
+  else
+    Py_RETURN_FALSE;
+}
+
+/* Creates a new complex type and returns a new gdb.Type associated with it. */
+
+PyObject *
+gdbpy_init_complex_type (PyObject *self, PyObject *args)
+{
+
+  PyObject *type_object;
+  const char *py_name;
+
+  if (!PyArg_ParseTuple (args, "Os", &type_object, &py_name))
+    return nullptr;
+
+  struct type *type = type_object_to_type (type_object);
+  if (type == nullptr)
+    return nullptr;
+
+  obstack *obstack;
+  if (type->is_objfile_owned ())
+    obstack = &type->objfile_owner ()->objfile_obstack;
+  else
+    obstack = gdbarch_obstack (type->arch_owner ());
+
+  unsigned int len = strlen (py_name);
+  const char *name = obstack_strndup (obstack,
+                                      py_name,
+                                      len);
+  struct type *complex_type;
+  try
+  {
+    complex_type = init_complex_type (name, type);
+    gdb_assert (complex_type != nullptr);
+  }
+  catch (gdb_exception_error& ex)
+  {
+    GDB_PY_HANDLE_EXCEPTION (ex);
+  }
+
+  return type_to_type_object (complex_type);
+}
+
+/* Creates a new pointer type and returns a new gdb.Type associated with it. */
+
+PyObject *
+gdbpy_init_pointer_type (PyObject *self, PyObject *args)
+{
+  PyObject *objfile_object, *type_object;
+  int bit_length;
+  const char *py_name;
+
+  if (!PyArg_ParseTuple (args, "OOis", &objfile_object, &type_object, &bit_length, &py_name))
+    return nullptr;
+
+  struct objfile *objfile = objfile_object_to_objfile (objfile_object);
+  if (objfile == nullptr)
+    return nullptr;
+
+  struct type *type = type_object_to_type (type_object);
+  if (type == nullptr)
+    return nullptr;
+
+  const char *name = copy_string (objfile, py_name);
+  struct type *pointer_type;
+  try
+  {
+    pointer_type = init_pointer_type (objfile, bit_length, name, type);
+    gdb_assert (type != nullptr);
+  }
+  catch (gdb_exception_error& ex)
+  {
+    GDB_PY_HANDLE_EXCEPTION (ex);
+  }
+
+  return type_to_type_object (pointer_type);
+}
+
+/* Creates a new fixed point type and returns a new gdb.Type associated with it. */
+
+PyObject *
+gdbpy_init_fixed_point_type (PyObject *self, PyObject *args)
+{
+
+  PyObject *objfile_object;
+  int bit_length;
+  int unsigned_p;
+  const char* py_name;
+
+  if (!PyArg_ParseTuple (args, "Oips", &objfile_object, &bit_length, &unsigned_p, &py_name))
+    return nullptr;
+
+  struct objfile *objfile = objfile_object_to_objfile (objfile_object);
+  if (objfile == nullptr)
+    return nullptr;
+
+  const char *name = copy_string (objfile, py_name);
+  struct type *type;
+  try
+  {
+    type = init_fixed_point_type (objfile, bit_length, unsigned_p, name);
+    gdb_assert (type != nullptr);
+  }
+  catch (gdb_exception_error& ex)
+  {
+    GDB_PY_HANDLE_EXCEPTION (ex);
+  }
+
+  return type_to_type_object (type);
+}
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 06357cc8c0b..3877f8a7ca9 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -289,6 +289,8 @@ extern PyTypeObject frame_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("frame_object");
 extern PyTypeObject thread_object_type
     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("thread_object");
+extern PyTypeObject float_format_object_type
+    CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("float_format");
 
 /* Ensure that breakpoint_object_type is initialized and return true.  If
    breakpoint_object_type can't be initialized then set a suitable Python
@@ -431,6 +433,17 @@ gdb::unique_xmalloc_ptr<char> gdbpy_parse_command_name
 PyObject *gdbpy_register_tui_window (PyObject *self, PyObject *args,
 				     PyObject *kw);
 
+PyObject *gdbpy_init_type (PyObject *self, PyObject *args);
+PyObject *gdbpy_init_integer_type (PyObject *self, PyObject *args);
+PyObject *gdbpy_init_character_type (PyObject *self, PyObject *args);
+PyObject *gdbpy_init_boolean_type (PyObject *self, PyObject *args);
+PyObject *gdbpy_init_float_type (PyObject *self, PyObject *args);
+PyObject *gdbpy_init_decfloat_type (PyObject *self, PyObject *args);
+PyObject *gdbpy_can_create_complex_type (PyObject *self, PyObject *args);
+PyObject *gdbpy_init_complex_type (PyObject *self, PyObject *args);
+PyObject *gdbpy_init_pointer_type (PyObject *self, PyObject *args);
+PyObject *gdbpy_init_fixed_point_type (PyObject *self, PyObject *args);
+
 PyObject *symtab_and_line_to_sal_object (struct symtab_and_line sal);
 PyObject *symtab_to_symtab_object (struct symtab *symtab);
 PyObject *symbol_to_symbol_object (struct symbol *sym);
@@ -481,6 +494,8 @@ struct symtab *symtab_object_to_symtab (PyObject *obj);
 struct symtab_and_line *sal_object_to_symtab_and_line (PyObject *obj);
 frame_info_ptr frame_object_to_frame_info (PyObject *frame_obj);
 struct gdbarch *arch_object_to_gdbarch (PyObject *obj);
+struct objfile *objfile_object_to_objfile (PyObject *self);
+struct floatformat *float_format_object_as_float_format (PyObject *self);
 
 /* Convert Python object OBJ to a program_space pointer.  OBJ must be a
    gdb.Progspace reference.  Return nullptr if the gdb.Progspace is not
@@ -559,6 +574,8 @@ int gdbpy_initialize_micommands (void)
 void gdbpy_finalize_micommands ();
 int gdbpy_initialize_disasm ()
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
+int gdbpy_initialize_float_format ()
+  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 
 PyMODINIT_FUNC gdbpy_events_mod_func ();
 
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 4aa24421dec..1ed29ff4dea 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -2153,7 +2153,8 @@ do_start_initialization ()
       || gdbpy_initialize_membuf () < 0
       || gdbpy_initialize_connection () < 0
       || gdbpy_initialize_tui () < 0
-      || gdbpy_initialize_micommands () < 0)
+      || gdbpy_initialize_micommands () < 0
+      || gdbpy_initialize_float_format() < 0)
     return false;
 
 #define GDB_PY_DEFINE_EVENT_TYPE(name, py_name, doc, base)	\
@@ -2529,6 +2530,47 @@ Return current recording object." },
     "stop_recording () -> None.\n\
 Stop current recording." },
 
+  /* Type initialization functions. */
+  { "init_type", gdbpy_init_type, METH_VARARGS,
+    "init_type (objfile, type_code, bit_length, name) -> type\n\
+    Creates a new type with the given bit length and type code, owned\
+    by the given objfile." },
+  { "init_integer_type", gdbpy_init_integer_type, METH_VARARGS,
+    "init_integer_type (objfile, bit_length, unsigned, name) -> type\n\
+    Creates a new integer type with the given bit length and \
+    signedness, owned by the given objfile." },
+  { "init_character_type", gdbpy_init_character_type, METH_VARARGS,
+    "init_character_type (objfile, bit_length, unsigned, name) -> type\n\
+    Creates a new character type with the given bit length and \
+    signedness, owned by the given objfile." },
+  { "init_boolean_type", gdbpy_init_boolean_type, METH_VARARGS,
+    "init_boolean_type (objfile, bit_length, unsigned, name) -> type\n\
+    Creates a new boolean type with the given bit length and \
+    signedness, owned by the given objfile." },
+  { "init_float_type", gdbpy_init_float_type, METH_VARARGS,
+    "init_float_type (objfile, float_format, name) -> type\n\
+    Creates a new floating point type with the given bit length and \
+    format, owned by the given objfile." },
+  { "init_decfloat_type", gdbpy_init_decfloat_type, METH_VARARGS,
+    "init_decfloat_type (objfile, bit_length, name) -> type\n\
+    Creates a new decimal float type with the given bit length,\
+    owned by the given objfile." },
+  { "can_create_complex_type", gdbpy_can_create_complex_type, METH_VARARGS,
+    "can_create_complex_type (type) -> bool\n\
+     Returns whether a given type can form a new complex type." },
+  { "init_complex_type", gdbpy_init_complex_type, METH_VARARGS,
+    "init_complex_type (base_type, name) -> type\n\
+    Creates a new complex type whose components belong to the\
+    given type, owned by the given objfile." },
+  { "init_pointer_type", gdbpy_init_pointer_type, METH_VARARGS,
+    "init_pointer_type (objfile, target_type, bit_length, name) -> type\n\
+    Creates a new pointer type with the given bit length, pointing\
+    to the given target type, and owned by the given objfile." },
+ { "init_fixed_point_type", gdbpy_init_fixed_point_type, METH_VARARGS,
+   "init_fixed_point_type (objfile, bit_length, unsigned, name) -> type\n\
+   Creates a new fixed point type with the given bit length and\
+   signedness, owned by the given objfile." },
+
   { "lookup_type", (PyCFunction) gdbpy_lookup_type,
     METH_VARARGS | METH_KEYWORDS,
     "lookup_type (name [, block]) -> type\n\
