diff --git a/gdb/features/i386/32bit-avx.c b/gdb/features/i386/32bit-avx.c
index 53a939b..bae025d 100644
--- a/gdb/features/i386/32bit-avx.c
+++ b/gdb/features/i386/32bit-avx.c
@@ -1,9 +1,13 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
   Original: 32bit-avx.xml.tmp */
 
+#ifdef GDBSERVER
+#include "tdesc.h"
+#else
 #include "defs.h"
 #include "osabi.h"
 #include "target-descriptions.h"
+#endif
 
 static int
 create_feature_i386_32bit_avx (struct target_desc *result, long regnum)
diff --git a/gdb/features/i386/32bit-avx512.c b/gdb/features/i386/32bit-avx512.c
index 9bbf392..ca15f8b 100644
--- a/gdb/features/i386/32bit-avx512.c
+++ b/gdb/features/i386/32bit-avx512.c
@@ -1,9 +1,13 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
   Original: 32bit-avx512.xml.tmp */
 
+#ifdef GDBSERVER
+#include "tdesc.h"
+#else
 #include "defs.h"
 #include "osabi.h"
 #include "target-descriptions.h"
+#endif
 
 static int
 create_feature_i386_32bit_avx512 (struct target_desc *result, long regnum)
diff --git a/gdb/features/i386/32bit-core.c b/gdb/features/i386/32bit-core.c
index c5f0fca..8db91ab 100644
--- a/gdb/features/i386/32bit-core.c
+++ b/gdb/features/i386/32bit-core.c
@@ -1,9 +1,13 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
   Original: 32bit-core.xml.tmp */
 
+#ifdef GDBSERVER
+#include "tdesc.h"
+#else
 #include "defs.h"
 #include "osabi.h"
 #include "target-descriptions.h"
+#endif
 
 static int
 create_feature_i386_32bit_core (struct target_desc *result, long regnum)
diff --git a/gdb/features/i386/32bit-linux.c b/gdb/features/i386/32bit-linux.c
index ff90d40..7535c55 100644
--- a/gdb/features/i386/32bit-linux.c
+++ b/gdb/features/i386/32bit-linux.c
@@ -1,9 +1,13 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
   Original: 32bit-linux.xml.tmp */
 
+#ifdef GDBSERVER
+#include "tdesc.h"
+#else
 #include "defs.h"
 #include "osabi.h"
 #include "target-descriptions.h"
+#endif
 
 static int
 create_feature_i386_32bit_linux (struct target_desc *result, long regnum)
diff --git a/gdb/features/i386/32bit-mpx.c b/gdb/features/i386/32bit-mpx.c
index 50b627e..9f1ae67 100644
--- a/gdb/features/i386/32bit-mpx.c
+++ b/gdb/features/i386/32bit-mpx.c
@@ -1,9 +1,13 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
   Original: 32bit-mpx.xml.tmp */
 
+#ifdef GDBSERVER
+#include "tdesc.h"
+#else
 #include "defs.h"
 #include "osabi.h"
 #include "target-descriptions.h"
+#endif
 
 static int
 create_feature_i386_32bit_mpx (struct target_desc *result, long regnum)
diff --git a/gdb/features/i386/32bit-pkeys.c b/gdb/features/i386/32bit-pkeys.c
index afb4958..86035ab 100644
--- a/gdb/features/i386/32bit-pkeys.c
+++ b/gdb/features/i386/32bit-pkeys.c
@@ -1,9 +1,13 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
   Original: 32bit-pkeys.xml.tmp */
 
+#ifdef GDBSERVER
+#include "tdesc.h"
+#else
 #include "defs.h"
 #include "osabi.h"
 #include "target-descriptions.h"
+#endif
 
 static int
 create_feature_i386_32bit_pkeys (struct target_desc *result, long regnum)
diff --git a/gdb/features/i386/32bit-sse.c b/gdb/features/i386/32bit-sse.c
index 08c3948..876c04d 100644
--- a/gdb/features/i386/32bit-sse.c
+++ b/gdb/features/i386/32bit-sse.c
@@ -1,9 +1,13 @@
 /* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
   Original: 32bit-sse.xml.tmp */
 
+#ifdef GDBSERVER
+#include "tdesc.h"
+#else
 #include "defs.h"
 #include "osabi.h"
 #include "target-descriptions.h"
+#endif
 
 static int
 create_feature_i386_32bit_sse (struct target_desc *result, long regnum)
diff --git a/gdb/gdbserver/linux-x86-tdesc.c b/gdb/gdbserver/linux-x86-tdesc.c
index e294a98..f247a3c 100644
--- a/gdb/gdbserver/linux-x86-tdesc.c
+++ b/gdb/gdbserver/linux-x86-tdesc.c
@@ -18,8 +18,17 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "server.h"
+#include "tdesc.h"
 #include "linux-x86-tdesc.h"
 
+#include "../features/i386/32bit-core.c"
+#include "../features/i386/32bit-linux.c"
+#include "../features/i386/32bit-sse.c"
+#include "../features/i386/32bit-avx.c"
+#include "../features/i386/32bit-avx512.c"
+#include "../features/i386/32bit-mpx.c"
+#include "../features/i386/32bit-pkeys.c"
+
 #if defined __i386__ || !defined IN_PROCESS_AGENT
 /* Defined in auto-generated file i386-linux.c.  */
 void init_registers_i386_linux (void);
@@ -63,15 +72,6 @@ initialize_low_tdesc ()
   init_registers_i386_avx_mpx_linux ();
   init_registers_i386_avx_avx512_linux ();
   init_registers_i386_avx_mpx_avx512_pku_linux ();
-
-  i386_tdescs[X86_TDESC_MMX] = tdesc_i386_mmx_linux;
-  i386_tdescs[X86_TDESC_SSE] = tdesc_i386_linux;
-  i386_tdescs[X86_TDESC_AVX] = tdesc_i386_avx_linux;
-  i386_tdescs[X86_TDESC_MPX] = tdesc_i386_mpx_linux;
-  i386_tdescs[X86_TDESC_AVX_MPX] = tdesc_i386_avx_mpx_linux;
-  i386_tdescs[X86_TDESC_AVX_AVX512] = tdesc_i386_avx_avx512_linux;
-  i386_tdescs[X86_TDESC_AVX_MPX_AVX512_PKU]
-    = tdesc_i386_avx_mpx_avx512_pku_linux;
 #endif
 }
 
@@ -82,7 +82,73 @@ i386_get_ipa_tdesc (int idx)
     internal_error (__FILE__, __LINE__,
 		    "unknown ipa tdesc index: %d", idx);
 
-  return i386_tdescs[idx];
+  struct target_desc **tdesc = (struct target_desc **) &i386_tdescs[idx];
+
+  if (*tdesc == NULL)
+    {
+      *tdesc = new target_desc ();
+      long regnum = 0;
+
+      regnum = create_feature_i386_32bit_core (*tdesc, regnum);
+
+      if (idx != X86_TDESC_MMX)
+	regnum = create_feature_i386_32bit_sse (*tdesc, regnum);
+
+      regnum = create_feature_i386_32bit_linux (*tdesc, regnum);
+
+      if (idx == X86_TDESC_AVX || idx == X86_TDESC_AVX_MPX
+	  || idx == X86_TDESC_AVX_AVX512
+	  || idx == X86_TDESC_AVX_MPX_AVX512_PKU)
+	regnum = create_feature_i386_32bit_avx (*tdesc, regnum);
+
+      if (idx == X86_TDESC_MPX || idx == X86_TDESC_AVX_MPX
+	  || idx == X86_TDESC_AVX_MPX_AVX512_PKU)
+	regnum = create_feature_i386_32bit_mpx (*tdesc, regnum);
+
+      if (idx == X86_TDESC_AVX_AVX512
+	  || idx == X86_TDESC_AVX_MPX_AVX512_PKU)
+	regnum = create_feature_i386_32bit_avx512 (*tdesc, regnum);
+
+      if (idx == X86_TDESC_AVX_MPX_AVX512_PKU)
+	regnum = create_feature_i386_32bit_pkeys (*tdesc, regnum);
+
+      init_target_desc (*tdesc);
+
+#ifndef IN_PROCESS_AGENT
+      static const char *expedite_regs_i386[] = { "ebp", "esp", "eip", NULL };
+      (*tdesc)->expedite_regs = expedite_regs_i386;
+
+      switch (idx)
+	{
+	case X86_TDESC_MMX:
+	  (*tdesc)->xmltarget = "i386-mmx-linux.xml";
+	  break;
+	case X86_TDESC_SSE:
+	  (*tdesc)->xmltarget = "i386-linux.xml";
+	  break;
+	case X86_TDESC_AVX:
+	  (*tdesc)->xmltarget = "i386-avx-linux.xml";
+	  break;
+	case X86_TDESC_MPX:
+	  (*tdesc)->xmltarget = "i386-mpx-linux.xml";
+	  break;
+	case X86_TDESC_AVX_MPX:
+	  (*tdesc)->xmltarget = "i386-avx-mpx-linux.xml";
+	  break;
+	case X86_TDESC_AVX_AVX512:
+	  (*tdesc)->xmltarget = "i386-avx-avx512-linux.xml";
+	  break;
+	case X86_TDESC_AVX_MPX_AVX512_PKU:
+	  (*tdesc)->xmltarget = "i386-avx-mpx-avx512-pku-linux.xml";
+	  break;
+	default:
+	  internal_error (__FILE__, __LINE__,
+			  "unknown ipa tdesc index: %d", idx);
+	}
+
+#endif
+    }
+  return *tdesc;;
 }
 
 #ifdef IN_PROCESS_AGENT
diff --git a/gdb/gdbserver/tdesc.c b/gdb/gdbserver/tdesc.c
index 1b1882e..686c76a 100644
--- a/gdb/gdbserver/tdesc.c
+++ b/gdb/gdbserver/tdesc.c
@@ -41,7 +41,7 @@ init_target_desc (struct target_desc *tdesc)
 
 #ifndef IN_PROCESS_AGENT
 
-static const struct target_desc default_description = { NULL, 0, NULL, NULL };
+static const struct target_desc default_description {};
 
 void
 copy_target_description (struct target_desc *dest,
@@ -61,5 +61,79 @@ current_target_desc (void)
 
   return current_process ()->tdesc;
 }
-
 #endif
+
+struct tdesc_type
+{};
+
+struct tdesc_feature *
+tdesc_create_feature (struct target_desc *tdesc, const char *name)
+{
+  return tdesc;
+}
+
+struct tdesc_type *
+tdesc_create_flags (struct tdesc_feature *feature, const char *name,
+		    int size)
+{
+  return NULL;
+}
+
+void
+tdesc_add_flag (struct tdesc_type *type, int start,
+		const char *flag_name)
+{}
+
+struct tdesc_type *
+tdesc_named_type (const struct tdesc_feature *feature, const char *id)
+{
+  return NULL;
+}
+
+void
+tdesc_create_reg (struct tdesc_feature *feature, const char *name,
+		  int regnum, int save_restore, const char *group,
+		  int bitsize, const char *type)
+{
+  struct target_desc *tdesc = (struct target_desc *) feature;
+
+  while (VEC_length (tdesc_reg_p, tdesc->reg_defs) < regnum)
+    {
+      struct reg *reg = XCNEW (struct reg);
+
+      reg->name = "";
+      reg->size = 0;
+      VEC_safe_push (tdesc_reg_p, tdesc->reg_defs, reg);
+    }
+
+  gdb_assert (regnum == 0
+	      || regnum == VEC_length (tdesc_reg_p, tdesc->reg_defs));
+
+  struct reg *reg = XCNEW (struct reg);
+
+  reg->name = name;
+  reg->size = bitsize;
+  VEC_safe_push (tdesc_reg_p, tdesc->reg_defs, reg);
+}
+
+struct tdesc_type *
+tdesc_create_vector (struct tdesc_feature *feature, const char *name,
+		     struct tdesc_type *field_type, int count)
+{
+  return NULL;
+}
+
+void
+tdesc_add_bitfield (struct tdesc_type *type, const char *field_name,
+		    int start, int end)
+{}
+
+void
+tdesc_add_field (struct tdesc_type *type, const char *field_name,
+		 struct tdesc_type *field_type)
+{}
+
+void
+tdesc_set_struct_size (struct tdesc_type *type, int size)
+{
+}
diff --git a/gdb/gdbserver/tdesc.h b/gdb/gdbserver/tdesc.h
index 424a2fd..2d4cbfa 100644
--- a/gdb/gdbserver/tdesc.h
+++ b/gdb/gdbserver/tdesc.h
@@ -38,13 +38,28 @@ struct target_desc
 #ifndef IN_PROCESS_AGENT
   /* An array of register names.  These are the "expedite" registers:
      registers whose values are sent along with stop replies.  */
-  const char **expedite_regs;
+  const char **expedite_regs = NULL;
 
   /* Defines what to return when looking for the "target.xml" file in
      response to qXfer:features:read.  Its contents can either be
      verbatim XML code (prefixed with a '@') or else the name of the
      actual XML file to be used in place of "target.xml".  */
-  const char *xmltarget;
+  const char *xmltarget = NULL;
+
+public:
+  target_desc ()
+    : reg_defs (NULL), registers_size (0)
+  {}
+
+  ~target_desc ()
+  {
+    int i;
+    struct reg *reg;
+
+    for (i = 0; VEC_iterate (tdesc_reg_p, reg_defs, i, reg); i++)
+      xfree (reg);
+    VEC_free (tdesc_reg_p, reg_defs);
+  }
 #endif
 };
 
@@ -62,4 +77,43 @@ void init_target_desc (struct target_desc *tdesc);
 
 const struct target_desc *current_target_desc (void);
 
+#ifndef IN_PROCESS_AGENT
+#endif
+
+#define tdesc_feature target_desc
+
+struct tdesc_type;
+
+struct tdesc_feature *tdesc_create_feature (struct target_desc *tdesc,
+					    const char *name);
+
+struct tdesc_type *tdesc_create_flags (struct tdesc_feature *feature,
+				       const char *name, int size);
+
+void tdesc_add_flag (struct tdesc_type *type, int start,
+		     const char *flag_name);
+
+struct tdesc_type *tdesc_named_type (const struct tdesc_feature *feature,
+				     const char *id);
+
+#define tdesc_create_union tdesc_named_type
+#define tdesc_create_struct tdesc_named_type
+
+void tdesc_add_field (struct tdesc_type *type, const char *field_name,
+		      struct tdesc_type *field_type);
+
+void tdesc_set_struct_size (struct tdesc_type *type, int size);
+
+void tdesc_add_bitfield (struct tdesc_type *type, const char *field_name,
+			 int start, int end);
+
+void tdesc_create_reg (struct tdesc_feature *feature, const char *name,
+		       int regnum, int save_restore, const char *group,
+		       int bitsize, const char *type);
+
+struct tdesc_type *tdesc_create_vector (struct tdesc_feature *feature,
+					const char *name,
+					struct tdesc_type *field_type,
+					int count);
+
 #endif /* TDESC_H */
diff --git a/gdb/regformats/regdat.sh b/gdb/regformats/regdat.sh
index 236cd93..66449cc 100755
--- a/gdb/regformats/regdat.sh
+++ b/gdb/regformats/regdat.sh
@@ -131,7 +131,6 @@ do
     echo "{"
     echo "  static struct target_desc tdesc_${name}_s;"
     echo "  struct target_desc *result = &tdesc_${name}_s;"
-    echo "  memset (result, 0, sizeof (*result));"
 
     continue
   elif test "${type}" = "xmltarget"; then
@@ -150,12 +149,9 @@ do
     echo "$0: $1 does not specify \`\`name''." 1>&2
     exit 1
   else
-    echo "  {struct reg *reg = XCNEW (struct reg);"
-    echo "  reg->name = \"${entry}\";"
-    echo "  reg->offset = ${offset};"
-    echo "  reg->size = ${type};"
-    echo "  VEC_safe_push (tdesc_reg_p, result->reg_defs, reg);"
-    echo "  };"
+    echo "  tdesc_create_reg ((struct tdesc_feature *) result, \"${entry}\","
+    echo "  0, 0, NULL, ${type}, NULL);"
+
     offset=`expr ${offset} + ${type}`
     i=`expr $i + 1`
   fi
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index 2b3083a..38e28d3 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -2166,9 +2166,13 @@ public:
 
   void visit (const target_desc *e) override
   {
+    printf_unfiltered ("#ifdef GDBSERVER\n");
+    printf_unfiltered ("#include \"tdesc.h\"\n");
+    printf_unfiltered ("#else\n");
     printf_unfiltered ("#include \"defs.h\"\n");
     printf_unfiltered ("#include \"osabi.h\"\n");
     printf_unfiltered ("#include \"target-descriptions.h\"\n");
+    printf_unfiltered ("#endif\n");
     printf_unfiltered ("\n");
   }
 
