aboutsummaryrefslogtreecommitdiff
path: root/gdb/arm-tdep.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2007-02-08 21:00:36 +0000
committerDaniel Jacobowitz <drow@false.org>2007-02-08 21:00:36 +0000
commit123dc839145c04e57435369a9f2551a505ce0b33 (patch)
tree57ac12fe2ef50824ceba464d4c0988e89388327d /gdb/arm-tdep.c
parent1183581f7f529336f76eff7980fc7112871482ed (diff)
downloadgdb-123dc839145c04e57435369a9f2551a505ce0b33.zip
gdb-123dc839145c04e57435369a9f2551a505ce0b33.tar.gz
gdb-123dc839145c04e57435369a9f2551a505ce0b33.tar.bz2
* Makefile.in (arm-tdep.o, eval.o, target-descriptions.o)
(xml-tdesc.o): Update. * xml-support.c: Add a comment. (gdb_xml_enums_boolean): New variable. (gdb_xml_parse_attr_enum): Use strcasecmp. * xml-support.h (gdb_xml_enums_boolean): Declare. * xml-tdesc.c (struct tdesc_parsing_data): Record current_feature, next_regnum, and current_union. (tdesc_start_feature, tdesc_start_reg, tdesc_start_union) (tdesc_end_union, tdesc_start_field, tdesc_start_vector) (field_attributes, union_children, reg_attributes, union_attributes) (vector_attributes, feature_attributes, feature_children): New. (target_children): Make static. Add <feature>. (tdesc_elements): Make static. * target-descriptions.c (struct tdesc_reg, tdesc_reg_p, type_p) (struct tdesc_feature, tdesc_feature_p): New types. (struct target_desc): Add features member. (struct tdesc_arch_data, tdesc_data): New. (target_find_description): Clarify error message. Warn about ignored register descriptions. (tdesc_has_registers, tdesc_find_feature, tdesc_feature_name) (tdesc_named_type, tdesc_data_init, tdesc_data_alloc) (tdesc_data_cleanup, tdesc_numbered_register) (tdesc_numbered_register_choices, tdesc_find_register) (tdesc_register_name, tdesc_register_type) (tdesc_remote_register_number, tdesc_register_reggroup_p) (set_tdesc_pseudo_register_name, set_tdesc_pseudo_register_type) (set_tdesc_pseudo_register_reggroup_p, tdesc_use_registers) (tdesc_free_reg, tdesc_create_reg, tdesc_free_feature) (tdesc_create_feature, tdesc_record_type): New. (free_target_description): Free features. (_initialize_target_descriptions): Initialize tdesc_data. * arch-utils.c (default_remote_register_number): New. * arch-utils.h (default_remote_register_number): New prototype. * target-descriptions.h (set_tdesc_pseudo_register_name) (set_tdesc_pseudo_register_type, set_tdesc_pseudo_register_reggroup_p) (tdesc_use_registers, tdesc_data_alloc, tdesc_data_cleanup) (tdesc_numbered_register, tdesc_numbered_register_choices) (tdesc_has_registers, tdesc_find_feature, tdesc_feature_name) (tdesc_named_type, tdesc_create_feature, tdesc_record_type) (tdesc_create_reg): Declare. * gdbarch.sh (remote_register_number): New entry. * gdbarch.c, gdbarch.h: Regenerate. * remote.c (init_remote_state): Use gdbarch_remote_register_number. * features/gdb-target.dtd: Add feature, reg, vector, union, and field. * arm-tdep.c (arm_register_aliases): New. (arm_register_name_strings): Rename to... (arm_register_names): ...this. Make const. Delete the old version. (current_option, arm_register_byte): Delete. (set_disassembly_style): Simplify. Do not adjust arm_register_names. (value_of_arm_user_reg): New. (arm_gdbarch_init): Verify any described registers. Call tdesc_use_registers. Don't use arm_register_byte. Create aliases for standard register names. (_initialize_arm_tdep): Do not adjust arm_register_names. * user-regs.c (struct user_reg): Add baton member. (append_user_reg, user_reg_add_builtin, user_regs_init) (user_reg_add, value_of_user_reg): Use a baton for user register functions. * std-regs.c: Update. * user-regs.h (user_reg_read_ftype, user_reg_add_builtin) (user_reg_add): Add baton argument. * NEWS: Mention target description register support. * features/arm-core.xml, features/arm-fpa.xml: New. * eval.c (evaluate_subexp_standard): Allow ptype $register when the program is not running. * gdb.texinfo (-target-disconnect): Use @smallexample. (Requirements): Add anchor for Expat. Update description. (Target Descriptions): Mention Expat. (Target Description Format): Document new elements. Use @smallexample. (Predefined Target Types, Standard Target Features): New sections. * doc/gdbint.texinfo (Target Descriptions): New section. * gdb.xml/single-reg.xml, gdb.xml/tdesc-regs.exp, gdb.xml/core-only.xml, gdb.xml/extra-regs.xml: New files.
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r--gdb/arm-tdep.c199
1 files changed, 142 insertions, 57 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 7b92cd7..ab7b2e9 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -41,6 +41,8 @@
#include "dwarf2-frame.h"
#include "gdbtypes.h"
#include "prologue-value.h"
+#include "target-descriptions.h"
+#include "user-regs.h"
#include "arm-tdep.h"
#include "gdb/sim-arm.h"
@@ -103,13 +105,58 @@ static const char *arm_abi_string = "auto";
/* Number of different reg name sets (options). */
static int num_disassembly_options;
-/* We have more registers than the disassembler as gdb can print the value
- of special registers as well.
- The general register names are overwritten by whatever is being used by
- the disassembler at the moment. We also adjust the case of cpsr and fps. */
+/* The standard register names, and all the valid aliases for them. */
+static const struct
+{
+ const char *name;
+ int regnum;
+} arm_register_aliases[] = {
+ /* Basic register numbers. */
+ { "r0", 0 },
+ { "r1", 1 },
+ { "r2", 2 },
+ { "r3", 3 },
+ { "r4", 4 },
+ { "r5", 5 },
+ { "r6", 6 },
+ { "r7", 7 },
+ { "r8", 8 },
+ { "r9", 9 },
+ { "r10", 10 },
+ { "r11", 11 },
+ { "r12", 12 },
+ { "r13", 13 },
+ { "r14", 14 },
+ { "r15", 15 },
+ /* Synonyms (argument and variable registers). */
+ { "a1", 0 },
+ { "a2", 1 },
+ { "a3", 2 },
+ { "a4", 3 },
+ { "v1", 4 },
+ { "v2", 5 },
+ { "v3", 6 },
+ { "v4", 7 },
+ { "v5", 8 },
+ { "v6", 9 },
+ { "v7", 10 },
+ { "v8", 11 },
+ /* Other platform-specific names for r9. */
+ { "sb", 9 },
+ { "tr", 9 },
+ /* Special names. */
+ { "ip", 12 },
+ { "sp", 13 },
+ { "lr", 14 },
+ { "pc", 15 },
+ /* Names used by GCC (not listed in the ARM EABI). */
+ { "sl", 10 },
+ { "fp", 11 },
+ /* A special name from the older ATPCS. */
+ { "wr", 7 },
+};
-/* Initial value: Register names used in ARM's ISA documentation. */
-static char * arm_register_name_strings[] =
+static const char *const arm_register_names[] =
{"r0", "r1", "r2", "r3", /* 0 1 2 3 */
"r4", "r5", "r6", "r7", /* 4 5 6 7 */
"r8", "r9", "r10", "r11", /* 8 9 10 11 */
@@ -117,15 +164,12 @@ static char * arm_register_name_strings[] =
"f0", "f1", "f2", "f3", /* 16 17 18 19 */
"f4", "f5", "f6", "f7", /* 20 21 22 23 */
"fps", "cpsr" }; /* 24 25 */
-static char **arm_register_names = arm_register_name_strings;
/* Valid register name styles. */
static const char **valid_disassembly_styles;
/* Disassembly style to use. Default to "std" register names. */
static const char *disassembly_style;
-/* Index to that option in the opcodes table. */
-static int current_option;
/* This is used to keep the bfd arch_info in sync with the disassembly
style. */
@@ -1343,23 +1387,6 @@ arm_register_type (struct gdbarch *gdbarch, int regnum)
return builtin_type_uint32;
}
-/* Index within `registers' of the first byte of the space for
- register N. */
-
-static int
-arm_register_byte (int regnum)
-{
- if (regnum < ARM_F0_REGNUM)
- return regnum * INT_REGISTER_SIZE;
- else if (regnum < ARM_PS_REGNUM)
- return (NUM_GREGS * INT_REGISTER_SIZE
- + (regnum - ARM_F0_REGNUM) * FP_REGISTER_SIZE);
- else
- return (NUM_GREGS * INT_REGISTER_SIZE
- + NUM_FREGS * FP_REGISTER_SIZE
- + (regnum - ARM_FPS_REGNUM) * STATUS_REGISTER_SIZE);
-}
-
/* Map GDB internal REGNUM onto the Arm simulator register numbers. */
static int
arm_register_sim_regno (int regnum)
@@ -2461,32 +2488,13 @@ arm_register_name (int i)
static void
set_disassembly_style (void)
{
- const char *setname, *setdesc, *const *regnames;
- int numregs, j;
-
- /* Find the style that the user wants in the opcodes table. */
- int current = 0;
- numregs = get_arm_regnames (current, &setname, &setdesc, &regnames);
- while ((disassembly_style != setname)
- && (current < num_disassembly_options))
- get_arm_regnames (++current, &setname, &setdesc, &regnames);
- current_option = current;
+ int current;
- /* Fill our copy. */
- for (j = 0; j < numregs; j++)
- arm_register_names[j] = (char *) regnames[j];
-
- /* Adjust case. */
- if (isupper (*regnames[ARM_PC_REGNUM]))
- {
- arm_register_names[ARM_FPS_REGNUM] = "FPS";
- arm_register_names[ARM_PS_REGNUM] = "CPSR";
- }
- else
- {
- arm_register_names[ARM_FPS_REGNUM] = "fps";
- arm_register_names[ARM_PS_REGNUM] = "cpsr";
- }
+ /* Find the style that the user wants. */
+ for (current = 0; current < num_disassembly_options; current++)
+ if (disassembly_style == valid_disassembly_styles[current])
+ break;
+ gdb_assert (current < num_disassembly_options);
/* Synchronize the disassembler. */
set_arm_regname_option (current);
@@ -2544,6 +2552,13 @@ arm_write_pc (CORE_ADDR pc, ptid_t ptid)
write_register_pid (ARM_PS_REGNUM, val & ~(CORE_ADDR) 0x20, ptid);
}
}
+
+static struct value *
+value_of_arm_user_reg (struct frame_info *frame, const void *baton)
+{
+ const int *reg_p = baton;
+ return value_of_register (*reg_p, frame);
+}
static enum gdb_osabi
arm_elf_osabi_sniffer (bfd *abfd)
@@ -2580,6 +2595,65 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
struct gdbarch_list *best_arch;
enum arm_abi_kind arm_abi = arm_abi_global;
enum arm_float_model fp_model = arm_fp_model;
+ struct tdesc_arch_data *tdesc_data = NULL;
+ int i;
+
+ /* Check any target description for validity. */
+ if (tdesc_has_registers (info.target_desc))
+ {
+ /* For most registers we require GDB's default names; but also allow
+ the numeric names for sp / lr / pc, as a convenience. */
+ static const char *const arm_sp_names[] = { "r13", "sp", NULL };
+ static const char *const arm_lr_names[] = { "r14", "lr", NULL };
+ static const char *const arm_pc_names[] = { "r15", "pc", NULL };
+
+ const struct tdesc_feature *feature;
+ int i, valid_p;
+
+ feature = tdesc_find_feature (info.target_desc,
+ "org.gnu.gdb.arm.core");
+ if (feature == NULL)
+ return NULL;
+
+ tdesc_data = tdesc_data_alloc ();
+
+ valid_p = 1;
+ for (i = 0; i < ARM_SP_REGNUM; i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
+ arm_register_names[i]);
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ ARM_SP_REGNUM,
+ arm_sp_names);
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ ARM_LR_REGNUM,
+ arm_lr_names);
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ ARM_PC_REGNUM,
+ arm_pc_names);
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ ARM_PS_REGNUM, "cpsr");
+
+ if (!valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+
+ feature = tdesc_find_feature (info.target_desc,
+ "org.gnu.gdb.arm.fpa");
+ if (feature != NULL)
+ {
+ valid_p = 1;
+ for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
+ arm_register_names[i]);
+ if (!valid_p)
+ {
+ tdesc_data_cleanup (tdesc_data);
+ return NULL;
+ }
+ }
+ }
/* If we have an object to base this architecture on, try to determine
its ABI. */
@@ -2709,7 +2783,11 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
}
if (best_arch != NULL)
- return best_arch->gdbarch;
+ {
+ if (tdesc_data != NULL)
+ tdesc_data_cleanup (tdesc_data);
+ return best_arch->gdbarch;
+ }
tdep = xcalloc (1, sizeof (struct gdbarch_tdep));
gdbarch = gdbarch_alloc (&info, tdep);
@@ -2784,7 +2862,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_deprecated_fp_regnum (gdbarch, ARM_FP_REGNUM); /* ??? */
set_gdbarch_sp_regnum (gdbarch, ARM_SP_REGNUM);
set_gdbarch_pc_regnum (gdbarch, ARM_PC_REGNUM);
- set_gdbarch_deprecated_register_byte (gdbarch, arm_register_byte);
set_gdbarch_num_regs (gdbarch, NUM_GREGS + NUM_FREGS + NUM_SREGS);
set_gdbarch_register_type (gdbarch, arm_register_type);
@@ -2842,6 +2919,16 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
}
+ if (tdesc_data)
+ tdesc_use_registers (gdbarch, tdesc_data);
+
+ /* Add standard register aliases. We add aliases even for those
+ nanes which are used by the current architecture - it's simpler,
+ and does no harm, since nothing ever lists user registers. */
+ for (i = 0; i < ARRAY_SIZE (arm_register_aliases); i++)
+ user_reg_add (gdbarch, arm_register_aliases[i].name,
+ value_of_arm_user_reg, &arm_register_aliases[i].regnum);
+
return gdbarch;
}
@@ -2906,13 +2993,11 @@ _initialize_arm_tdep (void)
length = snprintf (rdptr, rest, "%s - %s\n", setname, setdesc);
rdptr += length;
rest -= length;
- /* Copy the default names (if found) and synchronize disassembler. */
+ /* When we find the default names, tell the disassembler to use
+ them. */
if (!strcmp (setname, "std"))
{
disassembly_style = setname;
- current_option = i;
- for (j = 0; j < numregs; j++)
- arm_register_names[j] = (char *) regnames[j];
set_arm_regname_option (i);
}
}