This is an automated email from Gerrit.

Hsiangkai Wang (hsiang...@gmail.com) just uploaded a new patch set to Gerrit, 
which you can find at http://openocd.zylin.com/1381

-- gerrit

commit 16464448b926d2b1d2019ba68086ec7a60a4cc0b
Author: Hsiangkai Wang <hsiang...@gmail.com>
Date:   Sun May 5 15:09:02 2013 +0800

    gdb_server: support gdb target description
    
    * Add a parameter in .get_gdb_reg_list() to return different
      register lists as generating different register groups in
      target description.
    * Modify STRUCT REG to let gdb generate target description
      according to register information.
    
    The modified structure of register is
    
    struct reg {
            const char *name;
            uint32_t number;  /* for regnum="num" */
            struct reg_feature *feature;  /* for register group feature name */
            bool caller_save;  /* for save-restore="yes|no" */
            void *value;
            bool dirty;
            bool valid;
            uint32_t size;
            struct reg_data_type *reg_data_type;  /* for type="type" */
            enum reg_group group;  /* for group="general|float|vector" */
            void *arch_info;
            const struct reg_arch_type *type;
    };
    
    Change-Id: I6b24efa0eb65abd2838f4ac0ae36a4d9e80466d5
    Signed-off-by: Hsiangkai Wang <hsiang...@gmail.com>

diff --git a/src/rtos/linux.c b/src/rtos/linux.c
index 23b1a9e..c7eee70 100644
--- a/src/rtos/linux.c
+++ b/src/rtos/linux.c
@@ -226,7 +226,8 @@ static int linux_os_thread_reg_list(struct rtos *rtos,
                /*LOG_INFO("thread %lx current on core %x",thread_id,
                 * target->coreid);*/
                retval =
-                       target_get_gdb_reg_list(target, &reg_list, 
&reg_list_size);
+                       target_get_gdb_reg_list(target, &reg_list, 
&reg_list_size,
+                                       REG_CLASS_GENERAL);
 
                if (retval != ERROR_OK)
                        return retval;
@@ -498,7 +499,7 @@ int get_current(struct target *target, int create)
                int retval;
 
                if (target_get_gdb_reg_list(head->target, &reg_list,
-                               &reg_list_size) != ERROR_OK) {
+                               &reg_list_size, REG_CLASS_GENERAL) != ERROR_OK) 
{
                        free(buffer);
                        return ERROR_TARGET_FAILURE;
                }
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index cd72658..0d31f86 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -114,6 +114,11 @@ static int gdb_flash_program = 1;
  */
 static int gdb_report_data_abort;
 
+/* set if we are sending target descriptions to gdb
+ * via qXfer:features:read packet */
+/* disabled by default */
+static int gdb_use_target_description;
+
 static int gdb_last_signal(struct target *target)
 {
        switch (target->debug_reason) {
@@ -968,7 +973,8 @@ static int gdb_get_registers_packet(struct connection 
*connection,
        if ((target->rtos != NULL) && (ERROR_OK == 
rtos_get_gdb_reg_list(connection)))
                return ERROR_OK;
 
-       retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size);
+       retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size,
+                       REG_CLASS_GENERAL);
        if (retval != ERROR_OK)
                return gdb_error(connection, retval);
 
@@ -1027,7 +1033,8 @@ static int gdb_set_registers_packet(struct connection 
*connection,
                return ERROR_SERVER_REMOTE_CLOSED;
        }
 
-       retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size);
+       retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size,
+                       REG_CLASS_GENERAL);
        if (retval != ERROR_OK)
                return gdb_error(connection, retval);
 
@@ -1072,7 +1079,8 @@ static int gdb_get_register_packet(struct connection 
*connection,
        LOG_DEBUG("-");
 #endif
 
-       retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size);
+       retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size,
+                       REG_CLASS_ALL);
        if (retval != ERROR_OK)
                return gdb_error(connection, retval);
 
@@ -1109,7 +1117,8 @@ static int gdb_set_register_packet(struct connection 
*connection,
 
        LOG_DEBUG("-");
 
-       retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size);
+       retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size,
+                       REG_CLASS_ALL);
        if (retval != ERROR_OK)
                return gdb_error(connection, retval);
 
@@ -1670,6 +1679,276 @@ static int gdb_memory_map(struct connection *connection,
        return ERROR_OK;
 }
 
+static const char *gdb_get_reg_type_name(enum reg_type type)
+{
+       switch (type) {
+               case REG_TYPE_INT8:
+                       return "int8";
+               case REG_TYPE_INT16:
+                       return "int16";
+               case REG_TYPE_INT32:
+                       return "int32";
+               case REG_TYPE_INT64:
+                       return "int64";
+               case REG_TYPE_INT128:
+                       return "int128";
+               case REG_TYPE_UINT8:
+                       return "uin8";
+               case REG_TYPE_UINT16:
+                       return "uint16";
+               case REG_TYPE_UINT32:
+                       return "uint32";
+               case REG_TYPE_UINT64:
+                       return "uint64";
+               case REG_TYPE_UINT128:
+                       return "uint128";
+               case REG_TYPE_CODE_PTR:
+                       return "code_ptr";
+               case REG_TYPE_DATA_PTR:
+                       return "data_ptr";
+               case REG_TYPE_IEEE_SINGLE:
+                       return "ieee_single";
+               case REG_TYPE_IEEE_DOUBLE:
+                       return "ieee_double";
+               case REG_TYPE_ARCH_DEFINED:
+                       return "int"; /* return arbitrary string to avoid 
compile warning. */
+       }
+
+       return "int"; /* "int" as default value */
+}
+
+static const char *gdb_get_reg_group_name(enum reg_group group)
+{
+       switch (group) {
+               case REG_GROUP_GENERAL:
+                       return "general";
+               case REG_GROUP_FLOAT:
+                       return "float";
+               case REG_GROUP_VECTOR:
+                       return "vector";
+       }
+
+       return NULL;
+}
+
+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;
+}
+
+static int gdb_generate_target_description(struct target *target, char **tdesc)
+{
+       int retval = ERROR_OK;
+       enum target_register_class reg_class;
+       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");
+
+       for (reg_class = REG_CLASS_GENERAL; reg_class != REG_CLASS_END; 
reg_class++) {
+               retval = target_get_gdb_reg_list(target, &reg_list, 
&reg_list_size,
+                               reg_class);
+
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("get register list %d failed", reg_class);
+                       continue;
+               }
+
+               if (reg_list_size <= 0)
+                       continue;
+
+               /* generate target description according to register list */
+               xml_printf(&retval, tdesc, &pos, &size,
+                               "<feature name=\"%s\">\n",
+                               reg_list[0]->feature->name);
+
+               int i;
+               for (i = 0; i < reg_list_size ;i++) {
+
+                       const char *type_str;
+                       if (reg_list[i]->reg_data_type->type == 
REG_TYPE_ARCH_DEFINED) {
+                               /* generate <type... first, if there are 
architecture-defined types. */
+                               gdb_generate_reg_type_description(target, 
tdesc, &pos, &size,
+                                               reg_list[i]->reg_data_type);
+
+                               type_str = reg_list[i]->reg_data_type->id;
+                       } else {
+                               /* predefined type */
+                               type_str = gdb_get_reg_type_name(
+                                               
reg_list[i]->reg_data_type->type);
+                       }
+
+                       xml_printf(&retval, tdesc, &pos, &size,
+                                       "<reg name=\"%s\"", reg_list[i]->name);
+                       xml_printf(&retval, tdesc, &pos, &size,
+                                       " bitsize=\"%d\"", reg_list[i]->size);
+                       xml_printf(&retval, tdesc, &pos, &size,
+                                       " regnum=\"%d\"", reg_list[i]->number);
+                       if (reg_list[i]->caller_save)
+                               xml_printf(&retval, tdesc, &pos, &size,
+                                               " save-restore=\"yes\"");
+                       else
+                               xml_printf(&retval, tdesc, &pos, &size,
+                                               " save-restore=\"no\"");
+
+                       xml_printf(&retval, tdesc, &pos, &size,
+                                       " type=\"%s\"", type_str);
+
+                       const char *group_str;
+                       group_str = gdb_get_reg_group_name(reg_list[i]->group);
+                       if (group_str != NULL)
+                               xml_printf(&retval, tdesc, &pos, &size,
+                                               " group=\"%s\"", group_str);
+
+                       xml_printf(&retval, tdesc, &pos, &size,
+                                       "/>");
+               }
+
+               xml_printf(&retval, tdesc, &pos, &size,
+                               "</feature>");
+
+               free(reg_list);
+       }
+
+       xml_printf(&retval, tdesc, &pos, &size,
+                       "</target>\n");
+
+       return ERROR_OK;
+}
+
+static int gdb_get_target_description_chunk(struct target *target, char 
**chunk,
+               int32_t offset, uint32_t length)
+{
+       static char *tdesc = NULL;
+       static uint32_t tdesc_length = 0;
+
+       if (tdesc == NULL) {
+               gdb_generate_target_description(target, &tdesc);
+               tdesc_length = strlen(tdesc);
+       }
+
+       char transfer_type;
+
+       if (length < (tdesc_length - offset))
+               transfer_type = 'm';
+       else
+               transfer_type = 'l';
+
+       *chunk = malloc(length + 2);
+       (*chunk)[0] = transfer_type;
+       if (transfer_type == 'm') {
+               strncpy((*chunk) + 1, tdesc + offset, length);
+               (*chunk)[1 + length] = '\0';
+       } else {
+               strncpy((*chunk) + 1, tdesc + offset, tdesc_length - offset);
+               (*chunk)[1 + (tdesc_length - offset)] = '\0';
+
+               /* After gdb-server sends out last chunk, invalidate tdesc. */
+               free(tdesc);
+               tdesc = NULL;
+               tdesc_length = 0;
+       }
+
+       return ERROR_OK;
+}
+
 static int gdb_query_packet(struct connection *connection,
                char *packet, int packet_size)
 {
@@ -1744,9 +2023,10 @@ static int gdb_query_packet(struct connection 
*connection,
                        &buffer,
                        &pos,
                        &size,
-                       
"PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read-;QStartNoAckMode+",
+                       
"PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;QStartNoAckMode+",
                        (GDB_BUFFER_SIZE - 1),
-                       ((gdb_use_memory_map == 1) && (flash_get_bank_count() > 
0)) ? '+' : '-');
+                       ((gdb_use_memory_map == 1) && (flash_get_bank_count() > 
0)) ? '+' : '-',
+                       (gdb_use_target_description == 1) ? '+' : '-');
 
                if (retval != ERROR_OK) {
                        gdb_send_error(connection, 01);
@@ -1762,8 +2042,6 @@ static int gdb_query_packet(struct connection *connection,
                return gdb_memory_map(connection, packet, packet_size);
        else if (strncmp(packet, "qXfer:features:read:", 20) == 0) {
                char *xml = NULL;
-               int size = 0;
-               int pos = 0;
                int retval = ERROR_OK;
 
                int offset;
@@ -1778,17 +2056,12 @@ static int gdb_query_packet(struct connection 
*connection,
                        return ERROR_OK;
                }
 
-               if (strcmp(annex, "target.xml") != 0) {
-                       gdb_send_error(connection, 01);
-                       return ERROR_OK;
-               }
-
-               xml_printf(&retval,
-                       &xml,
-                       &pos,
-                       &size, \
-                       "l < target version=\"1.0\">\n < architecture > 
arm</architecture>\n</target>\n");
-
+               /* Target should prepare correct target description for annex.
+                * The first character of returned xml is 'm' or 'l'. 'm' for
+                * there are *more* chunks to transfer. 'l' for it is the *last*
+                * chunk of target description.
+                */
+               retval = gdb_get_target_description_chunk(target, &xml, offset, 
length);
                if (retval != ERROR_OK) {
                        gdb_error(connection, retval);
                        return retval;
@@ -2372,6 +2645,15 @@ COMMAND_HANDLER(handle_gdb_breakpoint_override_command)
        return ERROR_OK;
 }
 
+COMMAND_HANDLER(handle_gdb_target_description_command)
+{
+       if (CMD_ARGC != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_ENABLE(CMD_ARGV[0], gdb_use_target_description);
+       return ERROR_OK;
+}
+
 static const struct command_registration gdb_command_handlers[] = {
        {
                .name = "gdb_sync",
@@ -2424,6 +2706,13 @@ static const struct command_registration 
gdb_command_handlers[] = {
                        "to be used by gdb 'break' commands.",
                .usage = "('hard'|'soft'|'disable')"
        },
+       {
+               .name = "gdb_target_description",
+               .handler = handle_gdb_target_description_command,
+               .mode = COMMAND_CONFIG,
+               .help = "enable or disable target description",
+               .usage = "('enable'|'disable')"
+       },
        COMMAND_REGISTRATION_DONE
 };
 
diff --git a/src/target/arm.h b/src/target/arm.h
index e476404..df276d9 100644
--- a/src/target/arm.h
+++ b/src/target/arm.h
@@ -211,7 +211,8 @@ extern const struct command_registration 
arm_command_handlers[];
 
 int arm_arch_state(struct target *target);
 int arm_get_gdb_reg_list(struct target *target,
-               struct reg **reg_list[], int *reg_list_size);
+               struct reg **reg_list[], int *reg_list_size,
+               enum target_register_class reg_class);
 
 int arm_init_arch_info(struct target *target, struct arm *arm);
 
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
index b04404b..76e4c2e 100644
--- a/src/target/armv4_5.c
+++ b/src/target/armv4_5.c
@@ -1047,7 +1047,8 @@ const struct command_registration arm_command_handlers[] 
= {
 };
 
 int arm_get_gdb_reg_list(struct target *target,
-       struct reg **reg_list[], int *reg_list_size)
+       struct reg **reg_list[], int *reg_list_size,
+       enum target_register_class reg_class)
 {
        struct arm *arm = target_to_arm(target);
        int i;
diff --git a/src/target/armv7m.c b/src/target/armv7m.c
index a3c81dc..8a3ce14 100644
--- a/src/target/armv7m.c
+++ b/src/target/armv7m.c
@@ -259,7 +259,7 @@ static int armv7m_write_core_reg(struct target *target, 
struct reg *r,
  * hardware, so this also fakes a set of long-obsolete FPA registers that
  * are not used in EABI based software stacks.
  */
-int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], 
int *reg_list_size)
+int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], 
int *reg_list_size, enum target_register_class reg_class)
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
        int i;
diff --git a/src/target/armv7m.h b/src/target/armv7m.h
index c785d30..4d3faf5 100644
--- a/src/target/armv7m.h
+++ b/src/target/armv7m.h
@@ -195,7 +195,8 @@ int armv7m_mode_to_number(enum armv7m_mode mode);
 
 int armv7m_arch_state(struct target *target);
 int armv7m_get_gdb_reg_list(struct target *target,
-               struct reg **reg_list[], int *reg_list_size);
+               struct reg **reg_list[], int *reg_list_size,
+               enum target_register_class reg_class);
 
 int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m);
 
diff --git a/src/target/avr32_ap7k.c b/src/target/avr32_ap7k.c
index 749bf30..3c3a6bd 100644
--- a/src/target/avr32_ap7k.c
+++ b/src/target/avr32_ap7k.c
@@ -576,7 +576,7 @@ int avr32_ap7k_arch_state(struct target *target)
        return ERROR_OK;
 }
 
-int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg 
**reg_list[], int *reg_list_size)
+int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg 
**reg_list[], int *reg_list_size, enum target_register_class reg_class)
 {
 #if 0
        /* get pointers to arch-specific information */
diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c
index b9c8b4d..cc02c56 100644
--- a/src/target/dsp563xx.c
+++ b/src/target/dsp563xx.c
@@ -323,7 +323,8 @@ uint8_t gdb_reg_list_idx[] = {
 
 static int dsp563xx_get_gdb_reg_list(struct target *target,
        struct reg **reg_list[],
-       int *reg_list_size)
+       int *reg_list_size,
+       enum target_register_class reg_class)
 {
        int i;
        struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
diff --git a/src/target/mips32.c b/src/target/mips32.c
index 55c197b..023ddc1 100644
--- a/src/target/mips32.c
+++ b/src/target/mips32.c
@@ -173,7 +173,7 @@ static int mips32_write_core_reg(struct target *target, int 
num)
        return ERROR_OK;
 }
 
-int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], 
int *reg_list_size)
+int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], 
int *reg_list_size, enum target_register_class reg_class)
 {
        /* get pointers to arch-specific information */
        struct mips32_common *mips32 = target_to_mips32(target);
diff --git a/src/target/mips32.h b/src/target/mips32.h
index 0bdfc59..414ac47 100644
--- a/src/target/mips32.h
+++ b/src/target/mips32.h
@@ -241,7 +241,8 @@ int mips32_examine(struct target *target);
 int mips32_register_commands(struct command_context *cmd_ctx);
 
 int mips32_get_gdb_reg_list(struct target *target,
-               struct reg **reg_list[], int *reg_list_size);
+               struct reg **reg_list[], int *reg_list_size,
+               enum target_register_class reg_class);
 int mips32_checksum_memory(struct target *target, uint32_t address,
                uint32_t count, uint32_t *checksum);
 int mips32_blank_check_memory(struct target *target,
diff --git a/src/target/register.h b/src/target/register.h
index cf08e4a..0ec8ed1 100644
--- a/src/target/register.h
+++ b/src/target/register.h
@@ -26,12 +26,110 @@
 
 struct target;
 
+enum reg_type {
+       REG_TYPE_INT8,
+       REG_TYPE_INT16,
+       REG_TYPE_INT32,
+       REG_TYPE_INT64,
+       REG_TYPE_INT128,
+       REG_TYPE_UINT8,
+       REG_TYPE_UINT16,
+       REG_TYPE_UINT32,
+       REG_TYPE_UINT64,
+       REG_TYPE_UINT128,
+       REG_TYPE_CODE_PTR,
+       REG_TYPE_DATA_PTR,
+       REG_TYPE_IEEE_SINGLE,
+       REG_TYPE_IEEE_DOUBLE,
+       REG_TYPE_ARCH_DEFINED,
+};
+
+enum reg_group {
+       REG_GROUP_GENERAL,
+       REG_GROUP_FLOAT,
+       REG_GROUP_VECTOR,
+};
+
+struct reg_feature {
+       const char *name;
+};
+
+struct reg_data_type_vector {
+       struct reg_data_type *type;
+       uint32_t count;
+};
+
+struct reg_data_type_union_field {
+       const char *name;
+       struct reg_data_type *type;
+       struct reg_data_type_union_field *next;
+};
+
+struct reg_data_type_union {
+       struct reg_data_type_union_field *fields;
+};
+
+struct reg_data_type_bitfield {
+       uint32_t start;
+       uint32_t end;
+};
+
+struct reg_data_type_struct_field {
+       const char *name;
+       bool use_bitfields;
+       union {
+               struct reg_data_type_bitfield *bitfield;
+               struct reg_data_type *type;
+       };
+       struct reg_data_type_struct_field *next;
+};
+
+struct reg_data_type_struct {
+       uint32_t size;
+       struct reg_data_type_struct_field *fields;
+};
+
+struct reg_data_type_flags_field {
+       const char *name;
+       struct reg_data_type_bitfield *bitfield;
+       struct reg_data_type_flags_field *next;
+};
+
+struct reg_data_type_flags {
+       uint32_t size;
+       struct reg_data_type_flags_field *fields;
+};
+
+enum reg_data_type_class {
+       REG_TYPE_CLASS_VECTOR,
+       REG_TYPE_CLASS_UNION,
+       REG_TYPE_CLASS_STRUCT,
+       REG_TYPE_CLASS_FLAGS,
+};
+
+struct reg_data_type {
+       enum reg_type type;
+       const char *id;
+       enum reg_data_type_class type_class;
+       union {
+               struct reg_data_type_vector *reg_type_vector;
+               struct reg_data_type_union *reg_type_union;
+               struct reg_data_type_struct *reg_type_struct;
+               struct reg_data_type_flags *reg_type_flags;
+       };
+};
+
 struct reg {
        const char *name;
+       uint32_t number;
+       struct reg_feature *feature;
+       bool caller_save;
        void *value;
        bool dirty;
        bool valid;
        uint32_t size;
+       struct reg_data_type *reg_data_type;
+       enum reg_group group;
        void *arch_info;
        const struct reg_arch_type *type;
 };
diff --git a/src/target/target.c b/src/target/target.c
index ed1a2cc..3d9bda1 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -1028,9 +1028,10 @@ int target_remove_watchpoint(struct target *target,
 }
 
 int target_get_gdb_reg_list(struct target *target,
-               struct reg **reg_list[], int *reg_list_size)
+               struct reg **reg_list[], int *reg_list_size,
+               enum target_register_class reg_class)
 {
-       return target->type->get_gdb_reg_list(target, reg_list, reg_list_size);
+       return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, 
reg_class);
 }
 int target_step(struct target *target,
                int current, uint32_t address, int handle_breakpoints)
diff --git a/src/target/target.h b/src/target/target.h
index e6b931d..49770c3 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -114,6 +114,21 @@ struct backoff_timer {
        int count;
 };
 
+/* split target registers into multiple class */
+enum target_register_class {
+       REG_CLASS_ALL,
+       REG_CLASS_GENERAL,
+       REG_CLASS_CORE,
+       REG_CLASS_FPU,
+       REG_CLASS_ARCH_EXTENSION_1,
+       REG_CLASS_ARCH_EXTENSION_2,
+       REG_CLASS_ARCH_EXTENSION_3,
+       REG_CLASS_ARCH_EXTENSION_4,
+       REG_CLASS_ARCH_EXTENSION_5,
+       REG_CLASS_ARCH_EXTENSION_6,
+       REG_CLASS_END,
+};
+
 /* target_type.h contains the full definition of struct target_type */
 struct target {
        struct target_type *type;                       /* target type 
definition (name, access functions) */
@@ -399,7 +414,8 @@ int target_remove_watchpoint(struct target *target,
  * This routine is a wrapper for target->type->get_gdb_reg_list.
  */
 int target_get_gdb_reg_list(struct target *target,
-               struct reg **reg_list[], int *reg_list_size);
+               struct reg **reg_list[], int *reg_list_size,
+               enum target_register_class reg_class);
 
 /**
  * Step the target.
diff --git a/src/target/target_type.h b/src/target/target_type.h
index 5b72d84..9b5cdbb 100644
--- a/src/target/target_type.h
+++ b/src/target/target_type.h
@@ -101,7 +101,8 @@ struct target_type {
         * list, however it is after GDB is connected that monitor commands can
         * be run to properly initialize the target
         */
-       int (*get_gdb_reg_list)(struct target *target, struct reg **reg_list[], 
int *reg_list_size);
+       int (*get_gdb_reg_list)(struct target *target, struct reg **reg_list[],
+                       int *reg_list_size, enum target_register_class 
reg_class);
 
        /* target memory access
        * size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)

-- 

------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and 
their applications. This 200-page book is written by three acclaimed 
leaders in the field. The early access version is available now. 
Download your free book today! http://p.sf.net/sfu/neotech_d2d_may
_______________________________________________
OpenOCD-devel mailing list
OpenOCD-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to