+static int gdb_generate_reg_type_description(struct target *target,
+ char **tdesc, int *pos, int *size, struct reg_data_type *type)
+{
+ int retval = ERROR_OK;
+
+ if (type->type_class == REG_TYPE_CLASS_VECTOR) {
+ /* <vector id="id" type="type" count="count"/> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>\n",
+ type->id, type->reg_type_vector->type->id,
+ type->reg_type_vector->count);
+
+ } else if (type->type_class == REG_TYPE_CLASS_UNION) {
+ /* <union id="id">
+ * <field name="name" type="type"/> ...
+ * </union> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<union id=\"%s\">\n",
+ type->id);
+
+ struct reg_data_type_union_field *field;
+ field = type->reg_type_union->fields;
+ while (field != NULL) {
+ xml_printf(&retval, tdesc, pos, size,
+ "<field name=\"%s\" type=\"%s\"/>\n",
+ field->name, field->type->id);
+
+ field = field->next;
+ }
+
+ xml_printf(&retval, tdesc, pos, size,
+ "</union>\n");
+
+ } else if (type->type_class == REG_TYPE_CLASS_STRUCT) {
+ struct reg_data_type_struct_field *field;
+ field = type->reg_type_struct->fields;
+
+ if (field->use_bitfields) {
+ /* <struct id="id" size="size">
+ * <field name="name" start="start" end="end"/> ...
+ * </struct> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<struct id=\"%s\" size=\"%d\">\n",
+ type->id, type->reg_type_struct->size);
+ while (field != NULL) {
+ xml_printf(&retval, tdesc, pos, size,
+ "<field name=\"%s\" start=\"%d\" end=\"%d\"/>\n",
+ field->name, field->bitfield->start,
+ field->bitfield->end);
+
+ field = field->next;
+ }
+ } else {
+ /* <struct id="id">
+ * <field name="name" type="type"/> ...
+ * </struct> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<struct id=\"%s\">\n",
+ type->id);
+ while (field != NULL) {
+ xml_printf(&retval, tdesc, pos, size,
+ "<field name=\"%s\" type=\"%s\"/>\n",
+ field->name, field->type->id);
+
+ field = field->next;
+ }
+ }
+
+ xml_printf(&retval, tdesc, pos, size,
+ "</struct>\n");
+
+ } else if (type->type_class == REG_TYPE_CLASS_FLAGS) {
+ /* <flags id="id" size="size">
+ * <field name="name" start="start" end="end"/> ...
+ * </flags> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<flags id=\"%s\" size=\"%d\">\n",
+ type->id, type->reg_type_flags->size);
+
+ struct reg_data_type_flags_field *field;
+ field = type->reg_type_flags->fields;
+ while (field != NULL) {
+ xml_printf(&retval, tdesc, pos, size,
+ "<field name=\"%s\" start=\"%d\" end=\"%d\"/>\n",
+ field->name, field->bitfield->start, field->bitfield->end);
+
+ field = field->next;
+ }
+
+ xml_printf(&retval, tdesc, pos, size,
+ "</flags>\n");
+
+ }
+
+ return ERROR_OK;
+}
+
+/* Get a list of available target registers features. feature_list must
+ * be freed by caller.
+ */
+int get_reg_features_list(struct target *target, char **feature_list[], int *feature_list_size,
+ struct reg **reg_list, int reg_list_size)
+{
+ int tbl_sz = 0;
+
+ /* Start with only one element */
+ *feature_list = calloc(1, sizeof(char *));
+
+ for (int i = 0; i < reg_list_size; i++) {
+ if (reg_list[i]->exist == false)
+ continue;
+
+ if ((reg_list[i]->feature->name != NULL)
+ && (strcmp(reg_list[i]->feature->name, ""))) {
+ /* We found a feature, check if the feature is already in the
+ * table. If not, allocate a new entry for the table and
+ * put the new feature in it.
+ */
+ for (int j = 0; j < (tbl_sz + 1); j++) {
+ if (!((*feature_list)[j])) {
+ (*feature_list)[tbl_sz++] = strdup(reg_list[i]->feature->name);
+ *feature_list = realloc(*feature_list, sizeof(char *) * (tbl_sz + 1));
+ (*feature_list)[tbl_sz] = NULL;
+ break;
+ } else {
+ if (!strcmp((*feature_list)[j], reg_list[i]->feature->name))
+ break;
+ }
+ }
+ }
+ }
+
+ if (feature_list_size)
+ *feature_list_size = tbl_sz;
+
+ return ERROR_OK;
+}
+
+static int gdb_generate_target_description(struct target *target, char **tdesc)
+{
+ int retval = ERROR_OK;
+ struct reg **reg_list;
+ int reg_list_size;
+ int pos = 0;
+ int size = 0;
+
+ xml_printf(&retval, tdesc, &pos, &size,
+ "<?xml version=\"1.0\"?>\n"
+ "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">\n"
+ "<target version=\"1.0\">\n");
+
+ retval = target_get_gdb_reg_list(target, ®_list,
+ ®_list_size, REG_CLASS_ALL);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("get register list failed");
+ return ERROR_FAIL;